0/3 已展开

LLM 分析

sched_ext: WAKE_SYNC 场景下标记唤醒者 CPU 为 busy

系列基线信息

字段
标题sched_ext: mark waker CPU busy when selected in WAKE_SYNC case
作者Kuba Piecuch (Google)
目标分支sched_ext/for-7.2-fixes
规模1 file, +3 / −1
Message-ID20260722143307.2772632-1-jpiecuch@google.com
来源sched-ext 频道
状态已被 Tejun Heo 合入 for-7.2-fixes

明确目的

SCX 的内置 idle CPU 追踪与实际 idle 状态可能不一致——尤其刚启用 SCX 时,
scx_idle_enable() 会把所有 online CPU 一股脑标记为 idle。

SCX_WAKE_SYNC 路径中,scx_select_cpu_dfl() 若选定了唤醒者(waker)CPU,
则跳过了将该 CPU 标记为 busy 的步骤。于是 waker CPU 在被选中之后仍然挂着 idle 标签,
wakee 切过来也跑在"看起来 idle"的 CPU 上。

allowed_cpus selftest 因此失败,dmesg 报:

allowed_cpus.bpf.c:21: CPU 0 should be marked as busy

本 patch 在 WAKE_SYNC 选中 waker CPU 时显式调用 scx_idle_test_and_clear_cpu(cpu)
将其从 idle mask 中摘除,修复该问题。


遍历代码

补丁只改了一个文件 kernel/sched/ext/idle.c,核心改动约 2 行:

if (cpumask_test_cpu(cpu, allowed)) {
    scx_idle_test_and_clear_cpu(cpu);   // <-- 新增:清除 idle 标记
}

改动位置scx_select_cpu_dfl() 函数,处理 SCX_WAKE_SYNC 选中 waker CPU 的分支。

逻辑流程

  1. scx_select_cpu_dfl()WAKE_SYNC 场景下优先考虑 waker CPU,
    因为 wakee 与 waker 有同步关系,共享 cache 更有利。

  2. 选中 waker CPU 后,原代码只做了 cpumask_test_cpu(cpu, allowed) 检查,
    然后直接跳到 out_unlock 返回——没有像其他路径那样调用
    scx_idle_test_and_clear_cpu() 把选中 CPU 从 idle mask 移除。

  3. 补丁在此处补上 scx_idle_test_and_clear_cpu(cpu),确保 waker CPU
    一旦被选中,就不再被 idle 追踪视为空闲。

  4. 返回后,调度器继续将 wakee 放到该 CPU 执行,idle 状态已正确反映为 busy。


ASCII 流程图

              scx_select_cpu_dfl()
                      |
           wake_flags & SCX_WAKE_SYNC ?
            /                    \
          YES                     NO
           |                      |
     waker CPU 可用 ?        常规 CPU 选择路径
      (allowed mask)         → scx_idle_test_and_clear_cpu()
           |                      |    (已存在)
     ┌─ 之前 ─┐          ┌─ 补丁后 ─┐
     │ 直接返回 │          │ test_and_clear │
     │ waker CPU│          │ waker CPU idle │
     │ 仍标 idle│          │ 标记 → busy    │
     └──────────┘          └────────────────┘
           |                      |
       idle mask 不一致       idle mask 一致 ✓
       → selftest 失败        → selftest 通过 ✓

概念类比

想象一个停车场管理系统:

  • 入口闸机(scx_idle_enable())刚上线时,把所有车位统一标记为"空",
    哪怕有些车位上还停着车——这就是 idle 追踪初始化的不准确。

  • 当一个司机(waker)在自己车位上接了一位新乘客(wakee),
    停车系统本应把该车位标记为"已占用",但因为同步场景的特殊逻辑,
    系统认为"司机本来就在这儿,不需要重新标记"——车位仍显示"空"。

  • 补丁就是:即使司机没挪位置,也要重新刷一次车位状态,
    确保系统知道这个车位正在被使用。


Highlight 窗出问题

  1. 仍存在不可修复的竞态:作者承认 pick_task_idle() 可在 CPU 选择与验证之间
    再次把选中 CPU 标回 idle——极小概率但理论上存在,且"难以修复"。
    未来如果 selftest 仍偶发失败,需判断是否属于此竞态。

  2. 初始化阶段 idle mask 全量标记的固有偏差scx_idle_enable() 把所有 online CPU
    一股脑标 idle,是根因之一。本补丁只修了 WAKE_SYNC 一个路径;
    是否还有其他路径也存在类似"选中但没清 idle"的遗漏,值得后续排查。

  3. 只影响 sched_ext:此问题不涉及 CFS/classic scheduler,只在 SCX BPF scheduler
    的 idle 追踪中出现;测试和验证应限定在 SCX 场景。


版本演进

单版补丁,无 v1→v2 演进记录。


与其他相关 patch 系列的关联

  • allowed_cpus selftest:此补丁直接修复了该 selftest 的失败;
    该测试专门验证 SCX idle tracking 与实际 CPU 状态的一致性。
  • scx_idle_enable() 初始化逻辑:补丁 commit message 明确指出初始化全量标记 idle
    是偏差来源之一,后续可能有针对初始化阶段的改进。

一句话总结

补丁在 scx_select_cpu_dfl() 的 WAKE_SYNC 分支补上 scx_idle_test_and_clear_cpu()
修复 waker CPU 被选中后仍标记 idle 的问题,已被 maintainer 合入 for-7.2-fixes。