sched discussion
[PATCH] sched/core: Fix stale se.load when modifying nice value under sched_ext
LLM 分析
sched/core:修复 sched_ext 下修改 nice 后 se.load 过期问题
系列概况
- 标题:[PATCH] sched/core: Fix stale se.load when modifying nice value under sched_ext
- 作者:Wanwu Li liwanwu@kylinos.cn
- 版本:无(单 patch,未标注 vN)
- 规模:1 file changed, 13 insertions(+), 2 deletions(-)
- 修改文件:kernel/sched/core.c
- 代码统计:+13 / -2
- Message-ID:20260714091327.3-1-liwanwu9113@163.com
- 完整性:patch 已被作者主动撤回(withdrawn)。K Prateek Nayak 在第一封回复中指出同一问题已被更早的 patch 解决,作者确认后撤稿
补丁目的
修复 sched_ext(scx)调度类下,任务修改 nice 值后 p->se.load 没有同步更新的问题。当任务从 scx 切回 CFS 后,残留的旧 se.load 与新的 nice/priority 不匹配,导致 weight 计算错误,影响调度公平性和负载统计。
旧流程的问题
set_load_weight() 调用 p->sched_class->reweight_task():
- CFS 路径下:
reweight_task()内部会同步设置p->se.load = lw - scx 路径下:
reweight_task()只更新static_prio,不更新se.load(因为 scx 不使用 se.load)
在 scx 期间改 nice 后,static_prio 是新的,但 se.load 仍是旧值。一旦任务切回 CFS,旧的 se.load 与新 nice 不一致,weight 计算出错。
新流程
在 set_load_weight() 中,针对 scx 任务在调用 reweight_task() 后显式同步 p->se.load = lw:
if (update_load && p->sched_class->reweight_task) {
p->sched_class->reweight_task(task_rq(p), p, &lw);
/* 如果任务在 ext 类下改 nice,static_prio 已更新,
* 但 p->se.load 仍是旧的,与新 nice 不匹配。
* 切回 CFS 后会导致 weight 错误。同步刷新 se.load。 */
if (task_on_scx(p))
p->se.load = lw;
} else {
}
关键点:用 task_on_scx(p) 精确判断类,避免影响其他调度类的逻辑;仅在 update_load 为真且存在 reweight_task 回调时进入该分支。
Patch 概览
修改集中在 kernel/sched/core.c 的 set_load_weight():
- 增加
if (task_on_scx(p))条件判断 - 在
reweight_task()后追加p->se.load = lw - 修复对象明确:仅 scx 任务
关键实现
task_on_scx(p):宏定义,等价于p->sched_class == &ext_sched_class,运行时判断任务调度类lw:本次按新 nice 计算出来的 load weight- 替换的对象是 scx 自身的
reweight_task实现(不修改 scx 代码,仅在公共路径兜底)
类比
把 se.load 比作员工的「岗位级别」,把 static_prio 比作「工牌上的姓名/级别」。
CFS 像一个统一的人事系统,改动会自动同步两个字段。sched_ext 像临时借调部门,只关心工牌(static_prio),不维护岗位记录。员工在借调期间改了 nice(升职/降职),工牌是新的,但人事档案里的岗位级别没变。回到 CFS 时公司按档案发工资,bug 就出现了。
这个 patch 相当于在借调部门改工牌时,顺手把人事档案里的岗位级别也更新一下,保持两边一致。
+------------------------------------------+
|1. Task running under sched_ext (scx) |
+------------------------------------------+
|
v
+------------------------------------------+
| 2. nice modified -> reweight_task() |
| updates static_prio only |
| se.load stays OLD (stale) |
+------------------------------------------+
|
v
+------------------------------------------+
| 3. Task switched back to CFS |
| CFS reads se.load -> uses STALE |
| value -> weight calculation wrong |
+------------------------------------------+
|
v (proposed fix)
+------------------------------------------+
| After reweight_task(): |
| if (task_on_scx(p)) |
| p->se.load = lw;<-- refresh |
+------------------------------------------+
Highlight:风险与注意点
- 已被上游修复取代:Prateek 引用了
20260528131238.3879110-1-quzicheng315@gmail.com,说明该问题已经有更早的解决方案,作者已撤回本 patch;提交前应先做 grep/lore 检索 - 类切换时序:任务在 scx 与 CFS 之间切换的窗口期,
se.load的状态需要保证一致;本次 patch 只覆盖 nice 修改路径,迁移/唤醒等其他路径是否同步需要确认 - scx 内部维护:scx 自己不用 se.load,所以在 scx 内修改时不需要更新;但跨类切换到 CFS 后立刻被读取,公共路径必须兜底
- SCHED_IDLE 等其他 reweight 路径:被 Fixes 引用的 commit
d32960528702处理了 SCHED_IDLE,本 patch 应当确认与之是否冲突或互补
版本变化
无(单 patch,未发布新版本;已被撤回)。
一句话总结
作者提出补丁修复 scx 任务改 nice 后 se.load 不同步的问题,但在 maintainer 提示已有上游修复后,主动撤回了该 patch。