summaryrefslogtreecommitdiffstats
path: root/man2/futex.2
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-24 04:52:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-24 04:52:22 +0000
commit3d08cd331c1adcf0d917392f7e527b3f00511748 (patch)
tree312f0d1e1632f48862f044b8bb87e602dcffb5f9 /man2/futex.2
parentAdding debian version 6.7-2. (diff)
downloadmanpages-3d08cd331c1adcf0d917392f7e527b3f00511748.tar.xz
manpages-3d08cd331c1adcf0d917392f7e527b3f00511748.zip
Merging upstream version 6.8.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'man2/futex.2')
-rw-r--r--man2/futex.21976
1 files changed, 0 insertions, 1976 deletions
diff --git a/man2/futex.2 b/man2/futex.2
deleted file mode 100644
index 2ff300b..0000000
--- a/man2/futex.2
+++ /dev/null
@@ -1,1976 +0,0 @@
-.\" Page by b.hubert
-.\" and Copyright (C) 2015, Thomas Gleixner <tglx@linutronix.de>
-.\" and Copyright (C) 2015, Michael Kerrisk <mtk.manpages@gmail.com>
-.\"
-.\" %%%LICENSE_START(FREELY_REDISTRIBUTABLE)
-.\" may be freely modified and distributed
-.\" %%%LICENSE_END
-.\"
-.\" Niki A. Rahimi (LTC Security Development, narahimi@us.ibm.com)
-.\" added ERRORS section.
-.\"
-.\" Modified 2004-06-17 mtk
-.\" Modified 2004-10-07 aeb, added FUTEX_REQUEUE, FUTEX_CMP_REQUEUE
-.\"
-.\" FIXME Still to integrate are some points from Torvald Riegel's mail of
-.\" 2015-01-23:
-.\" http://thread.gmane.org/gmane.linux.kernel/1703405/focus=7977
-.\"
-.\" FIXME Do we need to add some text regarding Torvald Riegel's 2015-01-24 mail
-.\" http://thread.gmane.org/gmane.linux.kernel/1703405/focus=1873242
-.\"
-.TH futex 2 2023-10-31 "Linux man-pages 6.7"
-.SH NAME
-futex \- fast user-space locking
-.SH LIBRARY
-Standard C library
-.RI ( libc ", " \-lc )
-.SH SYNOPSIS
-.nf
-.P
-.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 ", int " futex_op \
-", uint32_t " val ,
-.BI " const struct timespec *" timeout , \
-" \fR /* or: \fBuint32_t \fIval2\fP */"
-.BI " uint32_t *" uaddr2 ", uint32_t " val3 );
-.fi
-.P
-.IR Note :
-glibc provides no wrapper for
-.BR futex (),
-necessitating the use of
-.BR syscall (2).
-.SH DESCRIPTION
-The
-.BR futex ()
-system call provides a method for waiting until a certain condition becomes
-true.
-It is typically used as a blocking construct in the context of
-shared-memory synchronization.
-When using futexes, the majority of
-the synchronization operations are performed in user space.
-A user-space program employs the
-.BR futex ()
-system call only when it is likely that the program has to block for
-a longer time until the condition becomes true.
-Other
-.BR futex ()
-operations can be used to wake any processes or threads waiting
-for a particular condition.
-.P
-A futex is a 32-bit value\[em]referred to below as a
-.IR "futex word" \[em]whose
-address is supplied to the
-.BR futex ()
-system call.
-(Futexes are 32 bits in size on all platforms, including 64-bit systems.)
-All futex operations are governed by this value.
-In order to share a futex between processes,
-the futex is placed in a region of shared memory,
-created using (for example)
-.BR mmap (2)
-or
-.BR shmat (2).
-(Thus, the futex word may have different
-virtual addresses in different processes,
-but these addresses all refer to the same location in physical memory.)
-In a multithreaded program, it is sufficient to place the futex word
-in a global variable shared by all threads.
-.P
-When executing a futex operation that requests to block a thread,
-the kernel will block only if the futex word has the value that the
-calling thread supplied (as one of the arguments of the
-.BR futex ()
-call) as the expected value of the futex word.
-The loading of the futex word's value,
-the comparison of that value with the expected value,
-and the actual blocking will happen atomically and will be totally ordered
-with respect to concurrent operations performed by other threads
-on the same futex word.
-.\" Notes from Darren Hart (Dec 2015):
-.\" Totally ordered with respect futex operations refers to semantics
-.\" of the ACQUIRE/RELEASE operations and how they impact ordering of
-.\" memory reads and writes. The kernel futex operations are protected
-.\" by spinlocks, which ensure that all operations are serialized
-.\" with respect to one another.
-.\"
-.\" This is a lot to attempt to define in this document. Perhaps a
-.\" reference to linux/Documentation/memory-barriers.txt as a footnote
-.\" would be sufficient? Or perhaps for this manual, "serialized" would
-.\" be sufficient, with a footnote regarding "totally ordered" and a
-.\" pointer to the memory-barrier documentation?
-Thus, the futex word is used to connect the synchronization in user space
-with the implementation of blocking by the kernel.
-Analogously to an atomic
-compare-and-exchange operation that potentially changes shared memory,
-blocking via a futex is an atomic compare-and-block operation.
-.\" FIXME(Torvald Riegel):
-.\" Eventually we want to have some text in NOTES to satisfy
-.\" the reference in the following sentence
-.\" See NOTES for a detailed specification of
-.\" the synchronization semantics.
-.P
-One use of futexes is for implementing locks.
-The state of the lock (i.e., acquired or not acquired)
-can be represented as an atomically accessed flag in shared memory.
-In the uncontended case,
-a thread can access or modify the lock state with atomic instructions,
-for example atomically changing it from not acquired to acquired
-using an atomic compare-and-exchange instruction.
-(Such instructions are performed entirely in user mode,
-and the kernel maintains no information about the lock state.)
-On the other hand, a thread may be unable to acquire a lock because
-it is already acquired by another thread.
-It then may pass the lock's flag as a futex word and the value
-representing the acquired state as the expected value to a
-.BR futex ()
-wait operation.
-This
-.BR futex ()
-operation will block if and only if the lock is still acquired
-(i.e., the value in the futex word still matches the "acquired state").
-When releasing the lock, a thread has to first reset the
-lock state to not acquired and then execute a futex
-operation that wakes threads blocked on the lock flag used as a futex word
-(this can be further optimized to avoid unnecessary wake-ups).
-See
-.BR futex (7)
-for more detail on how to use futexes.
-.P
-Besides the basic wait and wake-up futex functionality, there are further
-futex operations aimed at supporting more complex use cases.
-.P
-Note that
-no explicit initialization or destruction is necessary to use futexes;
-the kernel maintains a futex
-(i.e., the kernel-internal implementation artifact)
-only while operations such as
-.BR FUTEX_WAIT ,
-described below, are being performed on a particular futex word.
-.\"
-.SS Arguments
-The
-.I uaddr
-argument points to the futex word.
-On all platforms, futexes are four-byte
-integers that must be aligned on a four-byte boundary.
-The operation to perform on the futex is specified in the
-.I futex_op
-argument;
-.I val
-is a value whose meaning and purpose depends on
-.IR futex_op .
-.P
-The remaining arguments
-.RI ( timeout ,
-.IR uaddr2 ,
-and
-.IR val3 )
-are required only for certain of the futex operations described below.
-Where one of these arguments is not required, it is ignored.
-.P
-For several blocking operations, the
-.I timeout
-argument is a pointer to a
-.I timespec
-structure that specifies a timeout for the operation.
-However, notwithstanding the prototype shown above, for some operations,
-the least significant four bytes of this argument are instead
-used as an integer whose meaning is determined by the operation.
-For these operations, the kernel casts the
-.I timeout
-value first to
-.IR "unsigned long",
-then to
-.IR uint32_t ,
-and in the remainder of this page, this argument is referred to as
-.I val2
-when interpreted in this fashion.
-.P
-Where it is required, the
-.I uaddr2
-argument is a pointer to a second futex word that is employed
-by the operation.
-.P
-The interpretation of the final integer argument,
-.IR val3 ,
-depends on the operation.
-.\"
-.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.\"
-.SS Futex operations
-The
-.I futex_op
-argument consists of two parts:
-a command that specifies the operation to be performed,
-bitwise ORed with zero or more options that
-modify the behaviour of the operation.
-The options that may be included in
-.I futex_op
-are as follows:
-.TP
-.BR FUTEX_PRIVATE_FLAG " (since Linux 2.6.22)"
-.\" commit 34f01cc1f512fa783302982776895c73714ebbc2
-This option bit can be employed with all futex operations.
-It tells the kernel that the futex is process-private and not shared
-with another process (i.e., it is being used for synchronization
-only between threads of the same process).
-This allows the kernel to make some additional performance optimizations.
-.\" I.e., It allows the kernel choose the fast path for validating
-.\" the user-space address and avoids expensive VMA lookups,
-.\" taking reference counts on file backing store, and so on.
-.IP
-As a convenience,
-.I <linux/futex.h>
-defines a set of constants with the suffix
-.B _PRIVATE
-that are equivalents of all of the operations listed below,
-.\" except the obsolete FUTEX_FD, for which the "private" flag was
-.\" meaningless
-but with the
-.B FUTEX_PRIVATE_FLAG
-ORed into the constant value.
-Thus, there are
-.BR FUTEX_WAIT_PRIVATE ,
-.BR FUTEX_WAKE_PRIVATE ,
-and so on.
-.TP
-.BR FUTEX_CLOCK_REALTIME " (since Linux 2.6.28)"
-.\" commit 1acdac104668a0834cfa267de9946fac7764d486
-This option bit can be employed only with the
-.BR FUTEX_WAIT_BITSET ,
-.BR FUTEX_WAIT_REQUEUE_PI ,
-(since Linux 4.5)
-.\" commit 337f13046ff03717a9e99675284a817527440a49
-.BR FUTEX_WAIT ,
-and
-(since Linux 5.14)
-.\" commit bf22a6976897977b0a3f1aeba6823c959fc4fdae
-.B FUTEX_LOCK_PI2
-operations.
-.IP
-If this option is set, the kernel measures the
-.I timeout
-against the
-.B CLOCK_REALTIME
-clock.
-.IP
-If this option is not set, the kernel measures the
-.I timeout
-against the
-.B CLOCK_MONOTONIC
-clock.
-.P
-The operation specified in
-.I futex_op
-is one of the following:
-.\"
-.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.\"
-.TP
-.BR FUTEX_WAIT " (since Linux 2.6.0)"
-.\" Strictly speaking, since some time in Linux 2.5.x
-This operation tests that the value at the
-futex word pointed to by the address
-.I uaddr
-still contains the expected value
-.IR val ,
-and if so, then sleeps waiting for a
-.B FUTEX_WAKE
-operation on the futex word.
-The load of the value of the futex word is an atomic memory
-access (i.e., using atomic machine instructions of the respective
-architecture).
-This load, the comparison with the expected value, and
-starting to sleep are performed atomically
-.\" FIXME: Torvald, I think we may need to add some explanation of
-.\" "totally ordered" here.
-and totally ordered
-with respect to other futex operations on the same futex word.
-If the thread starts to sleep,
-it is considered a waiter on this futex word.
-If the futex value does not match
-.IR val ,
-then the call fails immediately with the error
-.BR EAGAIN .
-.IP
-The purpose of the comparison with the expected value is to prevent lost
-wake-ups.
-If another thread changed the value of the futex word after the
-calling thread decided to block based on the prior value,
-and if the other thread executed a
-.B FUTEX_WAKE
-operation (or similar wake-up) after the value change and before this
-.B FUTEX_WAIT
-operation, then the calling thread will observe the
-value change and will not start to sleep.
-.IP
-If the
-.I timeout
-is not NULL, the structure it points to specifies a
-timeout for the wait.
-(This interval will be rounded up to the system clock granularity,
-and is guaranteed not to expire early.)
-The timeout is by default measured according to the
-.B CLOCK_MONOTONIC
-clock, but, since Linux 4.5, the
-.B CLOCK_REALTIME
-clock can be selected by specifying
-.B FUTEX_CLOCK_REALTIME
-in
-.IR futex_op .
-If
-.I timeout
-is NULL, the call blocks indefinitely.
-.IP
-.IR Note :
-for
-.BR FUTEX_WAIT ,
-.I timeout
-is interpreted as a
-.I relative
-value.
-This differs from other futex operations, where
-.I timeout
-is interpreted as an absolute value.
-To obtain the equivalent of
-.B FUTEX_WAIT
-with an absolute timeout, employ
-.B FUTEX_WAIT_BITSET
-with
-.I val3
-specified as
-.BR FUTEX_BITSET_MATCH_ANY .
-.IP
-The arguments
-.I uaddr2
-and
-.I val3
-are ignored.
-.\" FIXME . (Torvald) I think we should remove this. Or maybe adapt to a
-.\" different example.
-.\"
-.\" For
-.\" .BR futex (7),
-.\" this call is executed if decrementing the count gave a negative value
-.\" (indicating contention),
-.\" and will sleep until another process or thread releases
-.\" the futex and executes the
-.\" .B FUTEX_WAKE
-.\" operation.
-.\"
-.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.\"
-.TP
-.BR FUTEX_WAKE " (since Linux 2.6.0)"
-.\" Strictly speaking, since Linux 2.5.x
-This operation wakes at most
-.I val
-of the waiters that are waiting (e.g., inside
-.BR FUTEX_WAIT )
-on the futex word at the address
-.IR uaddr .
-Most commonly,
-.I val
-is specified as either 1 (wake up a single waiter) or
-.B INT_MAX
-(wake up all waiters).
-No guarantee is provided about which waiters are awoken
-(e.g., a waiter with a higher scheduling priority is not guaranteed
-to be awoken in preference to a waiter with a lower priority).
-.IP
-The arguments
-.IR timeout ,
-.IR uaddr2 ,
-and
-.I val3
-are ignored.
-.\" FIXME . (Torvald) I think we should remove this. Or maybe adapt to
-.\" a different example.
-.\"
-.\" For
-.\" .BR futex (7),
-.\" this is executed if incrementing the count showed that
-.\" there were waiters,
-.\" once the futex value has been set to 1
-.\" (indicating that it is available).
-.\"
-.\" How does "incrementing the count show that there were waiters"?
-.\"
-.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.\"
-.TP
-.BR FUTEX_FD " (from Linux 2.6.0 up to and including Linux 2.6.25)"
-.\" Strictly speaking, from Linux 2.5.x to Linux 2.6.25
-This operation creates a file descriptor that is associated with
-the futex at
-.IR uaddr .
-The caller must close the returned file descriptor after use.
-When another process or thread performs a
-.B FUTEX_WAKE
-on the futex word, the file descriptor indicates as being readable with
-.BR select (2),
-.BR poll (2),
-and
-.BR epoll (7)
-.IP
-The file descriptor can be used to obtain asynchronous notifications: if
-.I val
-is nonzero, then, when another process or thread executes a
-.BR FUTEX_WAKE ,
-the caller will receive the signal number that was passed in
-.IR val .
-.IP
-The arguments
-.IR timeout ,
-.IR uaddr2 ,
-and
-.I val3
-are ignored.
-.IP
-Because it was inherently racy,
-.B FUTEX_FD
-has been removed
-.\" commit 82af7aca56c67061420d618cc5a30f0fd4106b80
-from Linux 2.6.26 onward.
-.\"
-.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.\"
-.TP
-.BR FUTEX_REQUEUE " (since Linux 2.6.0)"
-This operation performs the same task as
-.B FUTEX_CMP_REQUEUE
-(see below), except that no check is made using the value in
-.IR val3 .
-(The argument
-.I val3
-is ignored.)
-.\"
-.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.\"
-.TP
-.BR FUTEX_CMP_REQUEUE " (since Linux 2.6.7)"
-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 .
-.IP
-.\" 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.
-.IP
-Typical values to specify for
-.I val
-are 0 or 1.
-(Specifying
-.B INT_MAX
-is not useful, because it would make the
-.B FUTEX_CMP_REQUEUE
-operation equivalent to
-.BR FUTEX_WAKE .)
-The limit value specified via
-.I val2
-is typically either 1 or
-.BR INT_MAX .
-(Specifying the argument as 0 is not useful, because it would make the
-.B FUTEX_CMP_REQUEUE
-operation equivalent to
-.BR FUTEX_WAIT .)
-.IP
-The
-.B FUTEX_CMP_REQUEUE
-operation was added as a replacement for the earlier
-.BR FUTEX_REQUEUE .
-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?
-.IP
-Both
-.B FUTEX_REQUEUE
-and
-.B FUTEX_CMP_REQUEUE
-can be used to avoid "thundering herd" wake-ups that could occur when using
-.B FUTEX_WAKE
-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:
-.IP
-.in +4n
-.EX
-lock(A)
-while (!check_value(V)) {
- unlock(A);
- block_on(B);
- lock(A);
-};
-unlock(A);
-.EE
-.in
-.IP
-If a waker thread used
-.BR FUTEX_WAKE ,
-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.
-.\"
-.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.\"
-.TP
-.BR FUTEX_WAKE_OP " (since Linux 2.6.14)"
-.\" commit 4732efbeb997189d9f9b04708dc26bf8613ed721
-.\" Author: Jakub Jelinek <jakub@redhat.com>
-.\" 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.
-.IP
-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:
-.IP
-.in +4n
-.EX
-uint32_t oldval = *(uint32_t *) uaddr2;
-*(uint32_t *) uaddr2 = oldval \fIop\fP \fIoparg\fP;
-futex(uaddr, FUTEX_WAKE, val, 0, 0, 0);
-if (oldval \fIcmp\fP \fIcmparg\fP)
- futex(uaddr2, FUTEX_WAKE, val2, 0, 0, 0);
-.EE
-.in
-.IP
-In other words,
-.B FUTEX_WAKE_OP
-does the following:
-.RS
-.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 .
-.RE
-.IP
-The operation and comparison that are to be performed are encoded
-in the bits of the argument
-.IR val3 .
-Pictorially, the encoding is:
-.IP
-.in +4n
-.EX
-+---+---+-----------+-----------+
-|op |cmp| oparg | cmparg |
-+---+---+-----------+-----------+
- 4 4 12 12 <== # of bits
-.EE
-.in
-.IP
-Expressed in code, the encoding is:
-.IP
-.in +4n
-.EX
-#define FUTEX_OP(op, oparg, cmp, cmparg) \e
- (((op & 0xf) << 28) | \e
- ((cmp & 0xf) << 24) | \e
- ((oparg & 0xfff) << 12) | \e
- (cmparg & 0xfff))
-.EE
-.in
-.IP
-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.
-.IP
-The
-.I op
-component has one of the following values:
-.IP
-.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
-.IP
-In addition, bitwise ORing the following value into
-.I op
-causes
-.I (1\~<<\~oparg)
-to be used as the operand:
-.IP
-.in +4n
-.EX
-FUTEX_OP_ARG_SHIFT 8 /* Use (1 << oparg) as operand */
-.EE
-.in
-.IP
-The
-.I cmp
-field is one of the following:
-.IP
-.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
-.IP
-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 .
-.\"
-.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.\"
-.TP
-.BR FUTEX_WAIT_BITSET " (since Linux 2.6.25)"
-.\" commit cd689985cf49f6ff5c8eddc48d98b9d581d9475d
-This operation is like
-.B FUTEX_WAIT
-except that
-.I val3
-is used to provide a 32-bit bit mask to the kernel.
-This bit mask, in which at least one bit must be set,
-is stored in the kernel-internal state of the waiter.
-See the description of
-.B FUTEX_WAKE_BITSET
-for further details.
-.IP
-If
-.I timeout
-is not NULL, the structure it points to specifies
-an absolute timeout for the wait operation.
-If
-.I timeout
-is NULL, the operation can block indefinitely.
-.IP
-The
-.I uaddr2
-argument is ignored.
-.\"
-.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.\"
-.TP
-.BR FUTEX_WAKE_BITSET " (since Linux 2.6.25)"
-.\" commit cd689985cf49f6ff5c8eddc48d98b9d581d9475d
-This operation is the same as
-.B FUTEX_WAKE
-except that the
-.I val3
-argument is used to provide a 32-bit bit mask to the kernel.
-This bit mask, in which at least one bit must be set,
-is used to select which waiters should be woken up.
-The selection is done by a bitwise AND of the "wake" bit mask
-(i.e., the value in
-.IR val3 )
-and the bit mask which is stored in the kernel-internal
-state of the waiter (the "wait" bit mask that is set using
-.BR FUTEX_WAIT_BITSET ).
-All of the waiters for which the result of the AND is nonzero are woken up;
-the remaining waiters are left sleeping.
-.IP
-The effect of
-.B FUTEX_WAIT_BITSET
-and
-.B FUTEX_WAKE_BITSET
-is to allow selective wake-ups among multiple waiters that are blocked
-on the same futex.
-However, note that, depending on the use case,
-employing this bit-mask multiplexing feature on a
-futex can be less efficient than simply using multiple futexes,
-because employing bit-mask multiplexing requires the kernel
-to check all waiters on a futex,
-including those that are not interested in being woken up
-(i.e., they do not have the relevant bit set in their "wait" bit mask).
-.\" According to http://locklessinc.com/articles/futex_cheat_sheet/:
-.\"
-.\" "The original reason for the addition of these extensions
-.\" was to improve the performance of pthread read-write locks
-.\" in glibc. However, the pthreads library no longer uses the
-.\" same locking algorithm, and these extensions are not used
-.\" without the bitset parameter being all ones.
-.\"
-.\" The page goes on to note that the FUTEX_WAIT_BITSET operation
-.\" is nevertheless used (with a bit mask of all ones) in order to
-.\" obtain the absolute timeout functionality that is useful
-.\" for efficiently implementing Pthreads APIs (which use absolute
-.\" timeouts); FUTEX_WAIT provides only relative timeouts.
-.IP
-The constant
-.BR FUTEX_BITSET_MATCH_ANY ,
-which corresponds to all 32 bits set in the bit mask, can be used as the
-.I val3
-argument for
-.B FUTEX_WAIT_BITSET
-and
-.BR FUTEX_WAKE_BITSET .
-Other than differences in the handling of the
-.I timeout
-argument, the
-.B FUTEX_WAIT
-operation is equivalent to
-.B FUTEX_WAIT_BITSET
-with
-.I val3
-specified as
-.BR FUTEX_BITSET_MATCH_ANY ;
-that is, allow a wake-up by any waker.
-The
-.B FUTEX_WAKE
-operation is equivalent to
-.B FUTEX_WAKE_BITSET
-with
-.I val3
-specified as
-.BR FUTEX_BITSET_MATCH_ANY ;
-that is, wake up any waiter(s).
-.IP
-The
-.I uaddr2
-and
-.I timeout
-arguments are ignored.
-.\"
-.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.\"
-.SS Priority-inheritance futexes
-Linux supports priority-inheritance (PI) futexes in order to handle
-priority-inversion problems that can be encountered with
-normal futex locks.
-Priority inversion is the problem that occurs when a high-priority
-task is blocked waiting to acquire a lock held by a low-priority task,
-while tasks at an intermediate priority continuously preempt
-the low-priority task from the CPU.
-Consequently, the low-priority task makes no progress toward
-releasing the lock, and the high-priority task remains blocked.
-.P
-Priority inheritance is a mechanism for dealing with
-the priority-inversion problem.
-With this mechanism, when a high-priority task becomes blocked
-by a lock held by a low-priority task,
-the priority of the low-priority task is temporarily raised
-to that of the high-priority task,
-so that it is not preempted by any intermediate level tasks,
-and can thus make progress toward releasing the lock.
-To be effective, priority inheritance must be transitive,
-meaning that if a high-priority task blocks on a lock
-held by a lower-priority task that is itself blocked by a lock
-held by another intermediate-priority task
-(and so on, for chains of arbitrary length),
-then both of those tasks
-(or more generally, all of the tasks in a lock chain)
-have their priorities raised to be the same as the high-priority task.
-.P
-From a user-space perspective,
-what makes a futex PI-aware is a policy agreement (described below)
-between user space and the kernel about the value of the futex word,
-coupled with the use of the PI-futex operations described below.
-(Unlike the other futex operations described above,
-the PI-futex operations are designed
-for the implementation of very specific IPC mechanisms.)
-.\"
-.\" Quoting Darren Hart:
-.\" These opcodes paired with the PI futex value policy (described below)
-.\" defines a "futex" as PI aware. These were created very specifically
-.\" in support of PI pthread_mutexes, so it makes a lot more sense to
-.\" talk about a PI aware pthread_mutex, than a PI aware futex, since
-.\" there is a lot of policy and scaffolding that has to be built up
-.\" around it to use it properly (this is what a PI pthread_mutex is).
-.P
-.\" mtk: The following text is drawn from the Hart/Guniguntala paper
-.\" (listed in SEE ALSO), but I have reworded some pieces
-.\" significantly.
-.\"
-The PI-futex operations described below differ from the other
-futex operations in that they impose policy on the use of the value of the
-futex word:
-.IP \[bu] 3
-If the lock is not acquired, the futex word's value shall be 0.
-.IP \[bu]
-If the lock is acquired, the futex word's value shall
-be the thread ID (TID;
-see
-.BR gettid (2))
-of the owning thread.
-.IP \[bu]
-If the lock is owned and there are threads contending for the lock,
-then the
-.B FUTEX_WAITERS
-bit shall be set in the futex word's value; in other words, this value is:
-.IP
-.in +4n
-.EX
-FUTEX_WAITERS | TID
-.EE
-.in
-.IP
-(Note that is invalid for a PI futex word to have no owner and
-.B FUTEX_WAITERS
-set.)
-.P
-With this policy in place,
-a user-space application can acquire an unacquired
-lock or release a lock using atomic instructions executed in user mode
-(e.g., a compare-and-swap operation such as
-.I cmpxchg
-on the x86 architecture).
-Acquiring a lock simply consists of using compare-and-swap to atomically
-set the futex word's value to the caller's TID if its previous value was 0.
-Releasing a lock requires using compare-and-swap to set the futex word's
-value to 0 if the previous value was the expected TID.
-.P
-If a futex is already acquired (i.e., has a nonzero value),
-waiters must employ the
-.B FUTEX_LOCK_PI
-or
-.B FUTEX_LOCK_PI2
-operations to acquire the lock.
-If other threads are waiting for the lock, then the
-.B FUTEX_WAITERS
-bit is set in the futex value;
-in this case, the lock owner must employ the
-.B FUTEX_UNLOCK_PI
-operation to release the lock.
-.P
-In the cases where callers are forced into the kernel
-(i.e., required to perform a
-.BR futex ()
-call),
-they then deal directly with a so-called RT-mutex,
-a kernel locking mechanism which implements the required
-priority-inheritance semantics.
-After the RT-mutex is acquired, the futex value is updated accordingly,
-before the calling thread returns to user space.
-.P
-It is important to note
-.\" tglx (July 2015):
-.\" If there are multiple waiters on a pi futex then a wake pi operation
-.\" will wake the first waiter and hand over the lock to this waiter. This
-.\" includes handing over the rtmutex which represents the futex in the
-.\" kernel. The strict requirement is that the futex owner and the rtmutex
-.\" owner must be the same, except for the update period which is
-.\" serialized by the futex internal locking. That means the kernel must
-.\" update the user-space value prior to returning to user space
-that the kernel will update the futex word's value prior
-to returning to user space.
-(This prevents the possibility of the futex word's value ending
-up in an invalid state, such as having an owner but the value being 0,
-or having waiters but not having the
-.B FUTEX_WAITERS
-bit set.)
-.P
-If a futex has an associated RT-mutex in the kernel
-(i.e., there are blocked waiters)
-and the owner of the futex/RT-mutex dies unexpectedly,
-then the kernel cleans up the RT-mutex and hands it over to the next waiter.
-This in turn requires that the user-space value is updated accordingly.
-To indicate that this is required, the kernel sets the
-.B FUTEX_OWNER_DIED
-bit in the futex word along with the thread ID of the new owner.
-User space can detect this situation via the presence of the
-.B FUTEX_OWNER_DIED
-bit and is then responsible for cleaning up the stale state left over by
-the dead owner.
-.\" tglx (July 2015):
-.\" The FUTEX_OWNER_DIED bit can also be set on uncontended futexes, where
-.\" the kernel has no state associated. This happens via the robust futex
-.\" mechanism. In that case the futex value will be set to
-.\" FUTEX_OWNER_DIED. The robust futex mechanism is also available for non
-.\" PI futexes.
-.P
-PI futexes are operated on by specifying one of the values listed below in
-.IR futex_op .
-Note that the PI futex operations must be used as paired operations
-and are subject to some additional requirements:
-.IP \[bu] 3
-.BR FUTEX_LOCK_PI ,
-.BR FUTEX_LOCK_PI2 ,
-and
-.B FUTEX_TRYLOCK_PI
-pair with
-.BR FUTEX_UNLOCK_PI .
-.B FUTEX_UNLOCK_PI
-must be called only on a futex owned by the calling thread,
-as defined by the value policy, otherwise the error
-.B EPERM
-results.
-.IP \[bu]
-.B FUTEX_WAIT_REQUEUE_PI
-pairs with
-.BR FUTEX_CMP_REQUEUE_PI .
-This must be performed from a non-PI futex to a distinct PI futex
-(or the error
-.B EINVAL
-results).
-Additionally,
-.I val
-(the number of waiters to be woken) must be 1
-(or the error
-.B EINVAL
-results).
-.P
-The PI futex operations are as follows:
-.\"
-.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.\"
-.TP
-.BR FUTEX_LOCK_PI " (since Linux 2.6.18)"
-.\" commit c87e2837be82df479a6bae9f155c43516d2feebc
-This operation is used after an attempt to acquire
-the lock via an atomic user-mode instruction failed
-because the futex word has a nonzero value\[em]specifically,
-because it contained the (PID-namespace-specific) TID of the lock owner.
-.IP
-The operation checks the value of the futex word at the address
-.IR uaddr .
-If the value is 0, then the kernel tries to atomically set
-the futex value to the caller's TID.
-If the futex word's value is nonzero,
-the kernel atomically sets the
-.B FUTEX_WAITERS
-bit, which signals the futex owner that it cannot unlock the futex in
-user space atomically by setting the futex value to 0.
-.\" tglx (July 2015):
-.\" The operation here is similar to the FUTEX_WAIT logic. When the user
-.\" space atomic acquire does not succeed because the futex value was non
-.\" zero, then the waiter goes into the kernel, takes the kernel internal
-.\" lock and retries the acquisition under the lock. If the acquisition
-.\" does not succeed either, then it sets the FUTEX_WAITERS bit, to signal
-.\" the lock owner that it needs to go into the kernel. Here is the pseudo
-.\" code:
-.\"
-.\" lock(kernel_lock);
-.\" retry:
-.\"
-.\" /*
-.\" * Owner might have unlocked in user space before we
-.\" * were able to set the waiter bit.
-.\" */
-.\" if (atomic_acquire(futex) == SUCCESS) {
-.\" unlock(kernel_lock());
-.\" return 0;
-.\" }
-.\"
-.\" /*
-.\" * Owner might have unlocked after the above atomic_acquire()
-.\" * attempt.
-.\" */
-.\" if (atomic_set_waiters_bit(futex) != SUCCESS)
-.\" goto retry;
-.\"
-.\" queue_waiter();
-.\" unlock(kernel_lock);
-.\" block();
-.\"
-After that, the kernel:
-.RS
-.IP (1) 5
-Tries to find the thread which is associated with the owner TID.
-.IP (2)
-Creates or reuses kernel state on behalf of the owner.
-(If this is the first waiter, there is no kernel state for this
-futex, so kernel state is created by locking the RT-mutex
-and the futex owner is made the owner of the RT-mutex.
-If there are existing waiters, then the existing state is reused.)
-.IP (3)
-Attaches the waiter to the futex
-(i.e., the waiter is enqueued on the RT-mutex waiter list).
-.RE
-.IP
-If more than one waiter exists,
-the enqueueing of the waiter is in descending priority order.
-(For information on priority ordering, see the discussion of the
-.BR SCHED_DEADLINE ,
-.BR SCHED_FIFO ,
-and
-.B SCHED_RR
-scheduling policies in
-.BR sched (7).)
-The owner inherits either the waiter's CPU bandwidth
-(if the waiter is scheduled under the
-.B SCHED_DEADLINE
-policy) or the waiter's priority (if the waiter is scheduled under the
-.B SCHED_RR
-or
-.B SCHED_FIFO
-policy).
-.\" August 2015:
-.\" mtk: If the realm is restricted purely to SCHED_OTHER (SCHED_NORMAL)
-.\" processes, does the nice value come into play also?
-.\"
-.\" tglx: No. SCHED_OTHER/NORMAL tasks are handled in FIFO order
-This inheritance follows the lock chain in the case of nested locking
-.\" (i.e., task 1 blocks on lock A, held by task 2,
-.\" while task 2 blocks on lock B, held by task 3)
-and performs deadlock detection.
-.IP
-The
-.I timeout
-argument provides a timeout for the lock attempt.
-If
-.I timeout
-is not NULL, the structure it points to specifies
-an absolute timeout, measured against the
-.B CLOCK_REALTIME
-clock.
-.\" 2016-07-07 response from Thomas Gleixner on LKML:
-.\" From: Thomas Gleixner <tglx@linutronix.de>
-.\" Date: 6 July 2016 at 20:57
-.\" Subject: Re: futex: Allow FUTEX_CLOCK_REALTIME with FUTEX_WAIT op
-.\"
-.\" On Thu, 23 Jun 2016, Michael Kerrisk (man-pages) wrote:
-.\" > On 06/23/2016 08:28 PM, Darren Hart wrote:
-.\" > > And as a follow-on, what is the reason for FUTEX_LOCK_PI only using
-.\" > > CLOCK_REALTIME? It seems reasonable to me that a user may want to wait a
-.\" > > specific amount of time, regardless of wall time.
-.\" >
-.\" > Yes, that's another weird inconsistency.
-.\"
-.\" The reason is that phtread_mutex_timedlock() uses absolute timeouts based on
-.\" CLOCK_REALTIME. glibc folks asked to make that the default behaviour back
-.\" then when we added LOCK_PI.
-If
-.I timeout
-is NULL, the operation will block indefinitely.
-.IP
-The
-.IR uaddr2 ,
-.IR val ,
-and
-.I val3
-arguments are ignored.
-.\"
-.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.\"
-.TP
-.BR FUTEX_LOCK_PI2 " (since Linux 5.14)"
-.\" commit bf22a6976897977b0a3f1aeba6823c959fc4fdae
-This operation is the same as
-.BR FUTEX_LOCK_PI ,
-except that the clock against which
-.I timeout
-is measured is selectable.
-By default, the (absolute) timeout specified in
-.I timeout
-is measured against the
-.B CLOCK_MONOTONIC
-clock, but if the
-.B FUTEX_CLOCK_REALTIME
-flag is specified in
-.IR futex_op ,
-then the timeout is measured against the
-.B CLOCK_REALTIME
-clock.
-.\"
-.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.\"
-.TP
-.BR FUTEX_TRYLOCK_PI " (since Linux 2.6.18)"
-.\" commit c87e2837be82df479a6bae9f155c43516d2feebc
-This operation tries to acquire the lock at
-.IR uaddr .
-It is invoked when a user-space atomic acquire did not
-succeed because the futex word was not 0.
-.IP
-Because the kernel has access to more state information than user space,
-acquisition of the lock might succeed if performed by the
-kernel in cases where the futex word
-(i.e., the state information accessible to use-space) contains stale state
-.RB ( FUTEX_WAITERS
-and/or
-.BR FUTEX_OWNER_DIED ).
-This can happen when the owner of the futex died.
-User space cannot handle this condition in a race-free manner,
-but the kernel can fix this up and acquire the futex.
-.\" Paraphrasing a f2f conversation with Thomas Gleixner about the
-.\" above point (Aug 2015): ###
-.\" There is a rare possibility of a race condition involving an
-.\" uncontended futex with no owner, but with waiters. The
-.\" kernel-user-space contract is that if a futex is nonzero, you must
-.\" go into kernel. The futex was owned by a task, and that task dies
-.\" but there are no waiters, so the futex value is non zero.
-.\" Therefore, the next locker has to go into the kernel,
-.\" so that the kernel has a chance to clean up. (CMXCH on zero
-.\" in user space would fail, so kernel has to clean up.)
-.\" Darren Hart (Oct 2015):
-.\" The trylock in the kernel has more state, so it can independently
-.\" verify the flags that user space must trust implicitly.
-.IP
-The
-.IR uaddr2 ,
-.IR val ,
-.IR timeout ,
-and
-.I val3
-arguments are ignored.
-.\"
-.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.\"
-.TP
-.BR FUTEX_UNLOCK_PI " (since Linux 2.6.18)"
-.\" commit c87e2837be82df479a6bae9f155c43516d2feebc
-This operation wakes the top priority waiter that is waiting in
-.B FUTEX_LOCK_PI
-or
-.B FUTEX_LOCK_PI2
-on the futex address provided by the
-.I uaddr
-argument.
-.IP
-This is called when the user-space value at
-.I uaddr
-cannot be changed atomically from a TID (of the owner) to 0.
-.IP
-The
-.IR uaddr2 ,
-.IR val ,
-.IR timeout ,
-and
-.I val3
-arguments are ignored.
-.\"
-.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.\"
-.TP
-.BR FUTEX_CMP_REQUEUE_PI " (since Linux 2.6.31)"
-.\" commit 52400ba946759af28442dee6265c5c0180ac7122
-This operation is a PI-aware variant of
-.BR FUTEX_CMP_REQUEUE .
-It requeues waiters that are blocked via
-.B FUTEX_WAIT_REQUEUE_PI
-on
-.I uaddr
-from a non-PI source futex
-.RI ( uaddr )
-to a PI target futex
-.RI ( uaddr2 ).
-.IP
-As with
-.BR FUTEX_CMP_REQUEUE ,
-this operation wakes up a maximum of
-.I val
-waiters that are waiting on the futex at
-.IR uaddr .
-However, for
-.BR FUTEX_CMP_REQUEUE_PI ,
-.I val
-is required to be 1
-(since the main point is to avoid a thundering herd).
-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 .
-.IP
-The
-.I val2
-.\" val2 is the cap on the number of requeued waiters.
-.\" In the glibc pthread_cond_broadcast() implementation, this argument
-.\" is specified as INT_MAX, and for pthread_cond_signal() it is 0.
-and
-.I val3
-arguments serve the same purposes as for
-.BR FUTEX_CMP_REQUEUE .
-.\"
-.\" The page at http://locklessinc.com/articles/futex_cheat_sheet/
-.\" notes that "priority-inheritance Futex to priority-inheritance
-.\" Futex requeues are currently unsupported". However, probably
-.\" the page does not need to say nothing about this, since
-.\" Thomas Gleixner commented (July 2015): "they never will be
-.\" supported because they make no sense at all"
-.\"
-.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.\"
-.TP
-.BR FUTEX_WAIT_REQUEUE_PI " (since Linux 2.6.31)"
-.\" commit 52400ba946759af28442dee6265c5c0180ac7122
-.\"
-Wait on a non-PI futex at
-.I uaddr
-and potentially be requeued (via a
-.B FUTEX_CMP_REQUEUE_PI
-operation in another task) onto a PI futex at
-.IR uaddr2 .
-The wait operation on
-.I uaddr
-is the same as for
-.BR FUTEX_WAIT .
-.IP
-The waiter can be removed from the wait on
-.I uaddr
-without requeueing on
-.I uaddr2
-via a
-.B FUTEX_WAKE
-operation in another task.
-In this case, the
-.B FUTEX_WAIT_REQUEUE_PI
-operation fails with the error
-.BR EAGAIN .
-.IP
-If
-.I timeout
-is not NULL, the structure it points to specifies
-an absolute timeout for the wait operation.
-If
-.I timeout
-is NULL, the operation can block indefinitely.
-.IP
-The
-.I val3
-argument is ignored.
-.IP
-The
-.B FUTEX_WAIT_REQUEUE_PI
-and
-.B FUTEX_CMP_REQUEUE_PI
-were added to support a fairly specific use case:
-support for priority-inheritance-aware POSIX threads condition variables.
-The idea is that these operations should always be paired,
-in order to ensure that user space and the kernel remain in sync.
-Thus, in the
-.B FUTEX_WAIT_REQUEUE_PI
-operation, the user-space application pre-specifies the target
-of the requeue that takes place in the
-.B FUTEX_CMP_REQUEUE_PI
-operation.
-.\"
-.\" Darren Hart notes that a patch to allow glibc to fully support
-.\" PI-aware pthreads condition variables has not yet been accepted into
-.\" glibc. The story is complex, and can be found at
-.\" https://sourceware.org/bugzilla/show_bug.cgi?id=11588
-.\" Darren notes that in the meantime, the patch is shipped with various
-.\" PREEMPT_RT-enabled Linux systems.
-.\"
-.\" Related to the preceding, Darren proposed that somewhere, man-pages
-.\" should document the following point:
-.\"
-.\" While the Linux kernel, since Linux 2.6.31, supports requeueing of
-.\" priority-inheritance (PI) aware mutexes via the
-.\" FUTEX_WAIT_REQUEUE_PI and FUTEX_CMP_REQUEUE_PI futex operations,
-.\" the glibc implementation does not yet take full advantage of this.
-.\" Specifically, the condvar internal data lock remains a non-PI aware
-.\" mutex, regardless of the type of the pthread_mutex associated with
-.\" the condvar. This can lead to an unbounded priority inversion on
-.\" the internal data lock even when associating a PI aware
-.\" pthread_mutex with a condvar during a pthread_cond*_wait
-.\" operation. For this reason, it is not recommended to rely on
-.\" priority inheritance when using pthread condition variables.
-.\"
-.\" The problem is that the obvious location for this text is
-.\" the pthread_cond*wait(3) man page. However, such a man page
-.\" does not currently exist.
-.\"
-.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.\"
-.SH RETURN VALUE
-In the event of an error (and assuming that
-.BR futex ()
-was invoked via
-.BR syscall (2)),
-all operations return \-1 and set
-.I errno
-to indicate the error.
-.P
-The return value on success depends on the operation,
-as described in the following list:
-.TP
-.B FUTEX_WAIT
-Returns 0 if the caller was woken up.
-Note that a wake-up can also be caused by common futex usage patterns
-in unrelated code that happened to have previously used the futex word's
-memory location (e.g., typical futex-based implementations of
-Pthreads mutexes can cause this under some conditions).
-Therefore, callers should always conservatively assume that a return
-value of 0 can mean a spurious wake-up, and use the futex word's value
-(i.e., the user-space synchronization scheme)
-to decide whether to continue to block or not.
-.TP
-.B FUTEX_WAKE
-Returns the number of waiters that were woken up.
-.TP
-.B FUTEX_FD
-Returns the new file descriptor associated with the futex.
-.TP
-.B FUTEX_REQUEUE
-Returns the number of waiters that were woken up.
-.TP
-.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 .
-.TP
-.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 .
-.TP
-.B FUTEX_WAIT_BITSET
-Returns 0 if the caller was woken up.
-See
-.B FUTEX_WAIT
-for how to interpret this correctly in practice.
-.TP
-.B FUTEX_WAKE_BITSET
-Returns the number of waiters that were woken up.
-.TP
-.B FUTEX_LOCK_PI
-Returns 0 if the futex was successfully locked.
-.TP
-.B FUTEX_LOCK_PI2
-Returns 0 if the futex was successfully locked.
-.TP
-.B FUTEX_TRYLOCK_PI
-Returns 0 if the futex was successfully locked.
-.TP
-.B FUTEX_UNLOCK_PI
-Returns 0 if the futex was successfully unlocked.
-.TP
-.B FUTEX_CMP_REQUEUE_PI
-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 difference is the number of waiters requeued to the futex for
-the futex word at
-.IR uaddr2 .
-.TP
-.B FUTEX_WAIT_REQUEUE_PI
-Returns 0 if the caller was successfully requeued to the futex for
-the futex word at
-.IR uaddr2 .
-.\"
-.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.\"
-.SH ERRORS
-.TP
-.B EACCES
-No read access to the memory of a futex word.
-.TP
-.B EAGAIN
-.RB ( FUTEX_WAIT ,
-.BR FUTEX_WAIT_BITSET ,
-.BR FUTEX_WAIT_REQUEUE_PI )
-The value pointed to by
-.I uaddr
-was not equal to the expected value
-.I val
-at the time of the call.
-.IP
-.BR Note :
-on Linux, the symbolic names
-.B EAGAIN
-and
-.B EWOULDBLOCK
-(both of which appear in different parts of the kernel futex code)
-have the same value.
-.TP
-.B EAGAIN
-.RB ( FUTEX_CMP_REQUEUE ,
-.BR FUTEX_CMP_REQUEUE_PI )
-The value pointed to by
-.I uaddr
-is not equal to the expected value
-.IR val3 .
-.TP
-.B EAGAIN
-.RB ( FUTEX_LOCK_PI ,
-.BR FUTEX_LOCK_PI2 ,
-.BR FUTEX_TRYLOCK_PI ,
-.BR FUTEX_CMP_REQUEUE_PI )
-The futex owner thread ID of
-.I uaddr
-(for
-.BR FUTEX_CMP_REQUEUE_PI :
-.IR uaddr2 )
-is about to exit,
-but has not yet handled the internal state cleanup.
-Try again.
-.TP
-.B EDEADLK
-.RB ( FUTEX_LOCK_PI ,
-.BR FUTEX_LOCK_PI2 ,
-.BR FUTEX_TRYLOCK_PI ,
-.BR FUTEX_CMP_REQUEUE_PI )
-The futex word at
-.I uaddr
-is already locked by the caller.
-.TP
-.B EDEADLK
-.\" FIXME . I see that kernel/locking/rtmutex.c uses EDEADLK in some
-.\" places, and EDEADLOCK in others. On almost all architectures
-.\" these constants are synonymous. Is there a reason that both
-.\" names are used?
-.\"
-.\" tglx (July 2015): "No. We should probably fix that."
-.\"
-.RB ( FUTEX_CMP_REQUEUE_PI )
-While requeueing a waiter to the PI futex for the futex word at
-.IR uaddr2 ,
-the kernel detected a deadlock.
-.TP
-.B EFAULT
-A required pointer argument (i.e.,
-.IR uaddr ,
-.IR uaddr2 ,
-or
-.IR timeout )
-did not point to a valid user-space address.
-.TP
-.B EINTR
-A
-.B FUTEX_WAIT
-or
-.B FUTEX_WAIT_BITSET
-operation was interrupted by a signal (see
-.BR signal (7)).
-Before Linux 2.6.22, this error could also be returned for
-a spurious wakeup; since Linux 2.6.22, this no longer happens.
-.TP
-.B EINVAL
-The operation in
-.I futex_op
-is one of those that employs a timeout, but the supplied
-.I timeout
-argument was invalid
-.RI ( tv_sec
-was less than zero, or
-.I tv_nsec
-was not less than 1,000,000,000).
-.TP
-.B EINVAL
-The operation specified in
-.I futex_op
-employs one or both of the pointers
-.I uaddr
-and
-.IR uaddr2 ,
-but one of these does not point to a valid object\[em]that is,
-the address is not four-byte-aligned.
-.TP
-.B EINVAL
-.RB ( FUTEX_WAIT_BITSET ,
-.BR FUTEX_WAKE_BITSET )
-The bit mask supplied in
-.I val3
-is zero.
-.TP
-.B EINVAL
-.RB ( FUTEX_CMP_REQUEUE_PI )
-.I uaddr
-equals
-.I uaddr2
-(i.e., an attempt was made to requeue to the same futex).
-.TP
-.B EINVAL
-.RB ( FUTEX_FD )
-The signal number supplied in
-.I val
-is invalid.
-.TP
-.B EINVAL
-.RB ( FUTEX_WAKE ,
-.BR FUTEX_WAKE_OP ,
-.BR FUTEX_WAKE_BITSET ,
-.BR FUTEX_REQUEUE ,
-.BR FUTEX_CMP_REQUEUE )
-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
-.B FUTEX_LOCK_PI
-or
-.B FUTEX_LOCK_PI2
-on
-.IR uaddr .
-.TP
-.B EINVAL
-.RB ( FUTEX_LOCK_PI ,
-.BR FUTEX_LOCK_PI2 ,
-.BR FUTEX_TRYLOCK_PI ,
-.BR FUTEX_UNLOCK_PI )
-The kernel detected an inconsistency between the user-space state at
-.I uaddr
-and the kernel state.
-This indicates either state corruption
-or that the kernel found a waiter on
-.I uaddr
-which is waiting via
-.B FUTEX_WAIT
-or
-.BR FUTEX_WAIT_BITSET .
-.TP
-.B EINVAL
-.RB ( FUTEX_CMP_REQUEUE_PI )
-The kernel detected an inconsistency between the user-space state at
-.I uaddr2
-and the kernel state;
-.\" From a conversation with Thomas Gleixner (Aug 2015): ###
-.\" The kernel sees: I have non PI state for a futex you tried to
-.\" tell me was PI
-that is, the kernel detected a waiter which waits via
-.B FUTEX_WAIT
-or
-.B FUTEX_WAIT_BITSET
-on
-.IR uaddr2 .
-.TP
-.B EINVAL
-.RB ( FUTEX_CMP_REQUEUE_PI )
-The kernel detected an inconsistency between the user-space state at
-.I uaddr
-and the kernel state;
-that is, the kernel detected a waiter which waits via
-.B FUTEX_WAIT
-or
-.B FUTEX_WAIT_BITSET
-on
-.IR uaddr .
-.TP
-.B EINVAL
-.RB ( FUTEX_CMP_REQUEUE_PI )
-The kernel detected an inconsistency between the user-space state at
-.I uaddr
-and the kernel state;
-that is, the kernel detected a waiter which waits on
-.I uaddr
-via
-.B FUTEX_LOCK_PI
-or
-.B FUTEX_LOCK_PI2
-(instead of
-.BR FUTEX_WAIT_REQUEUE_PI ).
-.TP
-.B EINVAL
-.RB ( FUTEX_CMP_REQUEUE_PI )
-.\" This deals with the case:
-.\" wait_requeue_pi(A, B);
-.\" requeue_pi(A, C);
-An attempt was made to requeue a waiter to a futex other than that
-specified by the matching
-.B FUTEX_WAIT_REQUEUE_PI
-call for that waiter.
-.TP
-.B EINVAL
-.RB ( FUTEX_CMP_REQUEUE_PI )
-The
-.I val
-argument is not 1.
-.TP
-.B EINVAL
-Invalid argument.
-.TP
-.B ENFILE
-.RB ( FUTEX_FD )
-The system-wide limit on the total number of open files has been reached.
-.TP
-.B ENOMEM
-.RB ( FUTEX_LOCK_PI ,
-.BR FUTEX_LOCK_PI2 ,
-.BR FUTEX_TRYLOCK_PI ,
-.BR FUTEX_CMP_REQUEUE_PI )
-The kernel could not allocate memory to hold state information.
-.TP
-.B ENOSYS
-Invalid operation specified in
-.IR futex_op .
-.TP
-.B ENOSYS
-The
-.B FUTEX_CLOCK_REALTIME
-option was specified in
-.IR futex_op ,
-but the accompanying operation was neither
-.BR FUTEX_WAIT ,
-.BR FUTEX_WAIT_BITSET ,
-.BR FUTEX_WAIT_REQUEUE_PI ,
-nor
-.BR FUTEX_LOCK_PI2 .
-.TP
-.B ENOSYS
-.RB ( FUTEX_LOCK_PI ,
-.BR FUTEX_LOCK_PI2 ,
-.BR FUTEX_TRYLOCK_PI ,
-.BR FUTEX_UNLOCK_PI ,
-.BR FUTEX_CMP_REQUEUE_PI ,
-.BR FUTEX_WAIT_REQUEUE_PI )
-A run-time check determined that the operation is not available.
-The PI-futex operations are not implemented on all architectures and
-are not supported on some CPU variants.
-.TP
-.B EPERM
-.RB ( FUTEX_LOCK_PI ,
-.BR FUTEX_LOCK_PI2 ,
-.BR FUTEX_TRYLOCK_PI ,
-.BR FUTEX_CMP_REQUEUE_PI )
-The caller is not allowed to attach itself to the futex at
-.I uaddr
-(for
-.BR FUTEX_CMP_REQUEUE_PI :
-the futex at
-.IR uaddr2 ).
-(This may be caused by a state corruption in user space.)
-.TP
-.B EPERM
-.RB ( FUTEX_UNLOCK_PI )
-The caller does not own the lock represented by the futex word.
-.TP
-.B ESRCH
-.RB ( FUTEX_LOCK_PI ,
-.BR FUTEX_LOCK_PI2 ,
-.BR FUTEX_TRYLOCK_PI ,
-.BR FUTEX_CMP_REQUEUE_PI )
-The thread ID in the futex word at
-.I uaddr
-does not exist.
-.TP
-.B ESRCH
-.RB ( FUTEX_CMP_REQUEUE_PI )
-The thread ID in the futex word at
-.I uaddr2
-does not exist.
-.TP
-.B ETIMEDOUT
-The operation in
-.I futex_op
-employed the timeout specified in
-.IR timeout ,
-and the timeout expired before the operation completed.
-.\"
-.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.\"
-.SH STANDARDS
-Linux.
-.SH HISTORY
-Linux 2.6.0.
-.P
-Initial futex support was merged in Linux 2.5.7 but with different
-semantics from what was described above.
-A four-argument system call with the semantics
-described in this page was introduced in Linux 2.5.40.
-A fifth argument was added in Linux 2.5.70,
-and a sixth argument was added in Linux 2.6.7.
-.SH EXAMPLES
-The program below demonstrates use of futexes in a program where a parent
-process and a child process use a pair of futexes located inside a
-shared anonymous mapping to synchronize access to a shared resource:
-the terminal.
-The two processes each write
-.I nloops
-(a command-line argument that defaults to 5 if omitted)
-messages to the terminal and employ a synchronization protocol
-that ensures that they alternate in writing messages.
-Upon running this program we see output such as the following:
-.P
-.in +4n
-.EX
-$ \fB./futex_demo\fP
-Parent (18534) 0
-Child (18535) 0
-Parent (18534) 1
-Child (18535) 1
-Parent (18534) 2
-Child (18535) 2
-Parent (18534) 3
-Child (18535) 3
-Parent (18534) 4
-Child (18535) 4
-.EE
-.in
-.SS Program source
-\&
-.\" SRC BEGIN (futex.c)
-.EX
-/* futex_demo.c
-\&
- Usage: futex_demo [nloops]
- (Default: 5)
-\&
- Demonstrate the use of futexes in a program where parent and child
- use a pair of futexes located inside a shared anonymous mapping to
- synchronize access to a shared resource: the terminal. The two
- processes each write \[aq]num\-loops\[aq] messages to the terminal and employ
- a synchronization protocol that ensures that they alternate in
- writing messages.
-*/
-#define _GNU_SOURCE
-#include <err.h>
-#include <errno.h>
-#include <linux/futex.h>
-#include <stdatomic.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/mman.h>
-#include <sys/syscall.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <unistd.h>
-\&
-static uint32_t *futex1, *futex2, *iaddr;
-\&
-static int
-futex(uint32_t *uaddr, int futex_op, uint32_t val,
- const struct timespec *timeout, uint32_t *uaddr2, uint32_t val3)
-{
- return syscall(SYS_futex, uaddr, futex_op, val,
- timeout, uaddr2, val3);
-}
-\&
-/* Acquire the futex pointed to by \[aq]futexp\[aq]: wait for its value to
- become 1, and then set the value to 0. */
-\&
-static void
-fwait(uint32_t *futexp)
-{
- long s;
- const uint32_t one = 1;
-\&
- /* atomic_compare_exchange_strong(ptr, oldval, newval)
- atomically performs the equivalent of:
-\&
- if (*ptr == *oldval)
- *ptr = newval;
-\&
- It returns true if the test yielded true and *ptr was updated. */
-\&
- while (1) {
-\&
- /* Is the futex available? */
- if (atomic_compare_exchange_strong(futexp, &one, 0))
- break; /* Yes */
-\&
- /* Futex is not available; wait. */
-\&
- s = futex(futexp, FUTEX_WAIT, 0, NULL, NULL, 0);
- if (s == \-1 && errno != EAGAIN)
- err(EXIT_FAILURE, "futex\-FUTEX_WAIT");
- }
-}
-\&
-/* Release the futex pointed to by \[aq]futexp\[aq]: if the futex currently
- has the value 0, set its value to 1 and then wake any futex waiters,
- so that if the peer is blocked in fwait(), it can proceed. */
-\&
-static void
-fpost(uint32_t *futexp)
-{
- long s;
- const uint32_t zero = 0;
-\&
- /* atomic_compare_exchange_strong() was described
- in comments above. */
-\&
- if (atomic_compare_exchange_strong(futexp, &zero, 1)) {
- s = futex(futexp, FUTEX_WAKE, 1, NULL, NULL, 0);
- if (s == \-1)
- err(EXIT_FAILURE, "futex\-FUTEX_WAKE");
- }
-}
-\&
-int
-main(int argc, char *argv[])
-{
- pid_t childPid;
- unsigned int nloops;
-\&
- setbuf(stdout, NULL);
-\&
- nloops = (argc > 1) ? atoi(argv[1]) : 5;
-\&
- /* Create a shared anonymous mapping that will hold the futexes.
- Since the futexes are being shared between processes, we
- subsequently use the "shared" futex operations (i.e., not the
- ones suffixed "_PRIVATE"). */
-\&
- iaddr = mmap(NULL, sizeof(*iaddr) * 2, PROT_READ | PROT_WRITE,
- MAP_ANONYMOUS | MAP_SHARED, \-1, 0);
- if (iaddr == MAP_FAILED)
- err(EXIT_FAILURE, "mmap");
-\&
- futex1 = &iaddr[0];
- futex2 = &iaddr[1];
-\&
- *futex1 = 0; /* State: unavailable */
- *futex2 = 1; /* State: available */
-\&
- /* Create a child process that inherits the shared anonymous
- mapping. */
-\&
- childPid = fork();
- if (childPid == \-1)
- err(EXIT_FAILURE, "fork");
-\&
- if (childPid == 0) { /* Child */
- for (unsigned int j = 0; j < nloops; j++) {
- fwait(futex1);
- printf("Child (%jd) %u\en", (intmax_t) getpid(), j);
- fpost(futex2);
- }
-\&
- exit(EXIT_SUCCESS);
- }
-\&
- /* Parent falls through to here. */
-\&
- for (unsigned int j = 0; j < nloops; j++) {
- fwait(futex2);
- printf("Parent (%jd) %u\en", (intmax_t) getpid(), j);
- fpost(futex1);
- }
-\&
- wait(NULL);
-\&
- exit(EXIT_SUCCESS);
-}
-.EE
-.\" SRC END
-.SH SEE ALSO
-.ad l
-.BR get_robust_list (2),
-.BR restart_syscall (2),
-.BR pthread_mutexattr_getprotocol (3),
-.BR futex (7),
-.BR sched (7)
-.P
-The following kernel source files:
-.IP \[bu] 3
-.I Documentation/pi\-futex.txt
-.IP \[bu]
-.I Documentation/futex\-requeue\-pi.txt
-.IP \[bu]
-.I Documentation/locking/rt\-mutex.txt
-.IP \[bu]
-.I Documentation/locking/rt\-mutex\-design.txt
-.IP \[bu]
-.I Documentation/robust\-futex\-ABI.txt
-.P
-Franke, H., Russell, R., and Kirwood, M., 2002.
-\fIFuss, Futexes and Furwocks: Fast Userlevel Locking in Linux\fP
-(from proceedings of the Ottawa Linux Symposium 2002),
-.br
-.UR http://kernel.org\:/doc\:/ols\:/2002\:/ols2002\-pages\-479\-495.pdf
-.UE
-.P
-Hart, D., 2009. \fIA futex overview and update\fP,
-.UR http://lwn.net/Articles/360699/
-.UE
-.P
-Hart, D.\& and Guniguntala, D., 2009.
-\fIRequeue-PI: Making glibc Condvars PI-Aware\fP
-(from proceedings of the 2009 Real-Time Linux Workshop),
-.UR http://lwn.net/images/conf/rtlws11/papers/proc/p10.pdf
-.UE
-.P
-Drepper, U., 2011. \fIFutexes Are Tricky\fP,
-.UR http://www.akkadia.org/drepper/futex.pdf
-.UE
-.P
-Futex example library, futex\-*.tar.bz2 at
-.br
-.UR https://mirrors.kernel.org\:/pub\:/linux\:/kernel\:/people\:/rusty/
-.UE
-.\"
-.\" FIXME(Torvald) We should probably refer to the glibc code here, in
-.\" particular the glibc-internal futex wrapper functions that are
-.\" WIP, and the generic pthread_mutex_t and perhaps condvar
-.\" implementations.