Re: [PATCH v26 00/10] Simple Donor Migration for Proxy Execution

From: Peter Zijlstra

Date: Fri Mar 27 2026 - 07:52:35 EST


On Wed, Mar 25, 2026 at 04:22:14PM +0530, K Prateek Nayak wrote:

I tried to have a quick look, but I find it *very* hard to make sense of
the differences.

(could be I just don't know how to operate github -- that seems a
recurrent theme)

Anyway, this:

> fd60c48f7b71 sched: Avoid donor->sched_class->yield_task() null traversal

That seems *very* dodgy indeed. Exposing idle as the donor seems ... wrong?


Anyway, you seem to want to drive the return migration from the regular
wakeup path and I don't mind doing that, provided it isn't horrible. But
we can do this on top of these patches, right?

That is, I'm thinking of taking these patches, they're in reasonable
shape, and John deserves a little progress :-)

I did find myself liking the below a little better, but I'll just sneak
that in.

---
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6822,7 +6822,6 @@ static struct task_struct *
find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf)
__must_hold(__rq_lockp(rq))
{
- enum { FOUND, DEACTIVATE_DONOR, MIGRATE, NEEDS_RETURN } action = FOUND;
struct task_struct *owner = NULL;
bool curr_in_chain = false;
int this_cpu = cpu_of(rq);
@@ -6838,8 +6837,7 @@ find_proxy_task(struct rq *rq, struct ta
clear_task_blocked_on(p, PROXY_WAKING);
return p;
}
- action = NEEDS_RETURN;
- break;
+ goto force_return;
}

/*
@@ -6874,16 +6872,14 @@ find_proxy_task(struct rq *rq, struct ta
__clear_task_blocked_on(p, NULL);
return p;
}
- action = NEEDS_RETURN;
- break;
+ goto force_return;
}

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);
- action = DEACTIVATE_DONOR;
- break;
+ goto deactivate;
}

owner_cpu = task_cpu(owner);
@@ -6894,8 +6890,7 @@ find_proxy_task(struct rq *rq, struct ta
*/
if (curr_in_chain)
return proxy_resched_idle(rq);
- action = MIGRATE;
- break;
+ goto migrate_task;
}

if (task_on_rq_migrating(owner)) {
@@ -6952,26 +6947,20 @@ find_proxy_task(struct rq *rq, struct ta
* guarantee its existence, as per ttwu_remote().
*/
}
-
- /* Handle actions we need to do outside of the guard() scope */
- switch (action) {
- case DEACTIVATE_DONOR:
- if (proxy_deactivate(rq, donor))
- return NULL;
- /* If deactivate fails, force return */
- p = donor;
- fallthrough;
- case NEEDS_RETURN:
- proxy_force_return(rq, rf, p);
- return NULL;
- case MIGRATE:
- proxy_migrate_task(rq, rf, p, owner_cpu);
- return NULL;
- case FOUND:
- /* fallthrough */;
- }
WARN_ON_ONCE(owner && !owner->on_rq);
return owner;
+
+deactivate:
+ if (proxy_deactivate(rq, donor))
+ return NULL;
+ /* If deactivate fails, force return */
+ p = donor;
+force_return:
+ proxy_force_return(rq, rf, p);
+ return NULL;
+migrate_task:
+ proxy_migrate_task(rq, rf, p, owner_cpu);
+ return NULL;
}
#else /* SCHED_PROXY_EXEC */
static struct task_struct *