0/8 已展开

LLM 分析

Linux scheduler:迁移 static_key → static_branch API

系列概况

  • 标题: [PATCH RESEND] sched: Move some scheduler fields to new static branch API
  • 作者: Hongyan Xia <hongyan.xia@transsion.com>
  • 版本: RESEND(无 v 编号,无 series index/total)
  • 规模: 单 patch;RESEND 备注说明原是更大的 series,本次拆分单独重发
  • 修改文件: kernel/sched/core.ckernel/sched/fair.c
  • 代码统计: 13 行新增 / 13 行删除(core.c 18 行变更,fair.c 8 行变更)
  • Message-ID: 20260819080932.11564-1-hongyan.xia@transsion.com
  • 完整性: patch 文本完整;thread 中多条回复正文在 lore 上被截断(被引用上下文不全)

补丁目的

kernel/sched/ 中仍使用老 static_key_* 抽象的两处静态分支迁移到新的 static_branch_* API:

  1. __cfs_bandwidth_used 直接以 struct static_key 定义并以 static_key_false/slow_* 操作 —— 这条已经被标记 deprecated,是真正的 fix。
  2. sk_dynamic_* 使用 static_key_{enable,disable},未明确 deprecate,但作者趁此机会统一到 static_branch_*,保持代码风格一致。

作者在 commit message 中明确写明 "No functional change",因此这个 patch 是可读性 + 一致性改进 + 顺手清掉 deprecated 用法。

旧流程的问题

static_key 抽象要求开发者:

  • 手动声明 struct static_key sk;(不带初始化)
  • 调用时取地址 &sk.key
  • 读侧用 static_key_false()、写侧用 static_key_slow_inc_cpuslocked() / static_key_slow_dec_cpuslocked()

这种"裸 struct + 显式 &" 的写法散布在 kernel 中,新人难以一眼看出"这是一个 jump label"。新 static_branch_* 系列把声明 (DEFINE_STATIC_KEY_FALSE) 和读写 (static_branch_unlikelystatic_branch_*_cpuslocked) 统一在一组语义清晰的 API 下,更易读、与其他子系统风格一致。

新流程

改名映射关系:

老调用新调用
struct static_key sk;DEFINE_STATIC_KEY_FALSE(sk);
static_key_false(&sk)static_branch_unlikely(&sk)
static_key_slow_inc_cpuslocked(&sk)static_branch_inc_cpuslocked(&sk)
static_key_slow_dec_cpuslocked(&sk)static_branch_dec_cpuslocked(&sk)
static_key_enable(&sk.key)static_branch_enable(&sk)
static_key_disable(&sk.key)static_branch_disable(&sk)

语义保持不变:声明成默认 false,慢路径在 inc/dec 时改写 jump label 目标;读侧分支仍 unlikely

Patch 概览

只一封单 patch,无子 patch 列表。RESEND 备注里两点改动相对"原始系列":

  1. 把原来的 series 拆成单独 patch,便于 review。
  2. 顺手把 sk_dynamic_* 也迁到新 API。

关键实现

/* kernel/sched/core.c:宏改名 */
-# define preempt_dynamic_key_enable(f) static_key_enable(&sk_dynamic_##f.key)
-# define preempt_dynamic_key_disable(f) static_key_disable(&sk_dynamic_##f.key)
+# define preempt_dynamic_branch_enable(f) static_branch_enable(&sk_dynamic_##f)
+# define preempt_dynamic_branch_disable(f) static_branch_disable(&sk_dynamic_##f)

__sched_dynamic_update 中五个 case(none / voluntary / full / lazy、加上 default 分支)保持原结构,只是宏名替换成 preempt_dynamic_branch_{enable,disable}

/* kernel/sched/fair.c:cfs_bandwidth 入口 */
-static struct static_key __cfs_bandwidth_used;
+static DEFINE_STATIC_KEY_FALSE(__cfs_bandwidth_used);

 static inline bool cfs_bandwidth_used(void)
 {
-    return static_key_false(&__cfs_bandwidth_used);
+    return static_branch_unlikely(&__cfs_bandwidth_used);
 }

 void cfs_bandwidth_usage_inc(void)
 {
-    static_key_slow_inc_cpuslocked(&__cfs_bandwidth_used);
+    static_branch_inc_cpuslocked(&__cfs_bandwidth_used);
 }

 void cfs_bandwidth_usage_dec(void)
 {
-    static_key_slow_dec_cpuslocked(&__cfs_bandwidth_used);
+    static_branch_dec_cpuslocked(&__cfs_bandwidth_used);
 }

#ifdef CONFIG_JUMP_LABEL 分支保持不变;非 jump label 走 fallback 返回 false。

类比

jump label 就像大楼里可变的指示牌:

  • 老 API 让你自己去建材市场买牌子、装到墙上、再去物业登记开关台账(static_key_*)。
  • 新 API 给你一个统一服务台(static_branch_*),一句话"开/关"就行,台账自动维护。

这次 patch 就是把所有手工装配的指示牌统一换成服务台呼叫 —— 牌子指向没变、来往行人看到的箭头没变、只是姿势更优雅,物业也更开心。

Highlight:风险与注意点

  1. 邮件编码被 MUA 弄坏:transsion 的 Outlook 把 patch 编码成一种奇怪 quoted-printable(每行末尾 =0A=,包括最后一行),触发 Peter 的 review 脚本把整封邮件吃掉;Peter 已修脚本,但若 reviewer 工具链再次遇到类似 encoding,需要二次跟进。
  2. sk_dynamic_* 后续会被移除:Peter 提到 Mark Rutland 已有系列准备把它们大部分删掉,只保留 lazy check;本次改名是临时一致化,与 Mark 的清理系列存在重叠/对齐关系,作者应在 v2 中确认两者不会互相冲突。
  3. commit message 缺乏 deprecation 上下文:Shrikanth 评审时希望补充"为什么 deprecated"的链接(如 Documentation 或 git blame 说明),否则 reviewer 难以验证迁移必要性。
  4. cpuslocked 路径需重点验证:本次替换直接影响 hotplug / cgroup 路径下的 inc/dec_cpuslocked 调用,需确认在 CONFIG_JUMP_LABEL off 的 fallback 路径下仍正确返回 false,避免带宽控制误判。

版本变化

相对原始 series,RESEND 做了两点:

  1. 把整组 series 拆成单独 patch 提交,便于单点评审。
  2. sk_dynamic_* 也一并迁到 static_branch_*,扩大了一致化范围。

v2 及以上版本未见(thread 中无 v2 标签邮件)。

一句话总结

把 scheduler 里仍用老 static_key_*__cfs_bandwidth_usedsk_dynamic_* 统一迁到新的 static_branch_* API,无功能变更、纯可读性 + 一致性改进,并作为 Mark 后续清理系列的前置。

                 Review Flow
                 -----------
         +---------+         +-----------+
         | Hongyan |         |   Peter   |
         |   Xia   |         | Zijlstra  |
         +----+----+         +-----+-----+
              |                    |
              | patch (RESEND)     |
              |------------------->|
              |                    |
              |   MUA mangled QP   |
              |   script chokes    |
              |<-------------------|
              |                    |
              | debug request      |
              |------------------->|
              |                    |
              | =0A= + =$ tail     |
              | issue explained    |
              |<-------------------|
              |                    |
              | (more replies,     |
              |  several bodies    |
              |  truncated in lore)|
              +--------------------+

              API Rename Map
              --------------
struct static_key sk;          --> DEFINE_STATIC_KEY_FALSE(sk);
static_key_false(&sk)          --> static_branch_unlikely(&sk)
static_key_slow_inc_cpuslocked --> static_branch_inc_cpuslocked
static_key_slow_dec_cpuslocked --> static_branch_dec_cpuslocked
static_key_enable(&sk.key)     --> static_branch_enable(&sk)
static_key_disable(&sk.key)    --> static_branch_disable(&sk)