Re: [PATCH 04/18] sched/core: Avoid false migration warning for proxy donors

From: Andrea Righi

Date: Tue Sep 15 2026 - 13:32:43 EST


On Tue, Sep 15, 2026 at 06:05:19PM +0200, Andrea Righi wrote:
> On Thu, Sep 10, 2026 at 12:06:52PM +0200, Peter Zijlstra wrote:
> > On Mon, Aug 31, 2026 at 03:42:14PM +0200, Andrea Righi wrote:
> > > Proxy execution can move a blocked donor's scheduling context to the
> > > lock owner's CPU even when the donor is migration-disabled. The donor
> > > does not execute there, and its original execution CPU remains recorded
> > > in wake_cpu.
> > >
> > > set_task_cpu() warns unconditionally for migration-disabled tasks, so a
> > > subsequent proxy migration or the wakeup path returning the donor home
> > > triggers a false positive. Moving a blocked scheduling context does not
> > > violate the migration-disabled execution context.
> > >
> > > Exclude blocked proxy donors from the warning. The proxy wakeup path
> > > restores an executable placement before clearing the blocked state.
> > >
> > > This is a preparatory fix for enabling proxy execution together with
> > > sched_ext.
> > >
> > > Acked-by: John Stultz <jstultz@xxxxxxxxxx>
> > > Signed-off-by: Andrea Righi <arighi@xxxxxxxxxx>
> > > ---
> > > kernel/sched/core.c | 9 ++++++++-
> > > 1 file changed, 8 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> > > index 14d0d5c884393..0a2eabadfee02 100644
> > > --- a/kernel/sched/core.c
> > > +++ b/kernel/sched/core.c
> > > @@ -3351,6 +3351,8 @@ void relax_compatible_cpus_allowed_ptr(struct task_struct *p)
> > > void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
> > > {
> > > unsigned int state = READ_ONCE(p->__state);
> > > + bool proxy_migrated = sched_proxy_exec() && p->is_blocked &&
> > > + task_cpu(p) != p->wake_cpu;
> > >
> > > /*
> > > * We should never call set_task_cpu() on a blocked task,
> > > @@ -3386,7 +3388,12 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
> > > */
> > > WARN_ON_ONCE(!cpu_online(new_cpu));
> > >
> > > - WARN_ON_ONCE(is_migration_disabled(p));
> > > + /*
> > > + * Proxy execution can move a blocked task's scheduling context to any
> > > + * CPU without moving its migration-disabled execution context. The
> > > + * wakeup path will return the task to a CPU where it can execute.
> > > + */
> > > + WARN_ON_ONCE(is_migration_disabled(p) && !proxy_migrated);
> > >
> > > trace_sched_migrate_task(p, new_cpu);
> >
> > I'm not sure why we're not hitting this upstream?
>
> I think this can be hit upstream as well. I'll try to create a reproducer.

And I can reproduce this with the latest tip/master:

proxy_migrate_repro: donor blocking on CPU0 with migration disabled
proxy_migrate_repro: donor moved from CPU0 to CPU1
WARNING: kernel/sched/core.c:3389 at set_task_cpu+0x1d3/0x280
...
Call Trace:
try_to_wake_up+0x43f/0x780
__mutex_unlock_slowpath+0x330/0x540
owner_fn+0x9f/0xc0 [proxy_migrate_repro]
...
proxy_migrate_repro: donor woke on CPU0, task_cpu=0
proxy_migrate_repro: completed

The reproducer creates a mutex owner on CPU1 and a migration-disabled waiter on
CPU0. The waiter is proxy-migrated to CPU1 while blocked. When the owner
releases the mutex, try_to_wake_up() returns the waiter to its pinned CPU0
through set_task_cpu(), triggering the warning.

I guess I can send this as a separate fix, it doesn't necessarily need to be in
this series.

Thanks,
-Andrea