• D
    futex: Fix wakeup race by setting TASK_INTERRUPTIBLE before queue_me() · 0729e196
    Darren Hart 提交于
    PI futexes do not use the same plist_node_empty() test for wakeup.
    It was possible for the waiter (in futex_wait_requeue_pi()) to set
    TASK_INTERRUPTIBLE after the waker assigned the rtmutex to the
    waiter. The waiter would then note the plist was not empty and call
    schedule(). The task would not be found by any subsequeuent futex
    wakeups, resulting in a userspace hang.
    
    By moving the setting of TASK_INTERRUPTIBLE to before the call to
    queue_me(), the race with the waker is eliminated. Since we no
    longer call get_user() from within queue_me(), there is no need to
    delay the setting of TASK_INTERRUPTIBLE until after the call to
    queue_me().
    
    The FUTEX_LOCK_PI operation is not affected as futex_lock_pi()
    relies entirely on the rtmutex code to handle schedule() and
    wakeup.  The requeue PI code is affected because the waiter starts
    as a non-PI waiter and is woken on a PI futex.
    
    Remove the crusty old comment about holding spinlocks() across
    get_user() as we no longer do that. Correct the locking statement
    with a description of why the test is performed.
    Signed-off-by: NDarren Hart <dvhltc@us.ibm.com>
    Acked-by: NPeter Zijlstra <peterz@infradead.org>
    Cc: Steven Rostedt <rostedt@goodmis.org>
    Cc: Eric Dumazet <eric.dumazet@gmail.com>
    Cc: Dinakar Guniguntala <dino@in.ibm.com>
    Cc: John Stultz <johnstul@us.ibm.com>
    LKML-Reference: <20090922053038.8717.97838.stgit@Aeon>
    Signed-off-by: NIngo Molnar <mingo@elte.hu>
    0729e196
futex.c 67.3 KB