• Thomas Gleixner's avatar
    rtmutex: Fix deadlock detector for real · 397335f0
    Thomas Gleixner authored
    The current deadlock detection logic does not work reliably due to the
    following early exit path:
    
    	/*
    	 * Drop out, when the task has no waiters. Note,
    	 * top_waiter can be NULL, when we are in the deboosting
    	 * mode!
    	 */
    	if (top_waiter && (!task_has_pi_waiters(task) ||
    			   top_waiter != task_top_pi_waiter(task)))
    		goto out_unlock_pi;
    
    So this not only exits when the task has no waiters, it also exits
    unconditionally when the current waiter is not the top priority waiter
    of the task.
    
    So in a nested locking scenario, it might abort the lock chain walk
    and therefor miss a potential deadlock.
    
    Simple fix: Continue the chain walk, when deadlock detection is
    enabled.
    
    We also avoid the whole enqueue, if we detect the deadlock right away
    (A-A). It's an optimization, but also prevents that another waiter who
    comes in after the detection and before the task has undone the damage
    observes the situation and detects the deadlock and returns
    -EDEADLOCK, which is wrong as the other task is not in a deadlock
    situation.
    Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Reviewed-by: default avatarSteven Rostedt <rostedt@goodmis.org>
    Cc: Lai Jiangshan <laijs@cn.fujitsu.com>
    Cc: stable@vger.kernel.org
    Link: http://lkml.kernel.org/r/20140522031949.725272460@linutronix.deSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    397335f0
rtmutex.c 30.1 KB