0/4 已展开

LLM 分析

sched:删除死代码与修正注释的小清理

系列概况

  • 标题[PATCH 0/3] sched: minor cleanups
  • 作者:Zhan Xusheng <zhanxusheng@xiaomi.com>
  • 版本:v1(无版本号,系列号 [PATCH 0/3][PATCH 3/3],4 封邮件 = 1 cover + 3 patch)
  • 规模:3 个 patch,2 个文件改动,共 +5 / −10 行
  • 修改文件
    • kernel/sched/sched.h(patch 1/3)
    • kernel/sched/rt.c(patch 2/3、patch 3/3)
  • 代码统计(按 patch):
    • patch 1:sched.h 删 5 行
    • patch 2:rt.c 8 行改动(4+/4−)
    • patch 3:rt.c 注释修 1 处(1+/1−)
    • 合计 5 insertions, 10 deletions
  • Message-ID(首封/系列封面)20260804124947.3898447-1-zhanxusheng@xiaomi.com
  • 完整性:4/4 邮件齐全;正文与 diff 标记正常,覆盖 cover + 3 个 patch;无后续回复或 maintainer 评论。

补丁目的

作者在阅读 RT/fair 代码时顺手发现 3 处可以清理的地方,全部 No functional change

  1. sched_fair_runnable() 这个 static inline 自从 50653216e4ff("sched: Add support to pick functions to take rf")移除唯一调用者后就没用了,但因它是 inline,编译器不会触发 -Wunused-function,于是长期潜伏。
  2. RT 调度器的内部辅助函数 requeue_task_rt() 一直收一个 struct rq *rq 参数却从未使用;真正使用的是 &p->rtrt_rq_of_se() 拿到的 rt_rq
  3. rt.c 末尾 sched_rt_can_attach() 之后那个 #endif 注释写成了 !CONFIG_RT_GROUP_SCHED,但它闭合的是 #ifdef CONFIG_RT_GROUP_SCHED(块内没有 #else),注释与实际语义相反。

清理目标:让头文件更干净、函数签名更精简、注释不再撒谎;不动行为、不动 ABI。

旧流程的问题

  • sched_fair_runnable() 是个孤儿函数:声明、定义都在,但没人调用,属于历史遗留死代码。
  • requeue_task_rt(rq, p, head) 形参 rq 永远没被读,调用方在传它的时候只是凑齐签名,多余且误导。
  • #endif /* !CONFIG_RT_GROUP_SCHED */ 写反了取反,读代码的人按注释去 grep 反而搜不到对应宏块。

新流程

  • sched_fair_runnable() 直接从 sched.h 删除;同时保留仍在用的兄弟函数 sched_dl_runnable()sched_rt_runnable()
  • requeue_task_rt(p, head) 丢掉 rq 形参;三处调用方同步去掉 rq 实参:rq->donor 路径、check_preempt_equal_priotask_tick_rt
  • rt.c#endif 注释由 !CONFIG_RT_GROUP_SCHED 改为 CONFIG_RT_GROUP_SCHED,与该位置上方 #ifdef CONFIG_RT_GROUP_SCHED 配套。

Patch 概览

  • 1/3 sched/fair: Remove unused sched_fair_runnable():删 sched.h 中 5 行 static inline,附 50653216e4ff 作为最后一个调用者的来源。
  • 2/3 sched/rt: Remove unused rq argument from requeue_task_rt():函数签名减一个形参,3 处调用站点同步。
  • 3/3 sched/rt: Fix inverted #endif comment for the RT_GROUP_SCHED block#endif 注释里的 ! 去掉。

关键实现

Patch 1/3 — 删除 sched_fair_runnable()

-static inline bool sched_fair_runnable(struct rq *rq)
-{
-	return rq->cfs.nr_queued > 0;
-}

上下文:函数原位于 static inline bool sched_rt_runnable(struct rq *rq) 下方,本质是 rq->cfs.nr_queued > 0 的快捷检查;兄弟 sched_dl_runnable()sched_rt_runnable() 因为还在 pick_next_task 等路径里被引用而留下。删除它对其它代码无副作用,因为 50653216e4ff 已经把 pick_next_task 的 caller-side fastpath 重写走 rq->cfs 直接判断。

Patch 2/3 — requeue_task_rt() 简化为单参数

-static void requeue_task_rt(struct rq *rq, struct task_struct *p, int head)
+static void requeue_task_rt(struct task_struct *p, int head)
-	requeue_task_rt(rq, rq->donor, 0);
+	requeue_task_rt(rq->donor, 0);
-	requeue_task_rt(rq, p, 1);
+	requeue_task_rt(p, 1);
-	requeue_task_rt(rq, p, 0);
+	requeue_task_rt(p, 0);

函数体真正使用的是 for_each_sched_rt_entity(rt_se) + rt_rq_of_se(rt_se),因此 rq 形参在历史改写后就成了纯粹的占位。rq->donor 的调用点显式知道自己在哪个 rq 上,但传给辅助函数其实没用;删除形参可减少噪音并让接口自描述。

Patch 3/3 — #endif 注释去取反

-#endif /* !CONFIG_RT_GROUP_SCHED */
+#endif /* CONFIG_RT_GROUP_SCHED */

所在块是 #ifdef CONFIG_RT_GROUP_SCHED#endif 包裹的 sched_rt_can_attach() 函数定义;中间没有 #else,所以 ! 是历史写错的。改成正向匹配的文件惯用风格。

类比

把这三处清理比作 一次深度保洁阿姨巡楼

  • sched_fair_runnable() 像大厅里一张只剩桌腿的旧指示牌,标着"机房方向"但机房早就搬走 —— 直接拆掉。
  • requeue_task_rt(rq, p, head) 像快递柜取件码里多塞的一格"楼层号",柜机从来不用它看楼层,只看取件号 —— 把那一格去掉。
  • #endif /* !CONFIG_RT_GROUP_SCHED */ 像厕所门上贴的"非女厕",可里面其实是男厕 —— 把字改成"男厕",行为不变。

ASCII 流程图

Before cleanup                                After cleanup
-----------                                   ------------
sched.h                                       sched.h
+--------------------------------------------+
| sched_rt_runnable(rq)  [used]              |  sched_rt_runnable(rq)  [used]
| sched_fair_runnable(rq) [unused, static] X |  sched_rt_runnable only
| sched_dl_runnable(rq)   [used]             |  sched_dl_runnable(rq)   [used]
+--------------------------------------------+

rt.c::requeue_task_rt                          rt.c::requeue_task_rt
+----------------+                             +----------------+
| rq -- unused --|---> rt_rq via &p->rt       | (no rq) -----> rt_rq via &p->rt
+----------------+                             +----------------+
   ^  ^  ^                                          ^   ^   ^
   |  |  +-- task_tick_rt(rq,p,queued)              |   |   +-- task_tick_rt
   |  +----- check_preempt_equal_prio(rq,p)         |   +------ check_preempt_equal_prio
   +-------- yield_task_rt path (via donor)         +---------- yield_task_rt donor path

rt.c::sched_rt_can_attach end                    rt.c::sched_rt_can_attach end
+------------------------------+                 +-----------------------------+
| #ifdef CONFIG_RT_GROUP_SCHED |                 | #ifdef CONFIG_RT_GROUP_SCHED|
|   ...                        |                 |   ...                       |
| #endif /* !CONFIG_RT... X */ |                 | #endif /* CONFIG_RT...  */ |
+------------------------------+                 +-----------------------------+

Highlight:风险与注意点

  • 零行为改动验证:作者明确写 "No functional change" 三次;reviewer 应主要核对 50653216e4ff 之后真的没有第二个调用点(建议 git grep -n sched_fair_runnable 一次确认)。
  • requeue_task_rt 调用方覆盖:三处 caller 同步删 rq,漏一处会导致 Wunused-variable 或签名 mismatch;如果以后有人新加 caller,要按新的单参数签名写。
  • #endif 注释只是字符串:编译产物不动,但混淆读代码者;这种 review 顺手修,价值在长期可读性。
  • 可合入时机:典型 cleanup,无依赖任何未合并 patch,可独立走 tip:sched/core 的 cleanup 分支。
  • 真正可讨论点:是否要把 requeue_task_rt 直接去掉进一步 inline 到 requeue_rt_entity 调用点(series 之外的事),以及是否要把 sched_fair_runnable 的姊妹们接口统一化(如 sched_*_queued(rq) 命名风格)。

版本变化

仅 v1,无 v1→v2 的演进记录。

一句话总结

3 个清理型 patch:删除死代码 sched_fair_runnable()、给 requeue_task_rt() 甩掉永远不用的 rq 形参、把 rt.c#endif 取反注释改回正向,零行为改动。