• Linus Torvalds's avatar
    futex: avoid race between requeue and wake · 69cd9eba
    Linus Torvalds authored
    Jan Stancek reported:
     "pthread_cond_broadcast/4-1.c testcase from openposix testsuite (LTP)
      occasionally fails, because some threads fail to wake up.
    
      Testcase creates 5 threads, which are all waiting on same condition.
      Main thread then calls pthread_cond_broadcast() without holding mutex,
      which calls:
    
          futex(uaddr1, FUTEX_CMP_REQUEUE_PRIVATE, 1, 2147483647, uaddr2, ..)
    
      This immediately wakes up single thread A, which unlocks mutex and
      tries to wake up another thread:
    
          futex(uaddr2, FUTEX_WAKE_PRIVATE, 1)
    
      If thread A manages to call futex_wake() before any waiters are
      requeued for uaddr2, no other thread is woken up"
    
    The ordering constraints for the hash bucket waiter counting are that
    the waiter counts have to be incremented _before_ getting the spinlock
    (because the spinlock acts as part of the memory barrier), but the
    "requeue" operation didn't honor those rules, and nobody had even
    thought about that case.
    
    This fairly simple patch just increments the waiter count for the target
    hash bucket (hb2) when requeing a futex before taking the locks.  It
    then decrements them again after releasing the lock - the code that
    actually moves the futex(es) between hash buckets will do the additional
    required waiter count housekeeping.
    Reported-and-tested-by: default avatarJan Stancek <jstancek@redhat.com>
    Acked-by: default avatarDavidlohr Bueso <davidlohr@hp.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Cc: stable@vger.kernel.org # 3.14
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    69cd9eba
futex.c 76.8 KB