• Thomas Gleixner's avatar
    rtmutex: prevent missed wakeups · 487ac708
    Thomas Gleixner authored
    The sleeping locks implementation based on rtmutexes can miss wakeups
    for two reasons:
    
    1) The unconditional usage TASK_UNINTERRUPTIBLE for the blocking state
    
       Results in missed wakeups from wake_up_interruptible*()
    
       state = TASK_INTERRUPTIBLE;
       blocks_on_lock()
         state = TASK_UNINTERRUPTIBLE;
         schedule();
         ....
         acquires_lock();
         restore_state();
    
       Until the waiter has restored its state wake_up_interruptible*() will
       fail.
    
    2) The rtmutex wakeup intermediate state TASK_RUNNING_MUTEX
    
       Results in missed wakeups from wake_up*()
    
       waiter is woken by mutex wakeup
       	  waiter->state = TASK_RUNNING_MUTEX;
       ....
       acquires_lock();
       restore_state();
    
       Until the waiter has restored its state wake_up*() will fail.
    
    Solution:
    
    Instead of setting the state to TASK_RUNNING_MUTEX in the mutex wakeup
    case we logically OR TASK_RUNNING_MUTEX to the current waiter
    state. This keeps the original bits (TASK_INTERRUPTIBLE /
    TASK_UNINTERRUPTIBLE) intact and lets wakeups succeed. When a task
    blocks on a lock in state TASK_INTERRUPTIBLE and is woken up by a real
    wakeup, then we store the state = TASK_RUNNING for the restore and can
    safely use TASK_UNINTERRUPTIBLE from that point to avoid further
    wakeups which just let us loop in the lock code.
    
    This also removes the extra TASK_RUNNING_MUTEX flags from the
    wakeup_process*() functions as they are not longer necessary.
    Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
    487ac708
sched.h 73.3 KB