Re: [PATCH v25 1/9] sched: Make class_schedulers avoid pushing current, and get rid of proxy_tag_curr()
From: Peter Zijlstra
Date: Wed Mar 18 2026 - 10:00:21 EST
On Wed, Mar 18, 2026 at 02:36:40PM +0100, Peter Zijlstra wrote:
> On Mon, Mar 16, 2026 at 11:04:28PM -0700, John Stultz wrote:
> > On Mon, Mar 16, 2026 at 10:41 PM K Prateek Nayak <kprateek.nayak@xxxxxxx> wrote:
> > > On 3/17/2026 10:19 AM, John Stultz wrote:
> > > >
> > > > I guess adding a new helper function to manually do the
> > > > put_prev/set_next could be added to the top level __schedule() logic
> > > > in the (prev != next) case, though we'll have to preserve the
> > > > prev_donor on the stack probably.
> > >
> > > That seems like the best option to me too.
> > >
> > > Also, deadline, RT, fair, and idle don't really care about the "next"
> > > argument of put_prev_task() and the only one that does care is
> > > put_prev_task_scx() to call switch_class() callback so putting it as
> > > either NULL or "rq->donor" should be safe.
> >
> > Ack.
> > Here's the change I'm testing tonight (against 6.18):
> > https://github.com/johnstultz-work/linux-dev/commit/0cc72a4923143f496e33711cbcc1afdf6d861ca6
> >
> > Feel free to suggest a better name for the helper function. It feels a
> > little clunky (and sort of sad right after getting rid of the clunky
> > proxy_tag_curr(), to re-add something so similar).
>
> Does this capture it?
>
> --- a/kernel/sched/core.c
> +++ b/kernel/sched/core.c
> @@ -7100,9 +7103,11 @@ static void __sched notrace __schedule(i
> pick_again:
> assert_balance_callbacks_empty(rq);
> next = pick_next_task(rq, rq->donor, &rf);
> - rq_set_donor(rq, next);
> rq->next_class = next->sched_class;
> if (sched_proxy_exec()) {
> + struct task_struct *prev_donor = rq->donor;
> +
> + rq_set_donor(rq, next);
> if (unlikely(next->blocked_on)) {
> next = find_proxy_task(rq, next, &rf);
> if (!next) {
> @@ -7114,6 +7119,24 @@ static void __sched notrace __schedule(i
> goto keep_resched;
> }
> }
> +
> + /*
> + * When transitioning like:
> + *
> + * prev next
> + * donor: B B
> + * curr: A B
> + *
> + * then put_prev_set_next_task() will not have done anything,
> + * since B == B. However, A might have missed a RT/DL balance
> + * opportunity due to being on_cpu.
> + */
> + if (next == rq->donor && next == prev_donor) {
&& next != prev
> + next->sched_class->put_prev_task(rq, next, next);
> + next->sched_class->set_next_task(rq, next, true);
> + }
> + } else {
> + rq_set_donor(rq, next);
> }
> picked:
> clear_tsk_need_resched(prev);