0/2 已展开

LLM 分析

sched/deadline:忽略 proxy-exec 的 sched_yield()

系列概况

  • 标题[PATCH] sched/deadline: Ignore proxy-exec sched_yield()
  • 作者:Christian Loehle christian.loehle@arm.com
  • 版本:v1(单 patch,无版本号)
  • 规模:1 文件,+3 行
  • 修改文件kernel/sched/deadline.c
  • 代码统计1 file changed, 3 insertions(+),核心改动只涉及 dequeue_task_dl 头部
  • Message-ID20260707174557.1428174-1-christian.loehle@arm.com
  • 完整性:包含 commit message、Fixes tag、Signed-off-by;正文给出 LKP/历史讨论链接背景;Juri Lelli 的回复 (ak9WDuicXdHkKeHq@jlelli-thinkpadt14.remote.csb) 给出 maintainer 认可。整体上下文闭环。

补丁目的

Proxy execution(一个 task 借用另一个 task 的调度上下文运行)机制下,rq->curr(真正跑代码的上下文)调用 sched_yield() 时,yield 会被转发到 rq->donor(donor)的调度类,让 donor 也一起让出。这个转发对 FIFO/RR/OTHER 是安全的:

  • FIFO/RR:没有同等优先级任务时立刻被自己抢回;
  • OTHER:不引发优先级反转。

但对 SCHED_DEADLINE 不一样:yield_task_dl() 把当前 DL 实体的 runtime 直接清零,强制它 sleep 直到 replenishment——这是强语义,相当于让 donor 主动放弃一个 deadline 周期。补丁要在 dequeue_task_dl() 入口处:proxy-exec 模式下、donor 不是 rq->curr 时直接忽略 yield,不让 DL 实体进入"零 runtime"状态。

旧流程的问题

引入 proxy-exec yield(127b90315ca0 sched/proxy: Yield the donor task)之后,所有调度类的 donor 都会被转发 yield。FIFO/RR/OTHER 的 yield 语义温和,问题不大;但 DL 的 yield 等同于强制让 donor 错过一个 deadline 周期,在 proxy-exec 链路里相当于把调度决策"代捐"出去,可能出现优先级反转、误丢时限、捐出任务的 bandwidth 浪费。

新流程

dequeue_task_dl() 入口增加一个 early return:只要处于 proxy-exec 且 curr/donor 不同,就不再执行 DL 的 dequeue/yield 路径,等价于"DL donor 上发生的 yield 被忽略"。

static bool dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags)
{
    if (sched_proxy_exec() && rq->curr != rq->donor)
        return;
    /* 原 yield/dequeue 逻辑保持不变 */
}

关键实现

/* kernel/sched/deadline.c */
static bool dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags)
{
    if (sched_proxy_exec() && rq->curr != rq->donor)
        return;
    /* ...原有 yield / dequeue 逻辑... */
}

判定点放在 dequeue_task_dl 而非 yield_task_dl,是因为 sched_yield() 在 CFS/RT 上调用的就是 dequeue,把短路放在最外层可以让 proxy-exec 的 yield 在进入 DL 路径之前就被拦截,无需复制任何 yield 语义。

+-------------------+        +-------------------+
| rq->curr (proxy)  |        | rq->donor (DL)    |
| calls sched_yield |        |                   |
+---------+---------+        +---------+---------+
          |                            ^
          v                            |
+---------+---------+        +---------+---------+
| yield_to_donor?   |------->| proxy execution   |
| forward to class  |        |                   |
+---------+---------+        +---------+---------+
          |                            |
          | BEFORE patch:              | AFTER patch:
          v                            v
+---------+---------+        +---------+---------+
| yield_task_dl:    |        | dequeue_task_dl   |
| runtime = 0,      |        | early return,     |
| sleep until       |        | skip DL path      |
| replenishment     |        |                   |
| [BAD]             |        | [OK]              |
+-------------------+        +-------------------+

类比

把 proxy execution 想成"你借同事的车去送货":

  • rq->curr 是正在开车的(实际执行方);
  • rq->donor车主(donor task);
  • sched_yield() 是"让出方向盘"。

正常调度类(FIFO/RR/OTHER)下,按下"让出"只是让方向盘回到同事手上,没人要用就回到你手里——车没坏。但 DL 的 yield 等于"把车直接送进强制保养",要等到下次补给才能再用。如果"让出"是你按的,却让车主的 DL 调度账号进保养,那车主本来该跑的 deadline 任务被无辜暂停,就是捐赠带宽被白白浪费。这个 patch 相当于:proxy-exec 时你按"让出",系统识别出是借车状态,不真的把车送修,只是让这一次调度回到正常队列。

Highlight:风险与注意点

  • 没有真实复现:作者明确说 "Haven't actually encountered the issue",是基于代码审查推断,存在"理论上对、实际不必要"的可能。
  • 早期 return 的语义dequeue_task_dl 还有其他调用方(不是只被 yield 调用),短路可能影响其他 dequeue 路径;目前看 sched_proxy_exec()rq->curr != rq->donor 的组合已经足够特化,但仍需确认不影响 group/deboost 等场景。
  • 修复 vs workaround:该 patch 加 Fixes: tag 回指 127b90315ca0,说明 upstream 也认可是回归修复;但若代理执行链路随后又改 yield 模型,这里需要重新审视。
  • 测试覆盖:未来应补 proxy-exec + DL 的回归测试,覆盖 yield、互斥持有期间 yield、并发 priority boost 等场景。
  • 后续维护者建议:Juri Lelli 的回复把场景落到"持有 mutex 时调用 sched_yield",提示这个修复与 lock-holder yield / proxy mutex 等系列有关联,需要联调。

版本变化

只有 v1。后续若有 v2,应重点关注:是否补 regression test、是否扩大 proxy-exec 短路条件(如包含 p == rq->donor 还是 rq->curr != rq->donor)、以及 maintainer 是否提出替代方案(例如在 yield_to_donor 那一层统一拦截)。

一句话总结

Proxy-exec 下把 sched_yield() 转发给 donor 在 DL 上语义过强,本 patch 在 dequeue_task_dl 入口短路,使 DL donor 不被"借车"时的 yield 误伤,避免丢失 deadline 周期。