FUTEX_WAKE_OP(2const)
β¨ FUTEX_WAKE_OP β fast user-space locking β¨
okay bestie, buckle up, we're doing futexes today and honestly?? this one is a bop. it lives in section 2const of the manual (yes, FUTEX_WAKE_OP(2const), that's the whole title, she's a constant-flavored girlie π
).
π 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_WAKE_OP, uint32_t val,
uint32_t val2, uint32_t *uaddr2,
uint32_t val3);
π DESCRIPTION
so this op got added to the kernel to support some user-space situations where you've gotta juggle more than one futex at the same time. the most iconic example? the implementation of pthread_cond_signal(3), which needs to touch two futexes at once β the one doing the mutex thing and the one chilling in the wait queue tied to the condition variable. FUTEX_WAKE_OP lets those cases happen without setting off massive rates of contention and context switching. slay.
<tada>the vibe:</tada> FUTEX_WAKE_OP is equivalent to running the code below atomically and totally ordered with respect to other futex operations on either of the two futex words you handed over:
uint32_t oldval = *(uint32_t *) uaddr2;
*(uint32_t *) uaddr2 = oldval op oparg;
futex(uaddr, FUTEX_WAKE, val, 0, 0, 0);
if (oldval cmp cmparg)
futex(uaddr2, FUTEX_WAKE, val2, 0, 0, 0);
put another way, FUTEX_WAKE_OP does this whole routine:
- saves the original value of the futex word at
uaddr2and performs an operation that modifies the value of the futex atuaddr2β and this is an atomic read-modify-write memory access (i.e., it uses the atomic machine instructions of whatever architecture you're on, no shortcuts π€) - wakes up a maximum of
valwaiters on the futex for the futex word atuaddr; and - depending on how a test of the original value of the futex word at
uaddr2goes, wakes up a maximum ofval2waiters on the futex for the futex word atuaddr2.
the operation and the comparison you want performed are both encoded in the bits of the val3 argument. picture it bestie:
+---+---+-----------+-----------+
|op |cmp| oparg | cmparg |
+---+---+-----------+-----------+
4 4 12 12 <== # of bits
and in code form, the encoding is literally:
#define FUTEX_OP(op, oparg, cmp, cmparg) \
(((op & 0xf) << 28) | \
((cmp & 0xf) << 24) | \
((oparg & 0xfff) << 12) | \
(cmparg & 0xfff))
in the above, op and cmp are each one of the codes listed below π the oparg and cmparg components are literal numeric values, except as noted below.
πΈ the op component
FUTEX_OP_SETβ0β/* uaddr2 = oparg; */FUTEX_OP_ADDβ1β/* uaddr2 += oparg; */FUTEX_OP_ORβ2β/* uaddr2 |= oparg; */FUTEX_OP_ANDNβ3β/* uaddr2 &= ~oparg; */FUTEX_OP_XORβ4β/* uaddr2 ^= oparg; */
plus!! bitwise ORing the following value into op makes (1 << oparg) be used as the operand instead:
FUTEX_OP_ARG_SHIFTβ8β/* Use (1 << oparg) as operand */
π¦ the cmp field
FUTEX_OP_CMP_EQβ0β/* if (oldval == cmparg) wake */FUTEX_OP_CMP_NEβ1β/* if (oldval != cmparg) wake */FUTEX_OP_CMP_LTβ2β/* if (oldval < cmparg) wake */FUTEX_OP_CMP_LEβ3β/* if (oldval <= cmparg) wake */FUTEX_OP_CMP_GTβ4β/* if (oldval > cmparg) wake */FUTEX_OP_CMP_GEβ5β/* if (oldval >= cmparg) wake */
oh and, the return value of FUTEX_WAKE_OP is the sum of the number of waiters woken on the futex uaddr plus the number of waiters woken on the futex uaddr2. two futexes, one return value, it's giving efficiency π
π RETURN VALUE
on error, -1 gets returned, and errno is set to tell you what went wrong π
on success, FUTEX_WAKE_OP returns the total number of waiters that were woken up. that's the sum of the woken waiters on the two futexes for the futex words at uaddr and uaddr2. periodt.
π ERRORS
see futex(2).
EFAULTβuaddr2did not point to a valid user-space address.EINVALβuaddr2does not point to a valid object β meaning the address is not four-byte-aligned.EINVALβ the kernel detected an inconsistency between the user-space state atuaddrand the kernel state β that is, it detected a waiter which waits inFUTEX_LOCK_PI(2const)orFUTEX_LOCK_PI2(2const)onuaddr.
π« heads up bestie: both of those last two are EINVAL, so don't go assuming you can tell them apart by the error name alone. iykyk.
β STANDARDS
Linux. π§
π§ HISTORY
Linux 2.6.14. (ancient in timeline terms, still iconic in behavior terms β¨)
π SEE ALSO
and that's the whole page, bestie!! π«Ά this was Linux man-pages 6.20, dated 2025-09-21 β go forth and futex responsibly, mwah π ππΈ
π¦ where this page comes from
- arch rolling: man-pages 6.20-1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms