Skip to content

Commit c653a41

Browse files
Fernand Sieberopsiff
authored andcommitted
sched/fair: Forfeit vruntime on yield
stable inclusion from stable-v6.12.63 category: bugfix [ Upstream commit 79104be ] If a task yields, the scheduler may decide to pick it again. The task in turn may decide to yield immediately or shortly after, leading to a tight loop of yields. If there's another runnable task as this point, the deadline will be increased by the slice at each loop. This can cause the deadline to runaway pretty quickly, and subsequent elevated run delays later on as the task doesn't get picked again. The reason the scheduler can pick the same task again and again despite its deadline increasing is because it may be the only eligible task at that point. Fix this by making the task forfeiting its remaining vruntime and pushing the deadline one slice ahead. This implements yield behavior more authentically. We limit the forfeiting to eligible tasks. This is because core scheduling prefers running ineligible tasks rather than force idling. As such, without the condition, we can end up on a yield loop which makes the vruntime increase rapidly, leading to anomalous run delays later down the line. Fixes: 147f3ef ("sched/fair: Implement an EEVDF-like scheduling policy") Signed-off-by: Fernand Sieber <sieberf@amazon.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lore.kernel.org/r/20250401123622.584018-1-sieberf@amazon.com Link: https://lore.kernel.org/r/20250911095113.203439-1-sieberf@amazon.com Link: https://lore.kernel.org/r/20250916140228.452231-1-sieberf@amazon.com Signed-off-by: Sasha Levin <sashal@kernel.org> (cherry picked from commit d5843e1530d8d4ebf2b34f0185d45828848f107a) Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
1 parent f80d6b2 commit c653a41

1 file changed

Lines changed: 13 additions & 1 deletion

File tree

kernel/sched/fair.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8783,7 +8783,19 @@ static void yield_task_fair(struct rq *rq)
87838783
*/
87848784
rq_clock_skip_update(rq);
87858785

8786-
se->deadline += calc_delta_fair(se->slice, se);
8786+
/*
8787+
* Forfeit the remaining vruntime, only if the entity is eligible. This
8788+
* condition is necessary because in core scheduling we prefer to run
8789+
* ineligible tasks rather than force idling. If this happens we may
8790+
* end up in a loop where the core scheduler picks the yielding task,
8791+
* which yields immediately again; without the condition the vruntime
8792+
* ends up quickly running away.
8793+
*/
8794+
if (entity_eligible(cfs_rq, se)) {
8795+
se->vruntime = se->deadline;
8796+
se->deadline += calc_delta_fair(se->slice, se);
8797+
update_min_vruntime(cfs_rq);
8798+
}
87878799
}
87888800

87898801
static bool yield_to_task_fair(struct rq *rq, struct task_struct *p)

0 commit comments

Comments
 (0)