[PATCH 1/9] sched/core: Drop mutex locks before proxy rescheduling
From: Andrea Righi
Date: Mon Jul 06 2026 - 03:16:47 EST
find_proxy_task() can call proxy_resched_idle() while holding a mutex
wait_lock and the blocked task lock. Guard cleanup does not run until
after the return expression is evaluated.
proxy_resched_idle() invokes scheduling-class callbacks through
put_prev_set_next_task(). Calling those callbacks with the mutex locks
held prevents them from safely inspecting the proxy chain, as doing so
may require acquiring the same locks.
This is a preparatory change to support proxy execution in sched_ext. It
leaves the guard scope before calling proxy_resched_idle() so sched_ext
callbacks can safely inspect the proxy chain.
Signed-off-by: Andrea Righi <arighi@xxxxxxxxxx>
---
kernel/sched/core.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 3cc6fb1d20547..0139cd4a8be7e 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6923,7 +6923,7 @@ find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf)
if (!READ_ONCE(owner->on_rq) || owner->se.sched_delayed) {
/* XXX Don't handle blocked owners/delayed dequeue yet */
if (curr_in_chain)
- return proxy_resched_idle(rq);
+ goto resched_idle;
__clear_task_blocked_on(p, NULL);
goto deactivate;
}
@@ -6935,7 +6935,7 @@ find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf)
* and leave that CPU to sort things out.
*/
if (curr_in_chain)
- return proxy_resched_idle(rq);
+ goto resched_idle;
goto migrate_task;
}
@@ -6948,7 +6948,7 @@ find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf)
* case we should end up back in find_proxy_task(), this time
* hopefully with all relevant tasks already enqueued.
*/
- return proxy_resched_idle(rq);
+ goto resched_idle;
}
/*
@@ -6985,7 +6985,7 @@ find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf)
* So schedule rq->idle so that ttwu_runnable() can get the rq
* lock and mark owner as running.
*/
- return proxy_resched_idle(rq);
+ goto resched_idle;
}
/*
* OK, now we're absolutely sure @owner is on this
@@ -6997,6 +6997,8 @@ find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf)
WARN_ON_ONCE(owner && !owner->on_rq);
return owner;
+resched_idle:
+ return proxy_resched_idle(rq);
deactivate:
proxy_deactivate(rq, p);
return NULL;
--
2.55.0