summaryrefslogtreecommitdiff
path: root/kernel/locking
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2021-08-13 13:40:49 +0300
committerMinda Chen <minda.chen@starfivetech.com>2023-11-06 14:24:44 +0300
commiteb893f04744a485ef1a9e6c69f872a48e4932657 (patch)
treea86e06db5ed7869fe473b67b3ea2b347a2b8592b /kernel/locking
parent27b073576dcb1cac6c2855aa6688156903d4740e (diff)
downloadlinux-eb893f04744a485ef1a9e6c69f872a48e4932657.tar.xz
rtmutex: Add a special case for ww-mutex handling.
The lockdep selftest for ww-mutex assumes in a few cases the ww_ctx->contending_lock assignment via __ww_mutex_check_kill() which does not happen if the rtmutex detects the deadlock early. The testcase passes if the deadlock handling here is removed. This means that it will work if multiple threads/tasks are involved and not just a single one. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Diffstat (limited to 'kernel/locking')
-rw-r--r--kernel/locking/rtmutex.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index 6bb116c559b4..3665583361c0 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -1097,8 +1097,26 @@ static int __sched task_blocks_on_rt_mutex(struct rt_mutex_base *lock,
* which is wrong, as the other waiter is not in a deadlock
* situation.
*/
- if (owner == task)
+ if (owner == task) {
+#if defined(DEBUG_WW_MUTEXES) && defined(CONFIG_DEBUG_LOCKING_API_SELFTESTS)
+ /*
+ * The lockdep selftest for ww-mutex assumes in a few cases
+ * the ww_ctx->contending_lock assignment via
+ * __ww_mutex_check_kill() which does not happen if the rtmutex
+ * detects the deadlock early.
+ */
+ if (build_ww_mutex() && ww_ctx) {
+ struct rt_mutex *rtm;
+
+ /* Check whether the waiter should backout immediately */
+ rtm = container_of(lock, struct rt_mutex, rtmutex);
+
+ __ww_mutex_add_waiter(waiter, rtm, ww_ctx);
+ __ww_mutex_check_kill(rtm, waiter, ww_ctx);
+ }
+#endif
return -EDEADLK;
+ }
raw_spin_lock(&task->pi_lock);
waiter->task = task;