sched discussion
[PATCH] sched/deadline: Ignore proxy-exec sched_yield()
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-ID:
20260707174557.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 周期。