Case Study: Linux Futex (Fast Userspace Mutex)
uaddr
points to a 32-bit value in user space
futex_op
FUTEX_WAIT
– ifval == *uaddr
then sleep till FUTEX_WAKE Atomic check that condition still holds after we disable interrupts (in kernel!)
FUTEX_WAKE
– wake up at mostval
waiting threads
FUTEX_FD
,FUTEX_WAKE_OP
,FUTEX_CMP_REQUEUE
: More interesting operations!
timeout
-ptr
to a timespec structure that specifies a timeout for the op
Interface to the kernel sleep()
functionality. Let the thread put themselves to sleep conditionally.
T&S and Futex
acquire(int *thelock)
This function is used to acquire the lock. The argument is a pointer to the lock variable.
futex(thelock, FUTEX_WAIT, 1)
is called when the lock is not available. This puts the calling thread to sleep until the lock becomes available. TheFUTEX_WAIT
operation suspends the thread if the current value of the futex word (i.e., the lock variable) is1
(the third argument tofutex
).
release(int *thelock)
This function is used to release the lock. The argument is a pointer to the lock variable.
futex(&thelock, FUTEX_WAKE, 1);
wakes up one of the threads waiting on the lock, if any. TheFUTEX_WAKE
operation wakes up a number of threads waiting on the futex word (i.e., the lock variable). The third argument tofutex
specifies the maximum number of threads to wake up, which in this case is1
.
There is no busy waiting here. The acquire procedure simply sleeps until being waken up by the release. But we still have to tap into the kernel to release the lock even if there is no one who is acquring the lock.
So we provide a second implementation to be syscall-free in the uncontended case:
A more elegant implementation:
Last updated