Re: [PATCH 02/12] sched/core: Skip put_prev_task/set_next_task re-entry for sched_ext donors

From: Andrea Righi

Date: Thu Jul 02 2026 - 14:47:08 EST


On Thu, Jul 02, 2026 at 08:24:06PM +0200, Peter Zijlstra wrote:
> On Thu, Jul 02, 2026 at 07:09:18PM +0200, Andrea Righi wrote:
> > In __schedule(), the proxy-exec donor-stabilization block calls
> > put_prev_task() and set_next_task() when rq->donor == prev_donor and
> > prev != next.
> >
> > For sched_ext tasks, re-entering set_next_task_scx() for a donor that
> > has already been seen by BPF ops.running via the normal pick path causes
> > issues. It fires SCX_CALL_OP_TASK(sch, running, rq, donor) a second
> > time, and sch->ops dispatch can land on a vtable slot in a state that
> > yields a NULL function pointer or corrupts the stack.
> >
> > Fix this by skipping the put_prev_task/set_next_task re-entry when the
> > donor is in the ext_sched_class, since sched_ext tracks curr/donor
> > itself.
>
> This really sounds like a bug in ext; how is this different from the
> sched_change pattern doing a put/set cycle?

I think you're right, the patch differs from sched_change because it doesn't
bracket the put/set cycle with a dequeue/enqueue, but sched_ext still needs to
support the put/set contract.

The underlying problem is that set_next_task_scx() triggers ops.running() for a
blocked proxy donor even though the donor never becomes the execution context,
so we need to prevent triggering ops.running() in this case. But this should be
handled in sched_ext by pairing ops.running()/ops.stopping() only when the donor
actually runs. This is addressed later in the series with explicit running-state
tracking. I'll drop this core special case and rework that sched_ext fix.

Thanks,
-Andrea