Re: [PATCH 09/18] sched_ext: Block proxy donors across scheduler transitions

From: Andrea Righi

Date: Tue Sep 15 2026 - 17:40:47 EST


On Thu, Sep 10, 2026 at 01:41:58PM +0200, Peter Zijlstra wrote:
> On Thu, Sep 10, 2026 at 12:53:35PM +0200, Peter Zijlstra wrote:
> > On Mon, Aug 31, 2026 at 03:42:19PM +0200, Andrea Righi wrote:
>
> > > diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> > > index f142ab455b797..4bd956182af8d 100644
> > > --- a/kernel/sched/core.c
> > > +++ b/kernel/sched/core.c
> > > @@ -11302,6 +11302,15 @@ sched_change_begin(struct task_struct *p, const struct sched_class *next_class,
> > > flags |= DEQUEUE_NOCLOCK;
> > > }
> > >
> > > + /*
> > > + * Don't carry retained proxy state across scheduling class changes.
> > > + * Compatible RT/DL PI transitions could preserve the session so that a
> > > + * boosted donor continues proxy-executing its lock owner. Defining which
> > > + * class transitions can safely retain that state is left for future work.
> > > + */
> > > + if ((flags & DEQUEUE_CLASS) && next_class != p->sched_class)
> >
> > That's a tautology, having DEQUEUE_CLASS means next_class !=
> > ->sched_class.
> >
> > > + sched_proxy_block_task(rq, p);
> > > +
> > > if ((flags & DEQUEUE_CLASS) && p->sched_class->switching_from)
> > > p->sched_class->switching_from(rq, p);
> > >
>
> > Hmmmm... I don't like this. I was expecting this
> > sched_proxy_block_task() thing to be called in the big switcheroo
> > function when loading one of these ext thing. (scx_root_enable_ or
> > somesuch).

Agreed. The cleanup is required when sched_ext takes ownership of a task, not
for every scheduling-class transition.

Calling it from sched_change_begin() also breaks proxy exec across FAIR/RT/DL
transitions. I'll move it into the sched_ext enable and task-ownership
transition paths and test that approach.

> >
> > We most certainly don't want to do this on every sched class change. It
> > isn't even gated by scx_allow_proxy_exec().
>
> Why not do:
>
> switching_to_scx():
>
> + if (!scx_allow_proxy_exec(p))
> + sched_proxy_block_task(rq, p);

The scx_allow_proxy_exec() gate makes sense, but switching_to_scx() is called
from sched_change_end(). At that point, sched_change_begin() has already saved
ctx->queued = true for the retained donor and removed it from the old class.

Calling sched_proxy_block_task() there is too late: sched_change_end() would
still see the saved ctx->queued value and enqueue the blocked task in to EXT.
Also, p->sched_class already points to EXT even though the task has not yet been
enqueued there, while sched_proxy_block_task() dequeues through the current
class.

I think the cleanup needs to happen in the sched_ext ownership-transition path
immediately before sched_change_begin(). In this way ctx->queued is recorded as
false and the task is not restored into EXT.

I'll rework it along these lines and test the sched_ext enable /
ownership-transition paths.

Thanks,
-Andrea