sched discussion
[PATCH 2/2] sched/cache: Use execution context for cache task tick
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() 接收到的 curr 是 rq->donor(被代理的调度上下文),而不是真正在 CPU 上执行的 rq->curr。task_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->curr的mm->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->curr 的 sched_class 而不是依赖 task_tick_fair() 是否被触发。
Patch 概览
| Patch | 文件 | 实质改动 | 修复对象 |
|---|---|---|---|
| 1/2 | kernel/sched/fair.c | task_tick_numa(rq, curr) -> (rq, rq->curr) | NUMA 扫描周期与 runtime 错位 |
| 2/2 | kernel/sched/fair.c | task_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_stat、sum_exec_runtime、task_work(numa_work、cache_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_numa由static_branch_unlikely(&sched_numa_balancing)守护,但 cache tick 没有对应的 static key,需要确认关闭 NUMA balancing 的内核配置下 cache tick 仍然生效。 Fixestag 同时指向 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 的情况。