[PATCH 6/6 v3] sched/eevdf: Speedup short slice task scheduling
From: Vincent Guittot
Date: Wed Jun 24 2026 - 11:23:54 EST
When a task with a shorter slice is enqueued, we protect the running
task which has a longer slice until it becomes ineligible instead of a
full slice in order to speedup the switch to other tasks until the task
with the shortest slice is scheduled. This helps to the task to not wait
too many full slices before running.
Signed-off-by: Vincent Guittot <vincent.guittot@xxxxxxxxxx>
Tested-by: K Prateek Nayak <kprateek.nayak@xxxxxxx>
---
kernel/sched/fair.c | 52 +++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 50 insertions(+), 2 deletions(-)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index f972987618e7..7c541f27a1ed 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -813,6 +813,48 @@ u64 avg_vruntime(struct cfs_rq *cfs_rq)
return cfs_rq->zero_vruntime;
}
+/*
+ * Compute the vruntime until which the entity remains eligible when it runs
+ * or is about to run on the CPU. We use this value to set vprot to the min
+ * value until which other entities would not be picked anyway.
+ * \Sum (v_i - v0)*w_i
+ * V = ------------------- + v0
+ * \Sum w_i
+ *
+ * We want V' for (v_se - v0) == 0. Previous entity has already been enqueued
+ * in the rb tree and next is already dequeued so
+ *
+ * cfs_rq->sum_w_vruntime
+ * V' = ------------------------- + v0
+ * cfs_rq->sum_weight + w_se
+
+ */
+static u64 eligible_vruntime(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+ struct sched_entity *curr = cfs_rq->curr;
+ long weight = cfs_rq->sum_weight;
+ s64 delta = 0;
+
+ if (weight) {
+ s64 runtime = cfs_rq->sum_w_vruntime;
+
+ weight += avg_vruntime_weight(cfs_rq, se->load.weight);
+
+ /* sign flips effective floor / ceiling */
+ if (runtime < 0)
+ runtime -= (weight - 1);
+
+ delta = div64_long(runtime, weight);
+ } else {
+ /*
+ * When there is but one element, it is the average.
+ */
+ delta = 0;
+ }
+
+ return cfs_rq->zero_vruntime + delta + 1;
+}
+
static inline u64 cfs_rq_max_slice(struct cfs_rq *cfs_rq);
/*
@@ -1090,8 +1132,14 @@ static inline void set_protect_slice(struct cfs_rq *cfs_rq, struct sched_entity
slice = cfs_rq_min_slice(cfs_rq);
slice = min(slice, se->slice);
- if (slice != se->slice)
- vprot = min_vruntime(vprot, se->vruntime + calc_delta_fair(slice, se));
+
+ /* If there are shorter slices than se's one */
+ if (slice != se->slice) {
+ if (sched_feat(PREEMPT_SHORT))
+ vprot = min_vruntime(vprot, eligible_vruntime(cfs_rq, se));
+ else
+ vprot = min_vruntime(vprot, se->vruntime + calc_delta_fair(slice, se));
+ }
se->vprot = vprot;
}
--
2.43.0