Skip to content

Commit 6467822

Browse files
Peter ZijlstraKAGA-KOKO
authored andcommitted
locking/rtmutex: Prevent spurious EDEADLK return caused by ww_mutexes
rtmutex based ww_mutexes can legitimately create a cycle in the lock graph which can be observed by a blocker which didn't cause the problem: P1: A, ww_A, ww_B P2: ww_B, ww_A P3: A P3 might therefore be trapped in the ww_mutex induced cycle and run into the lock depth limitation of rt_mutex_adjust_prio_chain() which returns -EDEADLK to the caller. Disable the deadlock detection walk when the chain walk observes a ww_mutex to prevent this looping. [ tglx: Split it apart and added changelog ] Reported-by: Sebastian Siewior <[email protected]> Fixes: add4613 ("locking/rtmutex: Extend the rtmutex core to support ww_mutex") Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 37e8abf commit 6467822

File tree

1 file changed

+25
-0
lines changed

1 file changed

+25
-0
lines changed

kernel/locking/rtmutex.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,31 @@ static int __sched rt_mutex_adjust_prio_chain(struct task_struct *task,
656656
if (next_lock != waiter->lock)
657657
goto out_unlock_pi;
658658

659+
/*
660+
* There could be 'spurious' loops in the lock graph due to ww_mutex,
661+
* consider:
662+
*
663+
* P1: A, ww_A, ww_B
664+
* P2: ww_B, ww_A
665+
* P3: A
666+
*
667+
* P3 should not return -EDEADLK because it gets trapped in the cycle
668+
* created by P1 and P2 (which will resolve -- and runs into
669+
* max_lock_depth above). Therefore disable detect_deadlock such that
670+
* the below termination condition can trigger once all relevant tasks
671+
* are boosted.
672+
*
673+
* Even when we start with ww_mutex we can disable deadlock detection,
674+
* since we would supress a ww_mutex induced deadlock at [6] anyway.
675+
* Supressing it here however is not sufficient since we might still
676+
* hit [6] due to adjustment driven iteration.
677+
*
678+
* NOTE: if someone were to create a deadlock between 2 ww_classes we'd
679+
* utterly fail to report it; lockdep should.
680+
*/
681+
if (IS_ENABLED(CONFIG_PREEMPT_RT) && waiter->ww_ctx && detect_deadlock)
682+
detect_deadlock = false;
683+
659684
/*
660685
* Drop out, when the task has no waiters. Note,
661686
* top_waiter can be NULL, when we are in the deboosting

0 commit comments

Comments
 (0)