FUTEX_CMP_REQUEUE(2const)

NAME
FUTEX_CMP_REQUEUE - compare a futex, wake some waiters, and requeue others

LIBRARY
Standard C library (libc, -lc)

SYNOPSIS
#include <linux/futex.h>  /* Definition of FUTEX_* constants */
#include <sys/syscall.h>  /* Definition of SYS_* constants */
#include <unistd.h>

long syscall(SYS_futex, uint32_t *uaddr, FUTEX_CMP_REQUEUE,
             uint32_t val, uint32_t val2, uint32_t *uaddr2,
             uint32_t val3);

DESCRIPTION
This operation first checks whether the location uaddr still contains the value val3. If not, the operation fails with the error EAGAIN. Otherwise, the operation wakes up a maximum of val waiters that are waiting on the futex at uaddr. If there are more than val waiters, then the remaining waiters are removed from the wait queue of the source futex at uaddr and added to the wait queue of the target futex at uaddr2. The val2 argument specifies an upper limit on the number of waiters that are requeued to the futex at uaddr2.

The load from uaddr is an atomic memory access (i.e., using atomic machine instructions of the respective architecture). This load, the comparison with val3, and the requeueing of any waiters are performed atomically and totally ordered with respect to other operations on the same futex word.

Typical values to specify for val are 0 or 1. (Specifying val as INT_MAX is not useful, because it would make the FUTEX_CMP_REQUEUE operation equivalent to FUTEX_WAKE(2const).) The limit value specified via val2 is typically either 1 or INT_MAX. (Specifying val2 as 0 is not useful, because it would make the FUTEX_CMP_REQUEUE operation equivalent to FUTEX_WAKE(2const).)

The FUTEX_CMP_REQUEUE operation was added as a replacement for the earlier FUTEX_REQUEUE(2const). The difference is that the check of the value at uaddr can be used to ensure that requeueing happens only under certain conditions, which allows race conditions to be avoided in certain use cases.

Both FUTEX_REQUEUE(2const) and FUTEX_CMP_REQUEUE can be used to avoid "thundering herd" wake-ups that could occur when using FUTEX_WAKE(2const) in cases where all of the waiters that are woken need to acquire another futex. Consider the following scenario, where multiple waiter threads are waiting on B, a wait queue implemented using a futex:

    lock(A)
    while (!check_value(V)) {
        unlock(A);
        block_on(B);
        lock(A);
    };
    unlock(A);

If a waker thread used FUTEX_WAKE(2const), then all waiters waiting on B would be woken up, and they would all try to acquire lock A. However, waking all of the threads in this manner would be pointless because all except one of the threads would immediately block on lock A again. By contrast, a requeue operation wakes just one waiter and moves the other waiters to lock A, and when the woken waiter unlocks A then the next waiter can proceed.

RETURN VALUE
On error, -1 is returned, and errno is set to indicate the error.

On success, FUTEX_CMP_REQUEUE returns the total number of waiters that were woken up or requeued to the futex for the futex word at uaddr2. If this value is greater than val, then the difference is the number of waiters requeued to the futex for the futex word at uaddr2.

ERRORS
See futex(2).

EAGAIN
    The value pointed to by uaddr is not equal to the expected value val3.

EFAULT
    uaddr2 did not point to a valid user-space address.

EINVAL
    uaddr2 does not point to a valid object—that is, the address is not four-byte-aligned.

EINVAL
    The kernel detected an inconsistency between the user-space state at uaddr and the kernel state—that is, it detected a waiter which waits in FUTEX_LOCK_PI(2const) or FUTEX_LOCK_PI2(2const) on uaddr.

STANDARDS
Linux.

HISTORY
Linux 2.6.7.

SEE ALSO
futex(2)