sched discussion
[tip: sched/core] sched: Update time before requeueing delayed entities
LLM 分析
sched: 在重排队 delayed entity 前更新当前时间
系列概况
- 标题:
[tip: sched/core] sched: Update time before requeueing delayed entities - 作者:Vincent Guittot
<vincent.guittot@linaro.org> - 提交者:Peter Zijlstra (Intel)
<peterz@infradead.org> - 版本:tip-bot2 自动通告的已合并 commit,无独立版本号(单 patch)
- 规模:1 个文件,+2 行(
1 file changed, 2 insertions(+)) - 修改文件:
kernel/sched/fair.c,仅改动requeue_delayed_entity()函数 - 代码统计:
kernel/sched/fair.c | 2 ++ - Message-ID:
178673615898.442315.12755541915005920303.tip-bot2@tip-bot2 - 完整性:tip-bot2 merge notice,正文含 GitWeb commit 链接、commit message 全文与 hunk 上下文,可独立理解;唯一一封邮件,无系列回复
补丁目的
CFS 调度器在 requeue_delayed_entity() 中把"被延迟出队"的任务(标记 sched_delayed 的 SLEEPING 任务)重新挂回 runqueue 时,需要先计算它累积的 lag(应运行时间减去实际运行时间),再据此补偿 vruntime。
update_entity_lag() 内部依赖 rq 上的"当前时间"(cfs_rq->clock_task 等)来计算两次统计窗口之间的差值。如果不先 update_curr(cfs_rq) 把时间推到 now,runqueue 的 clock_task 可能仍是上次记账时的旧值,差值被压缩,lag 偏小,delayed 任务被少补偿。
这是一个隐性公平性 bug:delayed entity 在 wake-up 重排队时被少算了等待补偿。
旧流程的问题
requeue_delayed_entity(se)
|
+-> update_entity_lag(cfs_rq, se)
|
+-> dequeue / requeue decision
clock_task 若仍是陈旧值,差值被压缩,lag 偏小,delayed 任务拿不到足额 vruntime 补偿,调度公平性下降。
新流程
requeue_delayed_entity(se)
|
+-> update_curr(cfs_rq) [NEW line]
|
+-> update_entity_lag(cfs_rq, se)
|
+-> dequeue / requeue decision
只多一行 update_curr(cfs_rq),但保证 lag 计算使用的是 now 而非陈旧快照。
关键实现
补丁只动了 kernel/sched/fair.c 的 requeue_delayed_entity():
requeue_delayed_entity(struct sched_entity *se)
{
struct cfs_rq *cfs_rq = cfs_rq_of(se);
struct sched_entity *curr = cfs_rq->curr;
update_curr(cfs_rq); /* NEW line */
WARN_ON_ONCE(!se->sched_delayed);
WARN_ON_ONCE(!se->on_rq);
if (update_entity_lag(cfs_rq, se)) {
cfs_rq->nr_queued--;
if (se != cfs_rq->curr)
...
}
}
update_curr() 刷新 cfs_rq->clock_task、cfs_rq->clock、curr->exec_start 等基于 now 的统计点;后续 update_entity_lag() 读到的是真实当前时间。
类比
把 delayed entity 想象成自习课中途离开教室 10 分钟的学生。学生回到座位(requeue)时,老师要补录他落下多少分钟笔记(lag)。
如果老师不抬头看墙上的钟,凭印象写"大概只落下 3 分钟",那他实际落下的 10 分钟就丢了。update_curr(cfs_rq) 就是老师先看一眼钟、把"现在几点"校准,再算学生落下多少。
也可以从会计角度:CFS 的 clock_task 是 runqueue 的"会计时钟",任务执行 / 睡眠 / 被延迟出队期间它都可能没被推进;跨时段 lag 结算前必须先把会计时钟对齐到 wall clock now,否则就是用上周的报表算这个月的工资。
Highlight:风险与注意点
- 影响范围:所有使用 delayed dequeue 机制的 CFS 任务(典型为短 sleep 后被 wake-up 的 event-driven worker、kernel thread),都会从此补丁获益。
- 回归风险:
update_curr()会顺带刷新curr->exec_start等统计;如果有别的路径依赖"requeue_delayed_entity调用前clock_task仍是旧值",行为可能出现细微差异,需要 scheduler latency / fairness 基准回归。 - 可观察点:在未打补丁内核上,可用
perftraceupdate_entity_lag返回值,观察 delayed 任务 wake-up 时 lag 是否显著偏小。 - 后续观察:Vincent Guittot 持续重构 CFS dequeue / requeue 与 delayed entity 路径,未来可能还有更多"先 update_curr 再算 lag"的同类清理。
一句话总结
CFS 在重排 delayed entity 前先 update_curr(),确保 update_entity_lag() 读到当前时间,修正 delayed 任务因 lag 偏小而被少补偿的公平性 bug。