Futex Manual Summary

Source: Internet
Author: User

#include <linux/futex.h>

#include <sys/time.h>

int Futex (int *uaddr, int futex_op, int val,

const struct TIMESPEC * Timeout , /* or: uint32_t val2 * /

int * UADDR2 , int Val3 );

DESCRIPTION:

  The Futex () system call provides a way to wait for a particular condition to occur. A typical application is to act as a blocking device in shared memory synchronization. When using Futex, most of the synchronization operations are done in the user state, and a user-state program uses Futex only if it is possible to block a longer wait condition. Other Futex operations can be used to wake up any process or thread that waits for a particular condition to occur.

A Futex is a 32-bit value, its address is passed through Futex (), Futexs is 32 bits on all platforms (including 64-bit systems), and all Futex operations are on this value. In order to share futex,futex across multiple processes in a piece of shared memory created by Mmap or Shmat (in this case, the Futex values may be in different virtual addresses on different processes, but these virtual addresses point to the same physical address). In a multithreaded program, you can put the Futex value in a global variable shared by all threads.

When executing a FUTEX operation request blocking a thread, the kernel performs a blocking operation only when *uaddr = = val, all steps in this operation (1. Import the value of the *uaddr; 2. Comparison; 3. The blocking thread) will execute the atom, and all steps will not be disorderly when other threads are operating in parallel on the same Futex value.

One way to use Futex is to implement a lock, where the state of the lock (acquired or not acquired) can be represented by an atomic flag in shared memory. In non-competitive situations, a thread can access and modify the state of a lock through atomic operations (all of which operate in the user state, and the kernel does not save any state about the lock). On the other hand, another thread may not be able to acquire the lock (because the lock has already been fetched by a thread) and the thread will execute the Futex () wait operation in this way:

atomic<intlock//  lock:0. Lock not acquired 1. Lock is obtained Futex (&lock1, NULL, NULL, NULL);

Futex (futex_wait) will detect the value of lock and block the thread only if it equals 1 o'clock. When a thread releases a lock, the thread must first reset the lock's state, and then perform a futex operation to wake up the thread that is blocking on the lock.

Note Using Futex does not display initialization and destruction operations, and the kernel maintains Futex data only when performing Futex operations (such as futex_wait) on a specified Futex value.

Arguments (parameter):

  Uaddr points to the Futex value, on all platforms, the Futex value is a 4-byte integer and must be 4-byte aligned.

For some blocking operations, the timeout parameter is a pointer to the TIMESPEC structure, indicating the time-out for the operation. However, in some other operations, its minimum of 4 bytes is used as an integer value, the meaning of this integer is different from the Futex operation, for these operations, the kernel will convert the timeout value to unsigned long, and then convert to uint32_t, In the following description, it will be represented as val2.

When needed, UADDR2 is a pointer to the second Futex value, and Val3 's explanation will depend on the specific action.

Futex Operations (operation):

The Futex_op parameter contains two parts: 1. Type of operation 2. Flag options (affects action behavior).

  Futex_private_flag (Since Linux 2.6.22)

This flag option can be used in all futex operations, which tells the kernel that the Futex is in-process and not shared with other processes (it can only be used to synchronize threads within the same process), so that the kernel can do some additional optimizations.

  Futex_clock_realtime (Since Linux 2.6.28)

This flag option can only be used in futex_wait_bitset and futex_wait_requeue_pi operations, and if this flag option is set, the kernel will treat timeout as based on Clock_ the absolute time of the REALTIME. If this flag is not set, the kernel will treat it as a relative time based on clock_monotonic .

The Futex operation contains the following:

  futex_wait (Since Linux 2.6.0)

This operation checks if *uaddr is equal to Val, and if it is equal, then sleep waits for the futex_wake operation on Uaddr, and if the thread starts to sleep, it is considered to be the last person on this Futex value. If the two are not equal, the operation fails and returns the error eagain. The purpose of comparing *UADDR and Val is to avoid loss of wake.

If the timeout parameter is not NULL, it specifies the wait time-out ( measured by clock_monotonic ).

  Futex_wake (Since Linux 2.6.0)

This operation wakes up to a maximum of Val, and in most cases, Val has a value of 1 (waking only one of the waiting) or int_max (waking up all the waiting persons) . Note that there is no mechanism to ensure that certain waiting persons (such as those considered high priority) must be awakened .

  Parameter timeout, UADDR2, VAL3 will be ignored.

  Futex_requeue (Since Linux 2.6.0)

This operation and the following futex_cmp_requeue complete the same functionality, except that the VAL3 is not checked. (parameter val3 is ignored)

  Futex_cmp_requeue (Since Linux 2.6.7)

This operation first checks whether *uaddr equals Val3, and if not equal, returns the error eagain. Otherwise, it will wake up to a maximum of Val, and if the number of waiting persons is greater than Val, the remaining waits are removed from the uaddr waiting queue and added to the UADDR2 waiting queue. The Val2 parameter specifies the maximum number of waiting persons to move to UADDR2.

The typical value of Val is 0 or 1, and specifying INT_MAX is of no use, which will make the futex_cmp_requeue operation the same as the Futex_wake operation . Similarly, the value of val2 is typically 1 or int_max, and specifying 0 is useless, which makes the futex_cmp_requeue operation the same as the futex_wait operation.

  futex_cmp_requeue is used to replace the Futex_requeue , the difference between the two is whether to check the value of UADDR, this check can be used to ensure that the removal of the addition operation only under certain conditions, This avoids some race condition.

  Both futex_cmp_requeue and futex_requeue can be used to avoid the "thread scare" phenomenon that futex_wake may produce. Consider the following scenario, where multiple threads are waiting for B (a wait queue implemented with Futex):

Lock (A)  while (! Check_value (V)) {      unlock (A);      BLOCK_ON (B);       Lock (A);}; Unlock (A);

If a thread uses Futex_wake to wake all threads on B, they will all attempt to acquire lock A, but in this case it is futile to wake all the threads, because all but one thread are all blocked on a, by contrast, requeue The operation can wake up a waiting thread and then move the remaining waiting thread to a, while the other threads can continue to execute when the line threads unlocked a.

Futex Manual Summary

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.