1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
.\" Copyright, the authors of the Linux man-pages project
.\"
.\" %%%LICENSE_START(FREELY_REDISTRIBUTABLE)
.\" may be freely modified and distributed
.\" %%%LICENSE_END
.\"
.TH FUTEX_CMP_REQUEUE 2const 2025-05-30 "Linux man-pages (unreleased)"
.SH NAME
FUTEX_CMP_REQUEUE \- compare a futex, wake some waiters, and requeue others
.SH LIBRARY
Standard C library
.RI ( libc ,\~ \-lc )
.SH SYNOPSIS
.nf
.BR "#include <linux/futex.h>" " /* Definition of " FUTEX_* " constants */"
.BR "#include <sys/syscall.h>" " /* Definition of " SYS_* " constants */"
.B #include <unistd.h>
.P
.BI "long syscall(SYS_futex, uint32_t *" uaddr ", FUTEX_CMP_REQUEUE,"
.BI " uint32_t " val ", uint32_t " val2 ", uint32_t *" uaddr2 ,
.BI " uint32_t " val3 );
.fi
.SH DESCRIPTION
This operation first checks whether the location
.I uaddr
still contains the value
.IR val3 .
If not, the operation fails with the error
.BR EAGAIN .
Otherwise, the operation wakes up a maximum of
.I val
waiters that are waiting on the futex at
.IR uaddr .
If there are more than
.I val
waiters, then the remaining waiters are removed
from the wait queue of the source futex at
.I uaddr
and added to the wait queue of the target futex at
.IR uaddr2 .
The
.I val2
argument specifies an upper limit on the number of waiters
that are requeued to the futex at
.IR uaddr2 .
.P
.\" FIXME(Torvald) Is the following correct? Or is just the decision
.\" which threads to wake or requeue part of the atomic operation?
The load from
.I uaddr
is an atomic memory access (i.e., using atomic machine instructions of
the respective architecture).
This load, the comparison with
.IR val3 ,
and the requeueing of any waiters are performed atomically and totally
ordered with respect to other operations on the same futex word.
.\" Notes from a f2f conversation with Thomas Gleixner (Aug 2015): ###
.\" The operation is serialized with respect to operations on both
.\" source and target futex. No other waiter can enqueue itself
.\" for waiting and no other waiter can dequeue itself because of
.\" a timeout or signal.
.P
Typical values to specify for
.I val
are 0 or 1.
(Specifying
.I val
as
.B INT_MAX
is not useful,
because it would make the
.B FUTEX_CMP_REQUEUE
operation equivalent to
.BR FUTEX_WAKE (2const).)
The limit value specified via
.I val2
is typically either 1 or
.BR INT_MAX .
(Specifying
.I val2
as 0 is not useful,
because it would make the
.B FUTEX_CMP_REQUEUE
operation equivalent to
.BR FUTEX_WAKE (2const).)
.P
The
.B FUTEX_CMP_REQUEUE
operation was added as a replacement for the earlier
.BR FUTEX_REQUEUE (2const).
The difference is that the check of the value at
.I uaddr
can be used to ensure that requeueing happens only under certain
conditions, which allows race conditions to be avoided in certain use cases.
.\" But, as Rich Felker points out, there remain valid use cases for
.\" FUTEX_REQUEUE, for example, when the calling thread is requeuing
.\" the target(s) to a lock that the calling thread owns
.\" From: Rich Felker <dalias@libc.org>
.\" Date: Wed, 29 Oct 2014 22:43:17 -0400
.\" To: Darren Hart <dvhart@infradead.org>
.\" CC: libc-alpha@sourceware.org, ...
.\" Subject: Re: Add futex wrapper to glibc?
.P
Both
.BR FUTEX_REQUEUE (2const)
and
.B FUTEX_CMP_REQUEUE
can be used to avoid "thundering herd" wake-ups that could occur when using
.BR 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:
.P
.in +4n
.EX
lock(A)
while (!check_value(V)) {
unlock(A);
block_on(B);
lock(A);
};
unlock(A);
.EE
.in
.P
If a waker thread used
.BR 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.
.\"
.SH RETURN VALUE
On error,
\-1 is returned,
and
.I errno
is set to indicate the error.
.P
On success,
.B FUTEX_CMP_REQUEUE
returns the total number of waiters that were woken up or
requeued to the futex for the futex word at
.IR uaddr2 .
If this value is greater than
.IR val ,
then the difference is the number of waiters requeued to the futex for the
futex word at
.IR uaddr2 .
.SH ERRORS
See
.BR futex (2).
.TP
.B EAGAIN
The value pointed to by
.I uaddr
is not equal to the expected value
.IR val3 .
.TP
.B EFAULT
.I uaddr2
did not point to a valid user-space address.
.TP
.B EINVAL
.I uaddr2
does not point to a valid object\[em]that is,
the address is not four-byte-aligned.
.TP
.B EINVAL
The kernel detected an inconsistency between the user-space state at
.I uaddr
and the kernel state\[em]that is, it detected a waiter which waits in
.BR FUTEX_LOCK_PI (2const)
or
.BR FUTEX_LOCK_PI2 (2const)
on
.IR uaddr .
.SH STANDARDS
Linux.
.SH HISTORY
Linux 2.6.7.
.SH SEE ALSO
.BR futex (2)
|