0/3 已展开

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-ID20260714091327.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.cset_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。