Case Study: Linux Futex (Fast Userspace Mutex)

#include <linux/futex.h>
#include <sys/time.h>

int futex(int *uaddr, int futex_op, int val, const struct timespec *timeout);

uaddr points to a 32-bit value in user space

futex_op

  • FUTEX_WAIT – if val == *uaddr then sleep till FUTEX_WAKE Atomic check that condition still holds after we disable interrupts (in kernel!)

  • FUTEX_WAKE – wake up at most val 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) {
  while(__atomic_test_and_set(thelock, __ATOMIC_SEQ_CST)) {
    futex(thelock, FUTEX_WAIT, 1);
  }
}

release(int *thelock) {
  thelock = 0;
  futex(thelock, FUTEX_WAKE, 1);
}

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. The FUTEX_WAIT operation suspends the thread if the current value of the futex word (i.e., the lock variable) is 1 (the third argument to futex).

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. The FUTEX_WAKE operation wakes up a number of threads waiting on the futex word (i.e., the lock variable). The third argument to futex specifies the maximum number of threads to wake up, which in this case is 1.

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