[PATCH] locking/mutex: clear stale blocked_donor when blocked_on is cleared
From: Hui Su
Date: Wed Sep 02 2026 - 03:30:35 EST
Proxy execution records in current->blocked_donor the blocked donor
whose scheduling context the mutex owner is executing on behalf of.
The mutex unlock slowpath uses this backlink to hand the mutex directly
to that donor when it is still blocked on the mutex being unlocked.
The donor's blocked_on link can be cleared before the owner consumes the
backlink. For example, an interruptible mutex acquisition can be
interrupted by a signal and leave the owner with the blocked_donor from
the previous proxy pick.
If the owner later reaches another mutex unlock slowpath before being
rescheduled, the stale backlink is treated as an active donor and
forces the proxy-handoff path. Since blocked_donor is currently cleared
only when next_lock == lock, it can survive that unlock as well.
When __get_task_blocked_on() returns NULL, there is no mutex through
which this blocked_donor backlink can provide a direct handoff target,
so clear it.
Do not clear the backlink when next_lock names a different mutex. The
owner may hold multiple mutexes and the donor can still legitimately be
blocked through another one.
Fixes: 1628b25248d0 ("sched: Add blocked_donor link to task for smarter mutex handoffs")
Signed-off-by: Hui Su <sh_def@xxxxxxx>
---
kernel/locking/mutex.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
index 942a939cee95..63b9cc401bb0 100644
--- a/kernel/locking/mutex.c
+++ b/kernel/locking/mutex.c
@@ -1046,6 +1046,8 @@ static noinline void __sched __mutex_unlock_slowpath(struct mutex *lock, unsigne
next = get_task_struct(donor);
__clear_task_blocked_on(next, lock);
current->blocked_donor = NULL;
+ } else if (!next_lock) {
+ current->blocked_donor = NULL;
}
raw_spin_unlock(&donor->blocked_lock);
}
--
2.54.0