Linux 内核调度子系统周报(2026-07-13 ~ 2026-07-19)
本期重点
- 1. sched_ext v7.2-rc3 修复批次合入主线——Tejun Heo 的 GIT PULL 把上期报告的 sub-scheduler 生命周期修复(两个 use-after-free、enable 失败残留)、dispatch 路径锁 bug(rq tracking、migration race)、callback/task-state 修复、nohz_full finite-slice tick 等 14 个补丁拉入 Linus 树。
- 2. proxy execution 与 sched_ext 共存一周迭代 v5→v6→v7——Andrea Righi 在上期 v4 基础上连续三版,v7 明确了 scheduler-facing kfuncs(
scx_bpf_task_running() 等)报告 donor 而非 owner、NOHZ CFS bandwidth 跟 rq->donor、kselftest 扩展到 cross-CPU topology。 - 3. sub-scheduler 进入 follow-up 阶段——capability v5 之后,Tejun Heo 本周发出三个后续系列:follow-ups(teardown 轮询改直接删除 +
scx_has_subs static key 给热路径设门控)、cgroup migration(跨 sched 边界迁移的 use-after-free 与 op 投递路由)、rename cid-form cgroup ops 为 cpuctl_*。 - 4. schedutil 在 shared policy 上有数据竞争——Zhongqiu Han 指出
sugov_start() 合并初始化循环后,第一个 CPU 的 hook 发布即可让 sugov_update_shared() 与兄弟 CPU 的 memset 初始化并发读写,Fixes: 16a03c71bba0,Cc: stable。 - 5. PREEMPT_DYNAMIC 简化系列拿到 Reviewed-by——Shrikanth Hegde 给 Mark Rutland 的 5 补丁系列 review 通过,Mark 修了拼写并回了细节问题,等 maintainer 取。
一、核心进展
proxy execution 与 sched_ext 共存:一周 v5→v6→v7
[1]
上期 Andrea Righi 的 v4 把 SCX_OPS_ENQ_BLOCKED 的设计稳定下来(设计见上期周报一、:donor→owner 交接建模成函数调用,donor 是调度上下文、owner 是执行上下文)。本周连发 v5(7 月 15 日)、v6(7 月 15 日)、v7(7 月 16 日),设计层面补充了几条一致性规则。(Andrea Righi,v7 系列)
v7 相对上期 v4 的设计补充:
scheduler-facing 的 current-task kfuncs 统一报告 donor 而非 owner。scx_bpf_task_running()、scx_bpf_cpu_curr()、scx_bpf_cid_curr() 返回的是 BPF 选中的 donor,不是核心内部替换执行的 mutex owner。这与"内部 owner 替换不生成合成 callback"一致——BPF 侧看到的 current 始终是它 dispatch 出去的任务。
NOHZ CFS bandwidth 检查跟 rq->donor 而非 rq->curr。这样带宽受限的 FAIR donor 在 owner 代它执行期间仍能保持 tick 运行,不会因为 rq->curr 指向 owner(可能不受带宽约束)而误停 tick。
kselftest enq_blocked 扩展为 cross-CPU topology:低优 owner(nice +19)持内核 mutex、高优 donor(nice -20)阻塞、每个可用 CPU 一个 nice 0 竞争者,分别跑 same-CPU(donor 和 owner 同核)和 cross-CPU(donor 和 owner 异核)两种拓扑,每种拓扑分别在 SCX_OPS_ENQ_BLOCKED 关/开两轮,按 CPU 统计 blocked-donor enqueue、报告 mutex hold/wait 时间差。mutex 访问由 TEST_GEN_MODS_DIR 构建的可加载内核模块提供。[1]
系列内含一个 consume 路径的 TOCTOU 修复(consume_remote_task() 迁移任务时 task_can_run_on_remote_rq() 的 lockless 评估与后续加锁之间存在窗口),见二、。
sub-scheduler capability 之后的三个后续系列
capability v5(上期报告)之后没有新版本,本周 Tejun Heo 转向收尾和周边,发出三个后续系列。
Sub-scheduler follow-ups(4 补丁,回应 Andrea 对 v5 的两条 review):sched teardown 此前用 msleep() 轮询排空 queued ecaps syncs,patch 0001 改为直接从 llist 删除;patch 0002-0003 是 prep(把 scx_dispatch_sched() 从 sub.h 挪到 internal.h,sashiko AI 标出 internal.h 末尾 include cid.h 可能的循环头依赖);patch 0004 加 scx_has_subs static key,给热路径里的 sub-sched 簿记设门控——CONFIG_EXT_SUB_SCHED=y 但无子调度器存在时,热路径不再为 sub-sched 簿记付出代价。[2]
Cgroup migration and op delivery for sub-schedulers(8 补丁)——这条是本周容量最大的新系列。任务的 sched 必须与它所在 cgroup 的 sched 匹配:每个子调度器服务它挂载的 cgroup2 子树,root 调度器服务其余部分。但 cgroup 迁移当前破坏了这个不变量:任务跨子调度器边界迁移后保留旧 sched,导致 wrong-sched 调度,旧 sched 释放后是 use-after-free;cgroup ops 也始终投递给 root 调度器,不论哪个 sched 服务该 cgroup。
系列让两者都跟随 sub-scheduler 拓扑:cgroup 新增 task migration notifier(0001,cgroup 侧改动),sched_ext 用它在迁移跨 sched 边界时 re-home 任务——目的 sched 在迁移提交前运行可失败的 ops.init_task(),拒绝则 cgroup.procs 写失败(0002-0004);cgroup_init/exit 和 knob ops 投递给每个 task_group 所在的 sched,move ops 投递给任务的 sched、只对不 re-home 的迁移(0005);子调度器 enable 时从父 claim 子树的 cgroup、disable 时归还,父 re-init 归还 cgroup 失败则级联上移到 root(0006);scx_qmap 经 ops.cgroup_set_weight() 消费 cgroup 权重,加故障注入模式覆盖失败路径(0007-0008)。[3]
Rename the cid-form cgroup ops to cpuctl_*(2 补丁)——cid form 里两件不相关的事都叫"cgroup":子调度器挂到 cgroups,cgroup_*() ops 投递 cpu controller 事件。ops 名字暗示 cgroup2 层级,实际操作的是 cpu controller。cid form 除 scx_qmap 外无用户,趁 ABI 还能改把 ops 重命名为 cpuctl_*;cpu form 是已部署 ABI,保留旧名。patch 0001 把 skeleton open 路径从 SCX_OPS_OPEN() 抽出,加 SCX_OPS_CID_OPEN() 让 cid-form skeleton 不依赖 cpu-form 成员名。[4]
SLOP RFC:cid-form set_cmask() 传 kernel arena 指针
[5]
cid-form 的 set_cmask() 回调接收内核在 arena 里构建的 per-CPU cmask。此前参数无 __arena tag,回调拿到的是 trusted scx_cmask BTF 指针,内核调用前要手动把 kernel 地址转成 arena 指针形式(scx_kaddr_to_arena())。
Tejun Heo 的 RFC 给 stub 参数加 __arena tag,直接传 kernel arena 地址。struct_ops entry prologue 把它 rebase 到程序的 arena 指针,于是手动 scx_kaddr_to_arena() 转换和它的 helper 可以删除。标注 NOT_SIGNED_OFF: to be reworked after bpf-next is pulled into sched_ext,依赖 bpf-next 的 arena 支持改进,属预备性 RFC。[5]
PREEMPT_DYNAMIC 简化:拿到 Reviewed-by
[6]
上期 Mark Rutland 的 5 补丁系列(让 PREEMPT_DYNAMIC 依赖 ARCH_HAS_PREEMPT_LAZY、删 367 行死代码,背景见上期周报一、)本周拿到 Shrikanth Hegde 的 Reviewed-by。Mark 修了 cover letter 里 "suppoort" 的拼写,回了 Kconfig help 文本是否要更新的问题(认为现有措辞不算错,措辞改动与本次逻辑改动分开)。状态:已 review,等 maintainer 取。[6]
二、重要 Bug 修复
sched_ext v7.2-rc3 修复批次合入主线
[7]
Tejun Heo 7 月 13 日向 Linus 发出 GIT PULL(tags/sched_ext-for-7.2-rc3-fixes),pr-tracker-bot 确认已合入 torvalds/linux(commit f7574d3f906a)。这批 14 个补丁把上期报告里的修复全部带入主线:
- • sub-scheduler 生命周期:两个 use-after-free(
Annotate ksyncs with __rcu、Pin parent scx_sched across a child sub-scheduler's lifetime)、enable 失败残留(Record an error on errno-only sub-enable failure,即上期 David Carlier 报的 bug); - • dispatch 路径锁:migration race 导致的 spurious scheduler abort、stale runqueue-lock tracking 导致的 lockdep splat(即上期 Andrea 的 local DSQ rq tracking 修复);
- • callback/task-state:任务离开 SCX 时的 stale scheduler-owned state(
Reset dsq_vtime and slice)、disable 后的 weight callback(Skip ops.set_weight() for disabled tasks,上期 Kuba Piecuch)、core-sched forced idle 误告警; - • nohz_full:finite-slice 任务错过过期 slice 的 tick,附 selftest(上期 Andrea 的 nohz_tick)。
这批合入意味着上期"sched_ext 在 7.1/7.2 核心路径的边界条件仍在持续修复"判断里列出的多数条目,在本周进入已发布内核。[8]
schedutil:shared policy 上 sugov_start() 数据竞争
[9]
【问题】commit 16a03c71bba0 ("cpufreq: schedutil: Merge initialization code of sg_cpu in single loop") 把 per-CPU 初始化和 utilization-hook 注册合并进 sugov_start() 的单循环。对 shared cpufreq policy,这重新引入了 commit ab2f7cf141aa 原本修复的竞争。
【根因】调度器的 util 路径在 RCU-sched 下到达 hook,从不取 policy->rwsem,所以 sugov_start() 持有的 rwsem 无法串行化两边。第一个 CPU 的 hook 一经发布,sugov_update_shared() 就可能运行,经 sugov_next_freq_shared() 与仍在 memset 初始化的兄弟 sugov_cpu 并发读写各成员(iowait_boost、util、bw_min 等),两边无共同锁:update 侧持 sg_policy->update_lock,init 侧只持 policy->rwsem。
【影响范围】遍历只访问标量成员、不解引用 ->sg_policy 这类指针,所以目前不崩溃,只是用 stale(首次启动时为零)值扭曲频率选择和 tracepoint。但这是一条真实数据竞争,一旦该路径解引用任何指针成员就是潜在崩溃。
【修复方案】恢复两阶段:先初始化所有 per-CPU 结构,再发布 per-CPU utilization update hook。Fixes: 16a03c71bba0,Cc: stable。(Zhongqiu Han / 高通)
sched/core:sched_ext 下改 nice 的 se.load 问题(重复补丁,已撤回)
[10]
Wanwu Li(麒麟)发补丁处理 sched_ext 下改 nice 值导致 se.load 过期的问题:任务在 sched_ext 调度类下运行时改 nice,set_load_weight() 调 reweight_task(),sched_ext 的 reweight_task() 只更新 static_prio、不动 p->se.load,切回 CFS 后过期的 se.load 导致负载权重计算错误。补丁在 reweight_task() 后对 sched_ext 任务显式刷新 p->se.load = lw。
K Prateek Nayak 回复指出该问题已由 Zicheng Qu 5 月 28 日的补丁([PATCH] sched/fair: Fix stale se.load when running under sched_ext,[25])解决。Wanwu Li 随后确认不知此前已有修复,撤回了自己的补丁。该问题本身已被修复,本周这条线索只是重复提交被指出后撤回。
sched_ext:consume_remote_task() 的 TOCTOU
[11]
这条出现在 proxy execution v7 系列内(patch 05/11,作者 Andrea Righi)。consume_remote_task() 在 DSQ 消费期间迁移任务时,task_can_run_on_remote_rq() 的 lockless 评估与锁源 rq 后的复检之间存在窗口——任务可能在两次检查间开始在 CPU 上运行(task_on_cpu())。补丁加锁后重新评估 task_can_run_on_remote_rq(),失败则 fallback 到 global DSQ,由常规消费过滤器选合适 CPU,不强制塞回源 local DSQ。task_can_run_on_remote_rq() 还新增 task_on_cpu() 检查拒绝迁移正在 CPU 上跑的任务。
sashiko AI review 标出两个 High 风险:任务在 DSQ 消费时被跳过可能导致 lost wakeup/scheduler stall(idle CPU 在前一个 CPU 完成 finish_task_switch() 清 p->on_cpu 前消费,lockless 评估返回 false 跳过任务,之后若无新 kick 任务可能滞留 dispatch queue);fallback 路径把正在执行的任务 enqueue 到 global DSQ 可能导致链表腐败。这些是 review 中待 Andrea 确认的边界。[11]
sched_ext:sub-scheduler 与 cgroup 的四件修复
[12]
Tejun Heo 的 for-7.2-fixes 系列(4 补丁):
- 1.
ops.init_task() 在 enable 路径之外设 p->scx.disallow 会让调度器失败。子调度器 disable 路径会到达 load-path-only 的 policy revert,静默改写活任务的策略。改为 kill sched,匹配 fork 和 non-root 分支。Fixes: 337ec00b1d9c。 - 2.
scx_cgroup_lock()、cgroup teardown 排空 cpu controller 文件、并发 cpu.weight 写之间的三方死锁。Fixes 待定,存在于 v6.18 起的已发布内核,标 stable。 - 3. enable 失败前未 link 的子调度器与 root disable 并发 teardown 的 use-after-free。
- 4.
SCX_OPS_SWITCH_PARTIAL root 下子调度器任务循环里对非 ext 任务 gate task enabling,否则非 ext 任务被标 ENABLED 却留在自己的类,破坏任务状态机。
sched_ext:sub-enable 路径的 stale errno
[13]
scx_sub_enable_workfn() 丢弃 validate_ops() 的返回值。validate_ops() 失败跳到 err_disable 时 ret 还持有上一次调用的 0,于是 commit db4e9defd2e8(上期 capability v4 加的 errno-only 失败 fallback)报 "scx_sub_enable() failed (0)"。当前无害(validate_ops() 先记自己的 scx_error(),首错优先),但让该路径的 fallback 失效。修复把 validate_ops() 返回值存入 ret,并给 nesting depth 检查和 cgroup online 检查分别设 -EINVAL、-ENODEV。这是上期 sub-enable arm exit 修复的后续补全。(Cui Jian)
sched_ext:finite-slice tick 的独立补丁
[14]
上期 Andrea Righi 的 nohz_full finite-slice tick 修复已随 v7.2-rc3 合入。本周字节跳动的 Zhimin Feng、Chengming Zhou 发了一个针对同一问题的独立补丁,实现不同:Andrea 版对 finite-slice EXT 任务总是开 tick;字节版加 sched_set_tick_dependency() helper,从 set_next_task_scx() 在 next 任务有 finite slice 时直接设调度 tick 依赖,不依赖 sched_update_tick_dependency()(因为 rq->curr 此时可能还是前一个任务),保留 SCX_SLICE_INF 任务的 tickless 行为。两条思路解决同一根因(set_next_task_scx() 在 rq->curr 更新前刷新 nohz 依赖)。[14]
sched_ext:cid override 的 double-fetch TOCTOU(已被覆盖)
[15]
zhidao su(小米)发现 scx_bpf_cid_override() 边走用户映射边更新 cid 查找表,中途验证失败会让前面的表项残留,于是拆成验证和更新两个循环。Tejun Heo 回复指出 for-7.3 已做此事(先 cid_valid() 和重复检查验证全部映射,再第二趟写表),且 kmemdup() 输入避免并发修改竞争;该补丁基于旧 cid.c 已不再适用,不需 respin。sashiko AI 同时标出该补丁的"split into two loops"本身引入 double-fetch TOCTOU(用户态数组两次读取间可被修改,导致越界内核写)——这说明 for-7.3 用 kmemdup 复制输入是必要的。[16]
三、sched_ext 进展
核心功能演进
本周核心演进的主线是上面三节展开的 proxy execution v5→v7、sub-scheduler 三个后续系列、SLOP RFC。承接上期判断——sched_ext 在朝"层级化、可在子调度器间按 capability 划分 CPU、并能与 proxy execution 共存"走——本周的改动集中在让这套模型在 cgroup 迁移、热路径开销、kfunc 一致性这些周边环节落地。
proxy execution 共存(v5→v7)补的是 donor 与 owner 并存时的观测一致性:scheduler-facing kfuncs 统一报 donor、NOHZ bandwidth 跟 rq->donor、kselftest 加 cross-CPU 拓扑。这些是把上期 v4 立住的"函数调用"抽象在更多核心路径上对齐。
sub-scheduler 的 cgroup migration 系列(8 补丁)补的是 capability 模型缺失的一块——任务跨 sched 边界迁移时的归属一致性和 op 投递路由。scx_has_subs static key 则回应了"层级化模型对无子调度器场景的热路径开销"这一 review 关切。
稳定性修复
本周稳定性修复分两条线:一是 v7.2-rc3 修复批次合入主线(见二、),把上期报告的多数修复带入已发布内核;二是新的 for-7.2-fixes 候选(sub-scheduler + cgroup 四件修复,见二、),其中三方死锁从 v6.18 起存在、标 stable。再加上 schedutil shared policy 数据竞争(见二、)、sub-enable stale errno(见二、)。另有一条 sched_ext 下改 nice 的 se.load 重复补丁被指出已有修复后撤回(见二、)。
生态与工具改进
selftests/sched_ext: Fix bpf_link leak on early return in prog_run 的同类修复延续到多个工具补丁。本周工具侧改动:
- • scx_pair: Convert to sched_switch TP(Cheng-Yang Chou)——
ops.cpu_acquire/release() 已废弃,改为用 tp_btf/sched_switch 程序边沿检测同样的转换。加载 scx_pair 此前会发废弃告警。[17] - • scx_qmap: Fix stale API name in comment(Liang Luo,KylinOS)——
dispatch_highpri() 上方注释还引用 v6.13 已重命名的 scx_bpf_dispatch[_vtime]_from_dsq(),代码已用新名 scx_bpf_dsq_move[_vtime](),只注释落后于改名。Fixes: 5cbb302880f5。[18] - • scx_flatcg: Fix uninitialized stats on allocation failure(Liang Luo,KylinOS)——
fcg_read_stats() 里清零输出 @stats 的 memset() 在 calloc() 失败检查之后,calloc 失败时返回未初始化内存。[19]
四、工具链与调试
need-resched 定时等待接口 v14(Ankur Arora,Oracle,v14 11/15)——承接上期 v13。新增 tif_bitset_relaxed_wait() 及包裹它的 tif_need_resched_relaxed_wait(),带 thread_info 位和超时参数,用 smp_cond_load_relaxed_timeout() 实现,抽象 poll_idle 式"等标志位变更直到超时"的模式。放在 linux/sched/idle.h 绕开递归头文件依赖,服务于 cpuidle poll 路径。[20]
task enqueue/dequeue tracepoints(Nam Cao / Linutronix,v3 4/5)——给 enqueue_task() 和 dequeue_task() 加 tracepoint,服务于验证 RT 调度的 RV monitor。本周 Steven Rostedt 询问是否仍在等 Ack,Gabriele Monaco 表示计划在合并其他依赖后下个开发周期一起发,Ack 不紧急但欢迎;Nam Cao 提到 Peter 在 v2 线程有 comments。状态:等 Ack。[21]
perf sched: Add missing perf_session__delete()(Namhyung Kim,v1→v2)——perf sched stats record 漏释放 session,ASAN 报泄漏。Fixes: c3030995f23b。[22]
schedutil: sysfs show 用 sysfs_emit()(Zhongqiu Han,高通)——rate_limit_us_show() 的 sprintf() 换 sysfs_emit(),提供 PAGE_SIZE 边界检查。无功能改动。[23]
Add support for long task name(André Almeida / Igalia,v4 6 补丁)——16 字节 comm 在数百线程程序的调试追踪中不够。系列新增 PR_{SET,GET}_EXT_NAME 支持 64 字节名,引入 copy_task_comm() 保证 NUL 终止,把 current->comm 长度设为 TASK_COMM_EXT_LEN 同时让现有 userspace API 仍只暴露 TASK_COMM_LEN。v4 简化了 copy_task_comm()(memcpy + 末尾 NUL)。[24]
五、下周关注点
- 1. proxy execution + sched_ext v7 之后——v7 把 kfunc 一致性和 NOHZ bandwidth 对齐后,Peter Zijlstra是否接受函数调用模型;consume_remote_task TOCTOU 修复的 lost wakeup 和 fallback 链表腐败两个 sashiko AI 标出的 High 风险如何解决。
- 2. sub-scheduler cgroup migration 系列的 review——8 补丁系列引入 cgroup task migration notifier(cgroup 侧改动),跨子树的 re-home 失败传播和 op 投递路由是新的复杂度,关注是否引发 cgroup 侧 maintainer 的意见。
- 3. sub-scheduler + cgroup 四件 for-7.2-fixes 的合入——三方死锁(v6.18 起存在)和 use-after-free 是否进 stable 回填,以及
cpuctl_* rename 是否在 ABI 冻结前完成。 - 4. schedutil shared policy 数据竞争的 stable 回填范围——
Fixes: 16a03c71bba0,影响 shared cpufreq policy 下的频率选择正确性,关注 port 到哪些 stable 版本。 - 5. capability 系列本身——v5 之后本周无新版本,转入 follow-up 阶段;关注 cgroup migration 系列(依赖 capability 模型)合入后,capability 是否再出 v6 或开始进
for-7.3。
引用链接
[1] 原文: https://lore.kernel.org/all/20260716132229.61603-1-arighi@nvidia.com/
[2] 原文: https://lore.kernel.org/all/20260714230917.84158-1-tj@kernel.org/
[3] 原文: https://lore.kernel.org/all/20260718081727.582037-1-tj@kernel.org/
[4] 原文: https://lore.kernel.org/all/20260718101029.725350-1-tj@kernel.org/
[5] 原文: https://lore.kernel.org/all/20260713024414.3759854-6-tj@kernel.org/
[6] 原文: https://lore.kernel.org/all/aloLAbF1POaEIUE7@J2N7QTR9R3/
[7] 原文: https://lore.kernel.org/all/876d09cb8d47617d382a7e2af7a7fd6b@kernel.org/
[8] 原文: https://lore.kernel.org/all/178398457483.2881721.17658018427084030493.pr-tracker-bot@kernel.org/
[9] 原文: https://lore.kernel.org/all/20260716115159.848403-1-zhongqiu.han@oss.qualcomm.com/
[10] 原文: https://lore.kernel.org/all/20260714091327.3-1-liwanwu9113@163.com/
[11] 原文: https://lore.kernel.org/all/20260715211455.981AF1F000E9@smtp.kernel.org/
[12] 原文: https://lore.kernel.org/all/20260716213058.1739522-1-tj@kernel.org/
[13] 原文: https://lore.kernel.org/all/20260718201713.17890-1-cjian720@163.com/
[14] 原文: https://lore.kernel.org/all/20260716023746.3289089-1-fengzhimin@bytedance.com/
[15] 原文: https://lore.kernel.org/all/20260714024704.3318132-1-soolaugust@gmail.com/
[16] 原文: https://lore.kernel.org/all/7c5d028a7a46a2917a3fcc8d1eccf084@kernel.org/
[17] 原文: https://lore.kernel.org/all/20260719142917.34238-1-yphbchou0911@gmail.com/
[18] 原文: https://lore.kernel.org/all/20260714032051.1834822-1-luoliang@kylinos.cn/
[19] 原文: https://lore.kernel.org/all/20260713071808.89847-1-luoliang@kylinos.cn/
[20] 原文: https://lore.kernel.org/all/20260714073041.40250-12-ankur.a.arora@oracle.com/
[21] 原文: https://lore.kernel.org/all/20260714121145.1e73c05e@gandalf.local.home/
[22] 原文: https://lore.kernel.org/all/20260713204707.2181098-2-namhyung@kernel.org/
[23] 原文: https://lore.kernel.org/all/20260716131546.1159644-1-zhongqiu.han@oss.qualcomm.com/
[24] 原文: https://lore.kernel.org/all/20260717-tonyk-long_name-v4-0-1fedfc870d21@igalia.com/
[25] 原文: https://lore.kernel.org/lkml/20260528131238.3879110-1-quzicheng315@gmail.com/