Re: [PATCH 06/20 v3] sched/eevdf: Add min slice check when selecting CPU
From: Vincent Guittot
Date: Mon Nov 09 2026 - 10:35:13 EST
On Sat, 7 Nov 2026 at 09:57, Kayra Cizmeci <kayracizmeci@xxxxxxxxx> wrote:
>
>
> Hi Vincent,
>
>
> Sashiko reviewed this one so I'll just put here my own concerns instead
> of repeating.
>
>
> On Fri, Nov 06, 2026 at 04:19:33PM +0100, Vincent Guittot wrote:
>
> > Add a new level for selecting CPU when select_task_rq_fair() fails to find
> > an idle CPU. This last level compares the min slice to select a CPU where
> > the task could run 1st.
> > This helps a waking task to select a CPU where a longer slice runs
> > instead of one where a task with the same or shorter slice already runs.
> >
> > Signed-off-by: Vincent Guittot <vincent.guittot@xxxxxxxxxx>
> > ---
> > kernel/sched/core.c | 2 +-
> > kernel/sched/fair.c | 157 ++++++++++++++++++++++++++++----------------
> > 2 files changed, 102 insertions(+), 57 deletions(-)
> >
> > diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> > index 031efe7d49fb..d71da9069218 100644
> > --- a/kernel/sched/core.c
> > +++ b/kernel/sched/core.c
> > @@ -9012,7 +9012,7 @@ void __init sched_init(void)
> > rq->sd = NULL;
> > rq->rd = NULL;
> > rq->cpu_capacity = SCHED_CAPACITY_SCALE;
> > - rq->min_slice = ULONG_MAX;
> > + rq->min_slice = 0;
> > rq->balance_callback = &balance_push_callback;
> > rq->active_balance = 0;
> > rq->next_balance = jiffies;
> > diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
> > index cfc99b94d9ce..039dce244aaa 100644
> > --- a/kernel/sched/fair.c
> > +++ b/kernel/sched/fair.c
> > @@ -8842,11 +8842,25 @@ static inline int sched_balance_find_dst_cpu(struct sched_domain *sd, struct tas
> > return new_cpu;
> > }
> >
> > -static inline int __select_idle_cpu(int cpu, struct task_struct *p)
> > +static inline bool choose_sched_slice_rq(struct rq *rq, struct task_struct *p)
> > {
> > - if (choose_idle_cpu(cpu, p) && sched_cpu_cookie_match(cpu_rq(cpu), p))
> > + if (p->se.slice < get_rq_min_slice(rq))
> > + return true;
> > +
> > + return false;
> > +}
> > +
> > +static inline int __select_idle_cpu(int cpu, struct task_struct *p, int *slice_cpu)
> > +{
> > + if (!sched_cpu_cookie_match(cpu_rq(cpu), p))
> > + return -1;
> > +
> > + if (choose_idle_cpu(cpu, p))
> > return cpu;
> >
> > + if (*slice_cpu == -1 && choose_sched_slice_rq(cpu_rq(cpu), p))
> > + *slice_cpu = cpu;
> > +
> > return -1;
> > }
>
>
> Look here:
>
> CPU1: CPU2:
> FA RA
> FC
>
> CPU2 has 1 RT and 1 Fair tasks named RA and FC.
> Let's say RA is running on CPU2 and FC's slice is 10 ms.
>
> And let's say FA has 8 ms slice, and a fair task named TC is waking up
> with 9 ms slice:
>
> * We look to CPU1, 9 < 8 is false so we return false
>
> * We look to CPU2, 9 < 10 is true so we return it.
>
> But the problem is, CPU2 has a RT task running and we are going to
> compete with the RT task. In that case it can be worse than CPU1.
Yes, but we don't really know. The only thing we are sure of is that
TC will be the 1st fair task to run on CPU2 whereas it will wait
before running on CPU1. I tested more changes on top of patch 20 to
handle the case where the task is enqueued on a cpu chich run higher
sched class task, but I was not yet convinced by the result vs
complexity.
>
> So, I would suggest something like this or so:
>
>
> (My editor got crazy, so I had to copy this diff :<)
>
> diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
> index 262626455497..8b0dd858f332 100644
> --- a/kernel/sched/fair.c
> +++ b/kernel/sched/fair.c
> @@ -8876,10 +8876,8 @@ static inline int sched_balance_find_dst_cpu(struct sched_domain *sd, struct tas
>
> static inline bool choose_sched_slice_rq(struct rq *rq, struct task_struct *p)
> {
> - if (p->se.slice < get_rq_min_slice(rq))
> - return true;
> -
> - return false;
> + return p->se.slice < get_rq_min_slice(rq) &&
> + READ_ONCE(rq->curr)->sched_class == &fair_sched_class;
> }
>
> static inline int __select_idle_cpu(int cpu, struct task_struct *p, int *slice_cpu)
> @@ -9193,7 +9191,6 @@ select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target)
> bool has_idle_core = sched_smt_active() && test_idle_cores(target);
> unsigned long task_util, util_min, util_max, best_cap = 0;
> int fits, best_fits = ASYM_IDLE_THREAD_MISFIT;
> - unsigned long task_slice;
> int cpu, best_cpu = -1;
> struct cpumask *cpus;
> int nr = INT_MAX;
> @@ -9204,7 +9201,6 @@ select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target)
> task_util = task_util_est(p);
> util_min = uclamp_eff_value(p, UCLAMP_MIN);
> util_max = uclamp_eff_value(p, UCLAMP_MAX);
> - task_slice = p->se.slice;
>
> if (sched_feat(SIS_UTIL) && sd->shared) {
> /*
> @@ -9260,7 +9256,7 @@ select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target)
> else if (fits > 0)
> fits = ASYM_IDLE_THREAD_FITS;
>
> - } else if (fits > 0 && task_slice < get_rq_min_slice(cpu_rq(cpu))) {
> + } else if (fits > 0 && choose_sched_slice_rq(cpu_rq(cpu), p)) {
> fits = ASYM_BUSY_THREAD_FITS;
> cpu_cap = get_actual_cpu_capacity(cpu);
> } else {
>
>
>
> Cheers,
>
> Kayra :-)