fix(starry-perf): separate control and IRQ output locks - #1793
Conversation
There was a problem hiding this comment.
本 PR 将 PerfEvent 的任务控制面改为可睡眠的 Mutex,并将 eBPF 软件事件输出拆为 IRQ 安全的 SpinNoIrq 能力端点,从而避免控制回调在禁抢占上下文中分配、缺页或调度。映射页仍由 VMA 强引用持有,SET_OUTPUT 先快照目标再锁定源事件,锁顺序和页面生命周期均保持清晰。
影响范围限于 Starry perf 内部并发控制;已检查 perf_event_open、read、ioctl、mmap 与 bpf_perf_event_output 的入口、参数和 errno 路径,未见用户 ABI 变化。feature-development.md 不适用:这是不扩展功能边界的 bug 修复;starry/syscall.md 不适用:没有改变用户态 syscall 语义。新增 axtest 通过主动 yield_now() 覆盖修复前的禁抢占回归,且位于现有 axtest_runtime 注册路径中。
验证:review_pr_helper.py test 通过;helper 已识别 starry-kernel 变更;cargo fmt --all -- --check、git diff --check origin/dev...HEAD 通过。组织当前头 CI:81 项中 success=38、skipped=40、cancelled=3(取消项为 stale-run;无 failure),相关格式与 clippy 检查已通过,依照要求未重复完整本地测试。无既有评审评论或线程。
重复/重叠检查:base 不含此锁分层修复;#1577、#1601、#1602、#1603 仅在 perf 表面有后续整合冲突风险,并未实现本修复。未发现 crates.io patch、冲突或新增/变更 app 的运行时适用项。无遗留问题。
Powered by gpt-5.6-terra
问题
PerfEvent当前用一个SpinNoPreempt同时保护任务控制路径和 eBPF 输出路径。read、ioctl、mmap等任务上下文操作会在该锁内调用具体 perf event 的回调,而这些回调允许分配内存、缺页或调度;因此一旦回调发生调度,就会触发 atomic-context panic。这个问题可以从 #1775 的
2f4e8cb独立提取,不依赖该 PR 的调度器、网络或其他架构改动。修改
PerfEvent的任务控制面改为ax_sync::Mutex,允许回调在任务上下文中安全睡眠或调度。BpfPerfOutput:SpinNoIrq保护 IRQ/trace producer 可访问的状态;IrqNotify延迟唤醒 poll waiter。SpinNoIrq,避免同 CPU IRQ 重入。device_mmap在短自旋锁外完成连续页分配,并在发布映射前重新检查状态;VMA 继续持有强引用,输出状态只保留Weak,不改变原有页生命周期。PERF_EVENT_IOC_SET_OUTPUT先快照目标输出再锁定源事件,避免两个可睡眠锁嵌套。yield_now(),验证 perf 控制面没有禁用抢占。本修改不新增 syscall、属性布局或 errno 语义;
perf_event_open、read、ioctl、mmap和bpf_perf_event_output的用户 ABI 保持不变。回归证据
在修复前,仅加入回归测试后运行:
稳定触发:
应用修复并重放到最新
dev后,同一命令通过:其他本地检查:
cargo xtask clippy --package starry-kernel:24/24 checks passedcargo fmt --all -- --checkgit diff origin/dev...HEAD --check真实
ebpf/sched_traceQEMU 用例完成了用户态程序和 StarryOS 编译,但现有 x86_64 app 启动配置在进入内核前被 QEMU 拒绝:该配置与
origin/dev一致;因此没有把这个未进入内核的运行记为通过。物理板和 self-hosted 流程未在本地执行。与现有 PR 的关系
2f4e8cb提取并按当前dev的锁原语适配。PerfEvent的SpinNoPreempt,没有覆盖本问题;这些 PR 合并前需要处理文件冲突或重放本修复。