Re: [BUG] Apparent lost wakeups

From: Peter Zijlstra

Date: Tue Oct 13 2026 - 07:06:35 EST


On Tue, Oct 13, 2026 at 03:59:36PM +0530, K Prateek Nayak wrote:

> Essentially:
>
> /* rq->next_class starts as fair_sched_class */
>
> pick_next_task()
> /* Finishes ->pick_task() for stop, dl, rt */
> pick_task_fair()
> sched_balance_newidle()
> raw_spin_rq_unlock()
> activate_task(rq0, p) /* fair */
> /* p->on_rq but not curr */
> rq->next_class = fair_sched_class;
>
> __sched_setscheduler()
> /* Upgrades p to FIFO */
> sched_change_end()
> /* Does not change rq->next_class */
> rq_unlock()
>
> raw_spin_rq_lock()
>
> if (this_rq->cfs.h_nr_queued)
> /* Skipped! No fair task */
>
> if (rq_modified_above(this_rq, &fair_sched_class))
> /* Skipped: rq->nex_class is still fair */
>
> return 0;
> return NULL;
>
> pick_task_idle()
> return rq->idle;
>
> /* In __schedule() */
> clear_tsk_need_resched();
>
> /* Goes idle with rq->nr_running = 1 and no need_resched() */

Excellent Changelog material that ;-)

>
> > Does something like so make sense?
>
> Couple nits below.
>
> >
> > That is, any task on the rq cares about promotion, only the current
> > running task cares about demotion.
> >
> > diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> > index 047fbe8ef298..2a8bf562a769 100644
> > --- a/kernel/sched/core.c
> > +++ b/kernel/sched/core.c
> > @@ -11261,7 +11261,7 @@ void sched_change_end(struct sched_change_ctx *ctx)
> > if (p->sched_class->switched_to)
> > p->sched_class->switched_to(rq, p);
> >
> > - if (ctx->running) {
> > + if (ctx->queued) {
>
> I think this branch should just call wakeup_preempt() to account
> for p->sched_class == rq->next_class in case p is upgraded to
> same class as rq->curr.

Yes, that'll do.

> > /*
> > * If this was a class promotion; let the old class
> > * know it got preempted. Note that none of the
> > @@ -11272,6 +11272,9 @@ void sched_change_end(struct sched_change_ctx *ctx)
> > rq->next_class->wakeup_preempt(rq, p, 0);
> > rq->next_class = p->sched_class;
> > }
> > + }
> > +
> > + if (ctx->running) {
> > /*
> > * If this was a degradation in class; make sure to
> > * reschedule.
>
> This looks correct. Upgrade keeps the task running and degrade
> re-evaluates the selection.

Can you turn all this into a nice patch -- you've done all the hard work
on it anyway.

Thanks!