Re: [PATCH v2] sched/eevdf: Fix sched idle task group preemption

From: Peter Zijlstra

Date: Thu Oct 22 2026 - 17:22:31 EST


On Thu, Oct 22, 2026 at 10:49:36AM -0700, Josh Don wrote:
> > diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
> > index b5546cd27dba..779fcd5a2830 100644
> > --- a/kernel/sched/fair.c
> > +++ b/kernel/sched/fair.c
> > @@ -15767,6 +15767,40 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares)
> > return ret;
> > }
> >
> > +struct tg_set_idle_struct {
> > + long idle;
> > + int cpu;
> > +};
> > +
> > +static int tg_set_idle_up(struct task_group *tg, void *data)
> > +{
> > + struct tg_set_idle_struct *tsi = data;
> > + struct cfs_rq *grp_cfs_rq = tg_cfs_rq(tg, tsi->cpu);
> > + struct sched_entity *se = tg_se(tg, tsi->cpu);
> > + int old_idle = grp_cfs_rq->idle;
> > + long task_delta;
> > +
> > + grp_cfs_rq->idle += tsi->idle;
> > +
> > + if (!!old_idle == !!grp_cfs_rq->idle)
> > + return 0;
> > +
> > + task_delta = grp_cfs_rq->h_nr_queued - grp_cfs_rq->h_nr_idle;
> > + if (!task_delta)
> > + return 0;
> > +
> > + task_delta *= tsi->idle;
> > +
> > + for_each_sched_entity(se) {
> > + if (!se->on_rq)
> > + break;
> > +
> > + cfs_rq_of(se)->h_nr_idle += task_delta;
> > + }
> > +
> > + return 0;
> > +}
>
> Took me a bit to parse this double traversal. I think this is broken
> for the clear side?
>
> root
> |
> A ( 2 tasks)
> |
> B (3 tasks)
>
> If we start out with A marked as idle, then we have
> root: h_nr_idle = 5
> A: h_nr_idle = 3
> B: h_nr_idle = 0
>
> When we clear, we'll first start with B and subtract 3...
> root: h_nr_idle = 2
> A: h_nr_idle = 0
> B: h_nr_idle = 0
>
> Then we go to A and try to subtract 5 leading to
> root: h_nr_idle = -3
>

Argh. Yes, I seem to have gotten it wrong. I'll try again in the
morning.