[PATCH 4/8] sched/eevdf: Decay positive lag of sleeping entities
From: Vincent Guittot
Date: Mon Sep 21 2026 - 13:13:30 EST
Similarly to delayed dequeue that enables an entity to decay its negative
lag while sleeping, a task should not keep a positive lag forever.
The sleep duration and the weight of the entity is used to decay the
positive lag at wakeup.
Signed-off-by: Vincent Guittot <vincent.guittot@xxxxxxxxxx>
---
kernel/sched/fair.c | 33 +++++++++++++++++++++++++++++++--
1 file changed, 31 insertions(+), 2 deletions(-)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index e6eb9a4c03be..4230954d10d0 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -896,6 +896,32 @@ bool update_entity_lag(struct cfs_rq *cfs_rq, struct sched_entity *se)
return avruntime - vlag != se->vruntime;
}
+static __always_inline
+void decay_entity_lag(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
+{
+ s64 vlag = se->vlag;
+ s64 delta_exec;
+
+ WARN_ON_ONCE(se->on_rq);
+
+ /* Negative lag implies delayed dequeue */
+ if (vlag <= 0)
+ return;
+
+ if (flags & ENQUEUE_MIGRATED)
+ return;
+
+ /* Compute the sleep time */
+ delta_exec = rq_clock_task(rq_of(cfs_rq)) - se->exec_start;
+ if (unlikely(delta_exec <= 0))
+ return;
+
+ vlag -= calc_delta_fair(delta_exec, se);
+
+ /* vlag can't become negative while sleeping */
+ se->vlag = max(0, vlag);
+}
+
/*
* Entity is eligible once it received less service than it ought to have,
* eg. lag >= 0.
@@ -7986,7 +8012,7 @@ static void
enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
{
int rq_h_nr_queued = rq->cfs.h_nr_queued;
- int task_new = !(flags & ENQUEUE_WAKEUP);
+ int task_wake = flags & ENQUEUE_WAKEUP;
struct sched_entity *se = &p->se;
struct cfs_rq *cfs_rq = &rq->cfs;
unsigned long weight;
@@ -8019,6 +8045,9 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
if (p->in_iowait)
cpufreq_update_util(rq, SCHED_CPUFREQ_IOWAIT);
+ if (task_wake)
+ decay_entity_lag(cfs_rq, se, flags);
+
/*
* XXX comment on the curr thing
*/
@@ -8057,7 +8086,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
* into account, but that is not straightforward to implement,
* and the following generally works well enough in practice.
*/
- if (!task_new)
+ if (task_wake)
check_update_overutilized_status(rq);
assert_list_leaf_cfs_rq(rq);
--
2.53.0