summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Guittot <vincent.guittot@linaro.org>2026-06-24 17:12:29 +0200
committerPeter Zijlstra <peterz@infradead.org>2026-06-30 10:56:55 +0200
commit0d1e7a2bab35dbc898e8a6aa29fd074dafbbccda (patch)
tree404addb0e072433fecda167b32696c66d9c241bd
parent7cd2ef17de5e11612001e98b6319f1793239b243 (diff)
sched/eevdf: Speedup short slice task scheduling
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@linaro.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Tested-by: K Prateek Nayak <kprateek.nayak@amd.com> Link: https://patch.msgid.link/20260624151229.1710703-7-vincent.guittot@linaro.org
-rw-r--r--kernel/sched/fair.c71
1 files changed, 69 insertions, 2 deletions
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 2547a97921ac..c5759107b8be 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -777,6 +777,67 @@ u64 avg_vruntime(struct cfs_rq *cfs_rq)
return cfs_rq->zero_vruntime;
}
+/*
+ * \Sum (v_i - v0)*w_i
+ * V = ------------------- + v0
+ * \Sum w_i
+ *
+ * Let W = \Sum w_i, and move v_j such that 'v_j == V', thus:
+ *
+ * V = 1/W * {(v_j - v0)*w_j + \Sum_i!=j (v_i - v0)*w_i} + v0
+ *
+ * v_j = 1/W * {(v_j - v0)*w_j + \Sum_i!=j (v_i - v0)*w_i} + v0
+ *
+ * v_j = 1/W * (v_j - v0)*w_j + 1/W * \Sum_i!=j (v_i - v0)*w_i + v0
+ *
+ * v_j - 1/W * (v_j - v0)*w_j = 1/W * \Sum_i!=j (v_i - v0)*w_i + v0
+ *
+ * v_j*W - (v_j - v0)*w_j = \Sum_i!=j (v_i - v0)*w_i + v0*W
+ *
+ * v_j*(W - w_j) + v0*w_j = \Sum_i!=j (v_i - v0)*w_i + v0*W
+ *
+ * v_j*(W - w_j) = \Sum_i!=j (v_i - v0)*w_i + v0*(W - w_j)
+ *
+ * \Sum_i!=j (v_i - v0)*w_i
+ * v_j = ------------------------ + v0
+ * W - w_j
+ *
+ * When v_j happens to be curr, then '\Sum_i!=j (v_i - v0)*w_i'
+ * is cfs_rq->sum_w_runtime, and 'W - w_j' is cfs_rq->sum_weight, since curr
+ * is not included in the sum.
+ */
+static u64 ineligible_vruntime(struct cfs_rq *cfs_rq)
+{
+ struct sched_entity *curr = cfs_rq->curr;
+ long weight = cfs_rq->sum_weight;
+ s64 delta = 0;
+
+ if (curr && !curr->on_rq)
+ curr = NULL;
+
+ /*
+ * This is called from set_next_task_fair(.first=true) /
+ * set_protect_slice() so curr had better be set and on_rq.
+ */
+ WARN_ON_ONCE(!curr);
+
+ if (weight) {
+ s64 runtime = cfs_rq->sum_w_vruntime;
+
+ /*
+ * Do not add @curr to obtain the effective '- w_j' terms.
+ */
+
+ /* sign flips effective floor / ceiling */
+ if (runtime < 0)
+ runtime -= (weight - 1);
+
+ delta = div64_long(runtime, weight);
+ }
+
+ return cfs_rq->zero_vruntime + delta + 1;
+}
+
static inline u64 cfs_rq_max_slice(struct cfs_rq *cfs_rq);
/*
@@ -1058,8 +1119,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, ineligible_vruntime(cfs_rq));
+ else
+ vprot = min_vruntime(vprot, se->vruntime + calc_delta_fair(slice, se));
+ }
se->vprot = vprot;
}