0/4 已展开

LLM 分析

sched/cache 与 sched/numa:使用 execution context 驱动 task tick

系列概况

  • 标题[PATCH 1/2] sched/numa: Use execution context for NUMA task tick / [PATCH 2/2] sched/cache: Use execution context for cache task tick
  • 作者:Hui Su sh_def@163.com
  • 版本:v1
  • 规模:2 个 patch
  • 修改文件kernel/sched/fair.c(两处各一行替换)
  • 代码统计:每个 patch 1 行实质改动(task_tick_numa(rq, curr)改为 task_tick_numa(rq, rq->curr)task_tick_cache(rq, curr) 改为 task_tick_cache(rq, rq->curr)
  • Message-ID
    • <20260902163336.1552840-1-sh_def@163.com>(PATCH 1/2)
    • <20260902163336.1552840-2-sh_def@163.com>(PATCH 2/2)
    • <c5a2d651a5d647fb29f13fe483301b3b6e292b4d.camel@linux.intel.com>(Tim Chen 回复)
    • <de3928e26072ba22a6f7d8d293a3bd43.sh_def@163.com>(Hui Su 回复)
  • 完整性:v1 完整,含 2 个 patch + 2 封回复邮件。Tim Chen 在 review 中指出 v1 仍未覆盖 RT/deadline donor 通过 fair task 做 proxy execution 的场景,作者确认将重写为 v2。

补丁目的

修复 proxy execution 下 task_tick_fair() 接收到的 currrq->donor(被代理的调度上下文),而不是真正在 CPU 上执行的 rq->currtask_tick_numa()task_tick_cache() 误把 NUMA 扫描与 cache 扫描 epoch 推进到 donor 的 mm 上,但 runtime accounting(account_mm_sched())实际记到了 rq->curr 的 mm,导致两边状态错位。

旧流程的问题

task_tick_fair(rq, curr=donor, queued)
        |
        +-- task_tick_numa(rq, donor)    --> advance donor.sum_exec_runtime
        +-- task_tick_cache(rq, donor)   --> advance donor.mm->sc_stat.epoch
        |
        v
update_se() --> account_mm_sched(rq->curr)   # charged to executor rq->curr

后果:

  • donor 的 sum_exec_runtime 没动,但 task_tick_numa() 仍以它为基准判定扫描周期。
  • rq->currmm->sc_stat.epoch 永远停滞,cache 亲和性追踪与实际 runtime 走偏。
  • Tim Chen 进一步指出:当 donor 本身是 RT/deadline 时,task_tick_fair() 根本不会被调用,cache tick 直接被漏掉;account_mm_sched() 仍在运行,最终 mm->sc_stat.cpu 被重置为 -1,丢失 preferred LLC。

新流程

sched_tick()
   |
   +-- if rq->curr->sched_class == &fair_sched_class
   |        task_tick_fair(rq, rq->curr, queued)
   |             --> task_tick_numa(rq, rq->curr)
   |             --> task_tick_cache(rq, rq->curr)
   |
   +-- sched_tick_remote() must add the same two calls (nohz_full)
   v
update_se() --> account_mm_sched(rq->curr)   # runtime and tick on same mm

关键点是把 numa/cache tick 的判定上移到 sched_tick(),使用 rq->currsched_class 而不是依赖 task_tick_fair() 是否被触发。

Patch 概览

Patch文件实质改动修复对象
1/2kernel/sched/fair.ctask_tick_numa(rq, curr) -> (rq, rq->curr)NUMA 扫描周期与 runtime 错位
2/2kernel/sched/fair.ctask_tick_cache(rq, curr) -> (rq, rq->curr)cache epoch 与 account_mm_sched() 错位

关键实现

两个 v1 patch 只改了 task_tick_fair() 内部的入参:

// kernel/sched/fair.c
- task_tick_numa(rq, curr);
+ task_tick_numa(rq, rq->curr);
...
- task_tick_cache(rq, curr);
+ task_tick_cache(rq, rq->curr);

意图是:让 task_tick_numa() / task_tick_cache() 看到的 task 与 update_se() -> account_mm_sched(rq->curr) 记账的 task 一致,保证 mm->sc_statsum_exec_runtimetask_worknuma_workcache_work)都挂在同一个 execution context。

Fixes tag 分别指向:

  • PATCH 1/2:af0c8b2bf67b sched: Split scheduler and execution contexts
  • PATCH 2/2:df0d98475954 sched/cache: Introduce infrastructure for cache-aware load balancing

说明回归点都在 scheduler/execution context 拆分以及 cache-aware 基础设施引入之后。

类比

把 CPU 想象成一台自助咖啡机,rq->curr 是正在操作机器的顾客 A,rq->donor 是付钱/排队但让 A 代为操作的朋友 B。旧的代码把消费积分记在 B(donor)身上,但咖啡豆消耗和钱都扣在 A(执行者)头上,最后账单对不上。v1 改了 fair 收银台,但忽略了:如果 B 自己是非 fair 会员(RT/deadline)走 VIP 通道,fair 收银台压根不开单——这正是 Tim Chen 提醒的盲点,需要把 numa/cache 的扣分动作挪到更上层的总台(sched_tick()),不管走哪条通道都能记到 A 头上。

        +----------------------- sched_tick() ------------------------+
        |                                                              |
        |   rq->curr = A (executor)     rq->donor = B (sched ctx)      |
        |                                                              |
        |   +-----------+        +-----------+        +-----------+    |
        |   | fair tick |        | rt tick   |        | dl tick   |    |
        |   +-----------+        +-----------+        +-----------+    |
        |        |                     |                     |         |
        |   task_tick_numa (old: missing)        (old: missing)   |
        |   task_tick_cache      (old: missing)        (old: missing)   |
        |        |                                                      |
        |        v                                                      |
        |   all use rq->curr=A to advance mm->sc_stat/epoch/task_work   |
        +--------------------------------------------------------------+

Highlight:风险与注意点

  • v1 只修了 task_tick_fair() 路径,但当 fair task 作为 execution context 为 RT/deadline donor 做 proxy 时,task_tick_fair() 根本不会运行,导致 cache/NUMA tick 漏触发;mm->sc_stat.epoch 长期停滞后 account_mm_sched() 会把 mm->sc_stat.cpu 重置为 -1,丢失 preferred LLC。
  • 评审建议把 task_tick_numa() / task_tick_cache() 上提到 sched_tick(),并复用 account_mm_sched() 已有的 p->sched_class != &fair_sched_class 判断。
  • sched_tick_remote()(nohz_full 路径)必须同步补上两次调用,否则 nohz_full CPU 上的 cache/NUMA tick 会全部消失。
  • v1 patch 中 task_tick_numastatic_branch_unlikely(&sched_numa_balancing) 守护,但 cache tick 没有对应的 static key,需要确认关闭 NUMA balancing 的内核配置下 cache tick 仍然生效。
  • Fixes tag 同时指向 scheduler/execution context 拆分与 cache-aware load balancing 两个 commit,stable 回溯时要明确最旧需要打到的版本。

版本变化

  • 当前是 v1,评审已暴露上提路径缺失的问题,作者 Hui Su 在最后一封邮件中明确表示 "I have reworked the series to move task_tick_numa(...)",预计下一版会把两次调用上移到 sched_tick() 并补 sched_tick_remote()

一句话总结

proxy execution 下,task_tick_numa() / task_tick_cache() 必须用 rq->curr 而不是 rq->donor 来推进执行者的 mm 状态,且调用点应上提到 sched_tick() 以覆盖 donor 为 RT/deadline 的情况。