Linux-based Futex Locks

void mutex_lock (int *mutex)
{
  int v;
  /* Bit 31 was clear, we got the mutex (the fastpath) */
  if (atomic_bit_test_set (mutex, 31) == 0)
    return;
  atomic_increment (mutex);
  while (1)
  {
    if (atomic_bit_test_set (mutex, 31) == 0)
    {
      atomic_decrement (mutex);
      return;
    }
    /*We have to waitFirst make sure the futex value
             we are monitoring is truly negative (locked). */
    v = *mutex;
    if (v >= 0)
      continue;
    futex_wait (mutex, v);
  }
}
void mutex_unlock (int *mutex)
{
  /* Adding 0x80000000 to counter results in 0 if and
     only if there are not other interested threads */
  if (atomic_add_zero (mutex, 0x80000000))
    return;
  /* There are other threads waiting for this mutex,
     wake one of them up.  */
  futex_wake (mutex);
}

Specifically, two calls are available. The call to futex wait(address, expected) puts the calling thread to sleep, assuming the value at address is equal to expected. If it is not equal, the call returns immediately. The call to the routine futex wake(address) wakes one thread that is wait- ing on the queue. The usage of these calls in a Linux mutex is shown in Figure 28.10 (page 19).
This code snippet from lowlevellock.h in the nptl library (part of the gnu libc library) [L09] is interesting for a few reasons. First, it uses a single integer to track both whether the lock is held or not (the high bit of the integer) and the number of waiters on the lock (all the other bits). Thus, if the lock is negative, it is held (because the high bit is set and that bit determines the sign of the integer).

—摘自 Operating System (Three easy pieces) chapter 28.15

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章