Re: [PATCH v2] sched/eevdf: Fix sched idle task group preemption
From: Josh Don
Date: Wed Oct 21 2026 - 12:52:45 EST
On Wed, Oct 21, 2026 at 7:50 AM Peter Zijlstra <peterz@xxxxxxxxxxxxx> wrote:
>
> On Wed, Oct 21, 2026 at 04:41:52PM +0300, Kayra Cizmeci wrote:
> > On Wed, Oct 21, 2026 at 03:32:59PM +0200, Vincent Guittot wrote:
> > > On Wed, 21 Oct 2026 at 15:13, Peter Zijlstra <peterz@xxxxxxxxxxxxx> wrote:
>
> > > > What is the actual semantics of cpu.idle nonsense? Why do we care about
> > > > this common ancestor?
> > >
> > > AFAICT, cpu.idle applied to one level and against entities at the same level
> > >
> >
> > Yeah. Like on here:
> >
> > ROOT
> > /\
> > / \
> > / \
> > GA* GB
> > | /\
> > V / \
> > TA GC* GD
> > | |
> > V V
> > TB TC
>
> (marked GA and GC with * to denote their 'idleness')
>
> > If GA is idle and GB is not, while GC is idle and were looking to TA and
> > TB we gotta choose TB. But if we just look to GC and GA we would choose
> > neither. .idle just applies to one level as Vincent says.
>
> Yeah, that's what we used to do, but the more I think about this, the
> less sense it makes!
>
> Josh added this (added to Cc now), but we have a number of Google folks
> on Cc already. It would be good to hear how this is actually used.
>
>
> So in your example TA and TB are both inside an idle group, and
> therefore one can argue their behaviour should be like !idle. But their
> common ancestor is root, and so the fact that they're contained in idle
> groups gets lost (which seems crazeh).
TA and TB have a matching se of GA and GB, since those entities are
siblings under the common ancestor. Since GB is not idle but GA is, I
would argue that TB should preempt TA.
Consider GA and GB as groups representing different users, and user GB
has internally decided to create an idle cgroup GC to adjust
competition between its own tasks (TB and TC). This should not affect
GB's overall preemption ability against other users.
However in practice doing the exact computation to determine
preemption for relative idle properties (especially on wakeup) is
expensive and perhaps not strictly required. This is also why e.g. the
whole sched_idle_rq stuff is imprecise. We keep an overall tally of
the number of tasks that have a cpu.idle ancestor cgroup and use that
for wakeup placement, but if we were trying to be perfect we would
need to consider the matching_se stuff for that as well. What I'd say
there though is that imprecise placement is better than imprecise
preemption.
So overall, I would say the find_matching_se() stuff gives the more
ideal preemption decision; my first preference would be to keep it. It
avoids a regression with users who delegate cpu.idle internally within
their own cgroup hierarchy. FWIW wakeup preemption already does a
cgroup ancestor walk via update_curr; find_matching_se is similar in
spirit.
But to be clear I also don't think it would be terrible if we did
something like you suggest, cache whether a cgroup has _any_ cpu.idle
ancestor and then just make a single decision on wakeup comparing this
for the two tasks. The result of which is TC preempts T{AB}, but TA
and TB don't preempt each other. In which case I would suggest we
cache that as a part of updating cpu.idle so that we can avoid a
pointer chasing loop in se_is_idle().
Either of these two will at least also restore some semblance of
respecting cgroup cpu.idle in wakeup, as the flattening made it only
consider task level SCHED_IDLE.
>
> But worse I think is T{AB} vs TC. In that case none of the common
> ancestors (root,GB) resp. is idle. But T{AB} being inside idle should,
> IMO. definitely matter vs TC, which has no idle anywhere.
>
> So I think I would very much like to change the semantics here. The
> current stuff makes no sense.
>
> Anybody, please chime in with how this idle crap is used and expected to
> work.
Hopefully the above makes the use a bit more clear; cpu.idle is both a
weight thing and a preemption thing. The weight part is respected
naturally by the hierarchy, and it would be ideal to try to respect
the preemption part as much as feasible.
Best,
Josh