Re: [PATCH 09/18] sched_ext: Block proxy donors across scheduler transitions
From: Peter Zijlstra
Date: Thu Sep 10 2026 - 07:02:46 EST
On Mon, Aug 31, 2026 at 03:42:19PM +0200, Andrea Righi wrote:
> Proxy execution retains mutex-blocked donors on the runqueue so their
> scheduling context can execute a lock owner. sched_ext cannot safely retain
> such donors unless the BPF scheduler explicitly participates in their
> admission and ordering.
>
> Make sched_ext reject retained donors by default. Implement
> scx_allow_proxy_exec() to force blocked EXT tasks through the regular block
> path in schedule().
>
> Also fully deactivate any retained proxy donor in sched_change_begin()
> before changing its scheduling class. This prevents sched_setscheduler(),
> PI transitions and sched_ext activation from carrying an existing proxy
> session into the new class.
>
> Some RT/DL PI transitions could usefully preserve the proxy session. For
> example, an RT waiter can boost a FAIR donor which is itself blocked on a
> non-PI mutex; retaining the donor would allow the boosted context to keep
> proxy-executing that mutex owner. Doing so safely requires defining which
> scheduling classes can carry retained proxy state across a transition. Keep
> the conservative reset for now and leave compatible RT/DL PI chains for
> future work.
>
> This is a preparatory change to support proxy execution with sched_ext.
>
> Signed-off-by: Andrea Righi <arighi@xxxxxxxxxx>
> ---
> kernel/sched/core.c | 9 +++++++++
> kernel/sched/ext/ext.c | 2 +-
> 2 files changed, 10 insertions(+), 1 deletion(-)
>
> 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);
>
> diff --git a/kernel/sched/ext/ext.c b/kernel/sched/ext/ext.c
> index f3e59f4fad4ac..d5ed996ebfb4c 100644
> --- a/kernel/sched/ext/ext.c
> +++ b/kernel/sched/ext/ext.c
> @@ -26,7 +26,7 @@ DEFINE_RAW_SPINLOCK(scx_sched_lock);
>
> bool scx_allow_proxy_exec(const struct task_struct *p)
> {
> - return true;
> + return p->sched_class != &ext_sched_class;
> }
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).
We most certainly don't want to do this on every sched class change. It
isn't even gated by scx_allow_proxy_exec().