.\" Copyright, the authors of the Linux man-pages project .\" .\" %%%LICENSE_START(FREELY_REDISTRIBUTABLE) .\" may be freely modified and distributed .\" %%%LICENSE_END .\" .TH FUTEX_WAKE_OP 2const 2025-05-30 "Linux man-pages 6.15" .SH NAME FUTEX_WAKE_OP \- fast user-space locking .SH LIBRARY Standard C library .RI ( libc ,\~ \-lc ) .SH SYNOPSIS .nf .BR "#include " " /* Definition of " FUTEX_* " constants */" .BR "#include " " /* Definition of " SYS_* " constants */" .B #include .P .BI "long syscall(SYS_futex, uint32_t *" uaddr ", FUTEX_WAKE_OP, uint32_t " val , .BI " uint32_t " val2 ", uint32_t *" uaddr2 , .BI " uint32_t " val3 ); .fi .SH DESCRIPTION .\" commit 4732efbeb997189d9f9b04708dc26bf8613ed721 .\" Author: Jakub Jelinek .\" Date: Tue Sep 6 15:16:25 2005 -0700 .\" FIXME. (Torvald) The glibc condvar implementation is currently being .\" revised (e.g., to not use an internal lock anymore). .\" It is probably more future-proof to remove this paragraph. .\" [Torvald, do you have an update here?] This operation was added to support some user-space use cases where more than one futex must be handled at the same time. The most notable example is the implementation of .BR pthread_cond_signal (3), which requires operations on two futexes, the one used to implement the mutex and the one used in the implementation of the wait queue associated with the condition variable. .B FUTEX_WAKE_OP allows such cases to be implemented without leading to high rates of contention and context switching. .P The .B FUTEX_WAKE_OP operation is equivalent to executing the following code atomically and totally ordered with respect to other futex operations on any of the two supplied futex words: .P .in +4n .EX uint32_t oldval = *(uint32_t *) uaddr2; *(uint32_t *) uaddr2 = oldval \f[I]op\f[] \f[I]oparg\f[]; futex(uaddr, FUTEX_WAKE, val, 0, 0, 0); if (oldval \f[I]cmp\f[] \f[I]cmparg\f[]) futex(uaddr2, FUTEX_WAKE, val2, 0, 0, 0); .EE .in .P In other words, .B FUTEX_WAKE_OP does the following: .IP \[bu] 3 saves the original value of the futex word at .I uaddr2 and performs an operation to modify the value of the futex at .IR uaddr2 ; this is an atomic read-modify-write memory access (i.e., using atomic machine instructions of the respective architecture) .IP \[bu] wakes up a maximum of .I val waiters on the futex for the futex word at .IR uaddr ; and .IP \[bu] dependent on the results of a test of the original value of the futex word at .IR uaddr2 , wakes up a maximum of .I val2 waiters on the futex for the futex word at .IR uaddr2 . .P The operation and comparison that are to be performed are encoded in the bits of the argument .IR val3 . Pictorially, the encoding is: .P .in +4n .EX +---+---+-----------+-----------+ |op |cmp| oparg | cmparg | +---+---+-----------+-----------+ 4 4 12 12 <== # of bits .EE .in .P Expressed in code, the encoding is: .P .in +4n .EX #define FUTEX_OP(op, oparg, cmp, cmparg) \[rs] (((op & 0xf) << 28) | \[rs] ((cmp & 0xf) << 24) | \[rs] ((oparg & 0xfff) << 12) | \[rs] (cmparg & 0xfff)) .EE .in .P In the above, .I op and .I cmp are each one of the codes listed below. The .I oparg and .I cmparg components are literal numeric values, except as noted below. .P The .I op component has one of the following values: .P .in +4n .EX FUTEX_OP_SET 0 /* uaddr2 = oparg; */ FUTEX_OP_ADD 1 /* uaddr2 += oparg; */ FUTEX_OP_OR 2 /* uaddr2 |= oparg; */ FUTEX_OP_ANDN 3 /* uaddr2 &= \[ti]oparg; */ FUTEX_OP_XOR 4 /* uaddr2 \[ha]= oparg; */ .EE .in .P In addition, bitwise ORing the following value into .I op causes .I (1\~<<\~oparg) to be used as the operand: .P .in +4n .EX FUTEX_OP_ARG_SHIFT 8 /* Use (1 << oparg) as operand */ .EE .in .P The .I cmp field is one of the following: .P .in +4n .EX 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 */ .EE .in .P The return value of .B FUTEX_WAKE_OP is the sum of the number of waiters woken on the futex .I uaddr plus the number of waiters woken on the futex .IR uaddr2 . .\" .SH RETURN VALUE On error, \-1 is returned, and .I errno is set to indicate the error. .P On success, .B FUTEX_WAKE_OP Returns the total number of waiters that were woken up. This is the sum of the woken waiters on the two futexes for the futex words at .I uaddr and .IR uaddr2 . .SH ERRORS See .BR futex (2). .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.14. .SH SEE ALSO .BR futex (2)