sched-ext discussion
[PATCH sched_ext] sched/ext: Keep tick enabled for finite-slice tasks
LLM 分析
sched/ext:有限时间片任务必须保持 scheduler tick
系列基线信息
- 标题:
[PATCH sched_ext] sched/ext: Keep tick enabled for finite-slice tasks - 作者:Zhimin Feng(冯志敏)
- 共同开发者:Chengming Zhou
- 版本:未标注版本,可视为首版
- 系列规模:单补丁
- 改动规模:2 个文件,新增 29 行、删除 3 行
- 涉及文件:
kernel/sched/ext/ext.ckernel/sched/sched.h
- 首封 Message-ID:
20260716023746.3289089-1-fengzhimin@bytedance.com - 来源频道:
sched-ext - 讨论规模:3 封邮件
- 关联链接:回复中指向
20260708074812.1041434-1-arighi@nvidia.com
明确目的
这个补丁修复 sched_ext 在 nohz_full CPU 上运行有限时间片任务时,scheduler tick 可能被错误关闭的问题。
有限时间片 SCX 任务依赖周期性 tick 扣减和检查 p->scx.slice。时间片耗尽后,调度器才能及时触发重新调度。如果 tick 停止,任务的时间片可能无法正常到期,从而破坏时间片轮转和调度前进性。
问题出现在 set_next_task_scx() 选择了下一个 SCX 任务、但 rq->curr 尚未切换到该任务的窗口:
- 下一个任务
p使用有限时间片。 set_next_task_scx()调用旧的sched_update_tick_dependency()。- 后者通过
sched_can_stop_tick()检查rq->curr。 - 此时
rq->curr仍可能是 idle、RT、CFS 或另一个允许停 tick 的旧任务。 - 调度器据此错误地保持或清除了
TICK_DEP_BIT_SCHED。 - 新 SCX 任务开始运行后,CPU 可能仍然处于无 scheduler tick 状态。
补丁的核心原则是:是否需要 tick 应根据即将运行的任务 p 判断,而不能依赖尚未更新的 rq->curr。
遍历代码
1. 计算下一个 SCX 任务能否停 tick
set_next_task_scx() 根据时间片是否无限来计算状态:
can_stop_tick = p->scx.slice == SCX_SLICE_INF;
tick_state_changed = can_stop_tick !=
(bool)(rq->scx.flags & SCX_RQ_CAN_STOP_TICK);
语义如下:
p->scx.slice == SCX_SLICE_INF:任务没有有限时间片到期需求,可以允许停 tick。p->scx.slice != SCX_SLICE_INF:任务必须依靠 tick 推进时间片,不能停 tick。tick_state_changed:记录新任务的需求是否与 runqueue 当前缓存状态不同。
2. 更新 runqueue 的 SCX tick 状态
当状态发生变化时,补丁继续维护 SCX_RQ_CAN_STOP_TICK:
if (tick_state_changed) {
if (can_stop_tick)
rq->scx.flags |= SCX_RQ_CAN_STOP_TICK;
else
rq->scx.flags &= ~SCX_RQ_CAN_STOP_TICK;
}
这个标志描述 SCX 当前选中任务是否允许关闭 scheduler tick。
补丁将“更新状态标志”和“设置实际 tick dependency”拆开,使后者可以明确根据下一个任务执行。
3. 有限时间片任务直接设置 tick dependency
对于有限时间片任务,新的逻辑不再通过 rq->curr 间接判断:
if (!can_stop_tick)
sched_set_tick_dependency(rq);
这一步直接设置对应 CPU 的 TICK_DEP_BIT_SCHED,保证 scheduler tick 保持运行。
这里即使 SCX 标志没有发生变化,也会再次设置 dependency。这样可以避免实际 tick dependency 与 SCX 缓存状态因其他路径而不同步。
4. 无限时间片任务仍可恢复 tickless
当下一个任务使用 SCX_SLICE_INF,且状态确实发生变化时,代码才通过现有更新路径重新评估能否停 tick:
else if (tick_state_changed)
sched_update_tick_dependency(rq);
因此补丁没有禁止 SCX 使用 tickless 模式:
- 有限时间片:强制保留 tick。
- 无限时间片:仍按系统整体条件决定是否可以停止 tick。
5. 在 scheduler 公共头文件增加直接设置 helper
sched.h 新增:
static inline void sched_set_tick_dependency(struct rq *rq)
{
int cpu = cpu_of(rq);
if (!tick_nohz_full_cpu(cpu))
return;
tick_nohz_dep_set_cpu(cpu, TICK_DEP_BIT_SCHED);
}
该 helper:
- 从 runqueue 得到 CPU。
- 只对
nohz_fullCPU 执行操作。 - 直接设置 scheduler 的 tick dependency。
- 不调用
sched_can_stop_tick(),因此不读取可能仍指向旧任务的rq->curr。
在未启用 CONFIG_NO_HZ_FULL 时,提供空实现,不影响其他配置。
6. 与 CFS 现有处理对齐
提交说明指出,CFS 对需要 bandwidth accounting 的任务已有基于“下一个任务”的检查:sched_fair_update_stop_tick() 会明确设置 TICK_DEP_BIT_SCHED。
这个补丁为 SCX 有限时间片建立了对应保障,但没有把 CFS 的完整逻辑直接复制到 SCX。
ASCII 流程图
set_next_task_scx(rq, p)
|
v
+-----------------------------+
| Is p->scx.slice infinite? |
+-----------------------------+
| yes | no
v v
can_stop_tick=true can_stop_tick=false
| |
| v
| sched_set_tick_dependency(rq)
| |
| set TICK_DEP_BIT_SCHED
| |
v v
tickless may resume scheduler tick stays on
after reevaluation slice expiration progresses
旧路径中的竞态窗口:
Old task set_next_task_scx() New SCX task
rq->curr = old ---> p = finite-slice SCX -------> rq->curr = p
|
v
sched_can_stop_tick(rq)
|
v
examines rq->curr = old
|
v
may incorrectly allow tick stop
修复后的判断来源:
Before: rq->curr(old) -> sched_can_stop_tick() -> possibly stop tick
After : p(new) finite -> direct dependency -> keep tick enabled
概念类比
可以把 scheduler tick 看成厨房里的定时提醒器,有限时间片任务则是只能使用灶台十分钟的厨师。
旧逻辑在新厨师接手灶台时,仍询问上一位厨师是否需要定时器。上一位厨师可能已经做完,回答“不需要”,于是定时器被关掉。新厨师虽然只有十分钟配额,却再也收不到到时提醒,可能一直占用灶台。
补丁改为直接查看即将接手的厨师:
- 新厨师有明确时限,就立即打开定时器。
- 新厨师没有时限,才允许根据厨房的其他工作重新判断是否关闭定时器。
SCX_RQ_CAN_STOP_TICK 类似登记簿上的状态,而 TICK_DEP_BIT_SCHED 才是定时器的实际开关。补丁同时关注登记状态和真实开关,避免只改了登记簿却没有打开定时器。
Highlight 突出问题
-
关键问题不是普通的数据竞争,而是调度切换阶段的观察对象错误。
set_next_task_scx()已经知道下一个任务是p,但旧 helper 仍通过rq->curr判断,而rq->curr此时尚未完成切换。 -
影响集中在
nohz_fullCPU。
普通周期 tick 一直运行的 CPU 不容易表现出该问题;隔离 CPU、低干扰 workload 和 full dynticks 场景更需要重点验证。 -
有限时间片任务可能失去时间片到期前进性。
风险不只是统计误差,还可能表现为任务超出配置时间片、轮转延迟或其他 runnable 任务迟迟得不到调度。 -
设置 dependency 与清除 dependency 不对称是有意设计。
有限时间片任务可以无条件设置 dependency;恢复 tickless 则必须重新检查系统的其他 tick 需求,不能仅因 SCX 使用无限时间片就直接清除全局 scheduler dependency。 -
需要验证不同前驱调度类的切换。
建议覆盖 idle、CFS、RT、无限时间片 SCX 到有限时间片 SCX 的切换,并确认时间片到期后能及时发生重新调度。 -
需要验证实际 dependency 与
SCX_RQ_CAN_STOP_TICK的一致性。
尤其应覆盖 dependency 被其他 scheduler 路径修改、但 SCX 标志没有变化的情况。补丁对有限时间片任务每次直接设位,正是在防御这种不同步。 -
邮件正文存在截断。
输入中的 Andrea Righi 回复只保留了引用内容,未显示其实际评论;冯志敏的回复也在引用原提交时被截断。因此无法从当前材料确认评审结论、是否要求修改,或关联系列是否已经解决同一问题。
版本演进
当前线程只提供一个未标注版本的单补丁,没有可确认的 v1 -> v2 演进记录。
若后续发布新版本,值得关注的变化包括:
- helper 的命名和放置位置是否调整;
- 是否补充
Fixes:标签; - 是否增加
nohz_full与有限时间片切换测试; - 是否与 Andrea Righi 的关联补丁合并或重构;
- 是否进一步统一 CFS 与 SCX 的 next-task tick dependency 处理。
与其他相关 patch 系列的关联
冯志敏的回复给出了以下链接:
https://lore.kernel.org/all/20260708074812.1041434-1-arighi@nvidia.com/
从回复结构看,这是在提示 Andrea Righi 于 2026 年 7 月 8 日提交的相关工作。它很可能与 scheduler tick dependency 或本补丁触及的路径存在重叠。
不过,当前输入没有包含该关联邮件的标题和正文,而且两封回复都被截断,因此只能确认“评审者指出了一个相关系列”,不能可靠断言:
- 两个补丁是否完全重复;
- 哪一个覆盖范围更广;
- 当前补丁是否应撤回;
- 是否需要基于关联系列重写;
- maintainer 最终倾向采用哪套方案。
这是本线程最需要后续核实的评审信息。
分类说明
该线程应归类为 Bugfix。
虽然补丁标题使用的是“Keep tick enabled”,但提交说明明确描述了一个调度正确性缺陷:有限时间片 SCX 任务可能因为错误检查旧 rq->curr 而没有 scheduler tick,导致时间片无法正常到期。它不是单纯 feature、cleanup 或性能优化。
is_important 标记为 true,因为问题涉及调度前进性、时间片语义和 nohz_full CPU 上的任务公平运行,错误行为可能直接影响生产环境中的 CPU 隔离 workload。
一句话总结
该补丁让 sched_ext 根据即将运行的有限时间片任务直接打开 scheduler tick,避免因误看旧 rq->curr 而使时间片永不到期。