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 (date) "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)
|