Skip to content

refactor(ax-task): make IRQ runtime mandatory#1451

Open
ZR233 wants to merge 28 commits into
rcore-os:devfrom
ZR233:codex/starry-irq-runtime-refactor
Open

refactor(ax-task): make IRQ runtime mandatory#1451
ZR233 wants to merge 28 commits into
rcore-os:devfrom
ZR233:codex/starry-irq-runtime-refactor

Conversation

@ZR233

@ZR233 ZR233 commented Jun 30, 2026

Copy link
Copy Markdown
Member

问题

PR #1451 原本在修 hard IRQ wake 与设备 runtime 丢 wake/卡死问题。继续梳理后发现,irq 作为可选 Cargo feature 会让多任务调度、future runtime、WaitQueue timeout、timer、设备 IRQ registrar 同时维护“有 IRQ”和“无 IRQ”两套语义;这会把关键 wake 路径拆成兼容分支,增加 hard IRQ 与线程睡眠边界的丢 wake 风险,也让 CI/测试配置持续携带已经没有实际意义的 */irq feature 转发。

改动

  • 保留 hard IRQ wake 设计:IRQ callback 只发布 atomic seq/bits、合并 pending wake,并通过预先注册的 IrqTaskWaker 唤醒宿主任务;真正 run queue 插入和 waiter 唤醒留到 IRQ epilogue 或 task context。
  • ax-task 多任务 runtime 收敛为默认 IRQ-aware:删除 irq feature,multitask 直接包含 timer list、IRQ wake queue、IrqNotifyLocalExecutor 和 timer future;block_on 统一使用 IrqTaskWaker,不再保留 WeakTask/no-IRQ fallback。
  • ax-halax-plataxplat-dynax-plat-riscv64-sg2002 的 IRQ API 改为默认可见;没有真实 interrupt controller 的平台在实现层返回 Unsupported 或 no-op,而不是靠全局 Cargo feature 隐藏接口。
  • ax-runtime、设备 glue、axklib 的 IRQ 注册/解析路径改为默认存在;block/net/display/input 不再因全局 irq feature 关闭而忽略 IRQ binding。
  • 清理 ax-featax-stdax-apiax-posix-apiax-libcax-driver、apps、Starry、Axvisor、test-suit、axbuild 和文档里的旧 */irq feature 转发与描述。
  • 保留单任务 api_s 的 busy-wait/wfi sleep/yield 路径;这属于“无调度 runtime”,不再作为“多任务无 IRQ”兼容模式存在。

设计逻辑

多任务 ArceOS/Starry 的调度、timer、future runtime 和设备完成路径都依赖中断语义。把 IRQ 做成基础能力后,hard IRQ fast path 的 contract 更清晰:保存状态、合并 wake、触发 IRQ-safe kick;不分配、不拿 WaitQueue/runqueue/scheduler 普通锁、不在 callback 内切换任务。

设备没有 IRQ binding 时仍可由具体设备/driver 选择 polling fallback,但这不再由全局 irq Cargo feature 控制。这样可以保留真实硬件差异,同时避免同一个 runtime 内维护两套互斥调度语义。

CI 测例耗时对比

  • PR run: 28497595223,head a936d3957,branch codex/starry-irq-runtime-refactor
  • dev 基线: 28496301603,head 249ce92fe,branch dev,为当前可见最新成功的 dev push CI。
  • 统计口径:只比较已完成且同名的 Test ... jobs;排除 skipped、format、sync-lint、spin-lint、clippy、publish 等非测例 jobs。耗时取 GitHub Actions job 的 completed_at - started_at
  • 符号口径:本 PR - dev 为负数表示本 PR 更快,为正数表示本 PR 更慢。
  • 块设备口径:本 PR 没有把 qemu-smp1/system 从 NVMe 改为 virtio。现有配置是 aarch64/riscv64/x86_64 使用 NVMe,loongarch64 使用 virtio-blk;因此下表把 Starry QEMU 拆成 NVMe 与 virtio-blk 两类。
指标 dev 基线 本 PR 本 PR - dev 结论
可比测例数量 22 22 0 持平
测例 job 总耗时 137m30s 124m33s -12m57s 快 12m57s (9.4%)
并行关键测例耗时 11m32s 10m11s -1m21s 快 1m21s (11.7%)
Starry QEMU NVMe 测例总耗时(aarch64/riscv64/x86_64) 31m50s 20m47s -11m03s 快 11m03s (34.7%)
Starry QEMU virtio-blk 测例总耗时(loongarch64) 9m08s 8m44s -24s 快 24s (4.4%)
Starry QEMU 全部测例总耗时 40m58s 29m31s -11m27s 快 11m27s (27.9%)
测例 dev 基线 本 PR 本 PR - dev 结论
Test arceos aarch64 qemu / run_host 3m38s 4m16s +38s 慢 38s (17.4%)
Test arceos loongarch64 qemu / run_host 3m32s 2m39s -53s 快 53s (25.0%)
Test arceos riscv64 qemu / run_host 2m51s 4m01s +1m10s 慢 1m10s (40.9%)
Test arceos x86_64 qemu / run_host 3m09s 4m22s +1m13s 慢 1m13s (38.6%)
Test axloader HTTP smoke / run_host 6m34s 7m52s +1m18s 慢 1m18s (19.8%)
Test axvisor aarch64 qemu / run_host 2m51s 3m38s +47s 慢 47s (27.5%)
Test axvisor loongarch64 qemu / run_container 2m46s 2m45s -1s 快 1s (0.6%)
Test axvisor riscv64 qemu / run_host 3m26s 3m24s -2s 快 2s (1.0%)
Test axvisor self-hosted board orangepi-5-plus-linux / run_host 7m11s 6m22s -49s 快 49s (11.4%)
Test axvisor self-hosted board phytiumpi-linux / run_host 6m55s 5m57s -58s 快 58s (14.0%)
Test axvisor self-hosted board roc-rk3568-pc-linux / run_host 7m50s 8m08s +18s 慢 18s (3.8%)
Test axvisor self-hosted x86_64 / run_host 7m55s 7m42s -13s 快 13s (2.7%)
Test axvisor self-hosted x86_64 UEFI / run_host 6m04s 7m02s +58s 慢 58s (15.9%)
Test axvisor x86_64 svm hosted / run_host 4m44s 25s -4m19s 快 4m19s (91.2%)
Test starry aarch64 qemu / run_container 10m46s 6m54s -3m52s 快 3m52s (35.9%)
Test starry loongarch64 qemu / run_container 9m08s 8m44s -24s 快 24s (4.4%)
Test starry riscv64 qemu / run_container 9m32s 5m58s -3m34s 快 3m34s (37.4%)
Test starry self-hosted board aka-00-sg2002 / run_host 6m29s 5m39s -50s 快 50s (12.9%)
Test starry self-hosted board orangepi-5-plus / run_host 9m47s 10m11s +24s 慢 24s (4.1%)
Test starry self-hosted board visionfive2 / run_host 6m50s 7m03s +13s 慢 13s (3.2%)
Test starry x86_64 qemu / run_container 11m32s 7m55s -3m37s 快 3m37s (31.4%)
Test with std / run_host 4m00s 3m36s -24s 快 24s (10.0%)

说明:这是单次 CI run 的 job 级对比,少量 self-hosted/board/QEMU 测例会受宿主机负载和队列影响波动。主要稳定收益集中在 NVMe-backed Starry QEMU:aarch64 快 3m52s,riscv64 快 3m34s,x86_64 快 3m37s;LoongArch 的 qemu-smp1/system 是既有 virtio-blk 配置,快 24s。

Review follow-up

  • IrqTaskWaker 改为持有 WeakAxTaskRef,并继续校验 task id 与 generation;旧 IRQ callback 不再因为保存 waker 而强持有已退出 task。
  • IrqNotify 不再把第一个 waiter 固定在 Once 里,而是允许当前 deferred worker 重新 arm;IRQ fast path 只读稳定 waiter 指针并调用弱引用 IrqTaskWaker
  • WaitQueue::notify_*_from_irq 保留兼容入口,但文档明确标注它不是 hard IRQ safe,并加 in_irq_context() debug assert;net/KPU 的 hard IRQ call site 已改走 IrqNotify/IrqTaskWaker
  • wake-ipi 现在向 ax-task?/irq-wake-ipi 转发;smp+wake-ipi 可发送轻量 IRQ wake IPI,smp+ipi 仍启用完整 ax-ipi callback queue,纯 smp 则保持无远端 IPI 的原语义。
  • legacy future IRQ poll bridge 的 hard IRQ callback 改为捕获预分配 per-IRQ state;IRQ 中只写 atomic pending 并 poke IrqNotify,不再锁 IRQ_STATE 或触碰 PollSet
  • IrqNotify 不再复用 WaitQueue 作为 hard-IRQ 通知睡眠路径;等待方改用 IrqTaskWaker + future_blocked_resched 的 abort-sleep 复查协议,封住 publish-before-sleep/lost-wake 窗口。
  • ax-runtime/wake-ipi 直接转发到 ax-task?/irq-wake-ipi,避免直接启用 ax-runtime feature 时只注册轻量 IPI handler、但 axtask 不会发送远端 IRQ wake IPI 的半启用状态。
  • 修复 latest Starry CI 卡死:x86_64 的硬 IRQ vector->IRQ 反查改为预发布 atomic map,避免中断中抢 IOAPIC lock 失败后遗漏 level IRQ clear;switch_to 保持 prev task 强引用,避免 future/IRQ preempt 路径 drop 当前任务;IrqTaskWaker::wake()wake_from_irq() 分层,普通 Rust waker 在 task context 直接 unblock scheduler,hard IRQ 仍只入 pending queue。
  • 本轮进一步把类型边界锁死:IrqTaskWaker 拆成 task-context TaskWaker 与 hard-IRQ-only HardIrqWakerRuntimeEvent/serial/block/net/perf/usbfs 等 hard IRQ 注册点只保存 HardIrqWaker;普通 Rust Wakerblock_onLocalExecutor 和 deferred worker 只走 TaskWaker
  • IrqNotify 收敛为 HardIrqSignal,表达为 pending bit + deferred worker wake,不再伪装成 WaitQueue;WaitQueue::notify_*_from_irq 改名为 deferred-only API,避免被误认为 hard IRQ safe。
  • future timer 改为全局 FutureTimerService:timer IRQ 只标记 service pending 并 wake worker,worker 在 task context drain expired wakers;service pending 时不把已过期 future deadline 继续暴露给硬件 timer,避免 IRQ storm,同时不丢 runtime 内部 deadline。

Rebase update

  • 2026-07-03 再次 rebase 到最新 origin/dev;当前 head 为 738bddf67eddc8bb526b12d4f2c396b8ed1fc96d
  • rebase 冲突点在 axtask/src/api.rs:保留最新 dev 的 AtomicContextSnapshot 诊断结构,同时按本 PR 语义继续把 IRQ 判断收敛为默认 IRQ-aware 路径。
  • rebase 后修复 ax-plat/src/irq.rs 中由上游新增 in_irq_context() 与本分支 IRQ mandatory 转发叠加造成的重复定义,保留直接读取 per-CPU IRQ context 的实现。
  • 本轮 review 修复:LocalExecutor/LocalSpawner 支持真正的 non-Send local future,并用 Rc<Cell<_>> 回归测试覆盖;KPU IRQ 等待改成懒启动 deferred worker,hard IRQ callback 只触发 HardIrqSignal,不再把任意用户等待任务直接 arm 到 hard IRQ signal 上。
  • bare-task 通过 trait-ffi 定义 OS ABI,不依赖 ax-halax-percpuax-kspinax-schedax-task;host 测试内每个 host thread 模拟一个 CPU,并用 virtual IRQ controller 覆盖 edge/level IRQ、IPI、timer IRQ、IRQ epilogue、remote hard IRQ wake 和 generation 失效。

验证

  • cargo fmt
  • cargo test -p bare-task --features "host-test smp ipi irq" -- --test-threads=1
  • cargo test -p ax-task --features "test smp ipi sched-rr" irq_task_waker -- --test-threads=1
  • cargo test -p ax-task --features "test smp ipi sched-rr" runtime_event -- --test-threads=1
  • cargo test -p ax-task --features "test smp ipi sched-rr" local_executor -- --test-threads=1
  • cargo test -p ax-task --features "test smp ipi sched-rr" remote -- --test-threads=1
  • cargo xtask clippy --package bare-task
  • cargo xtask sync-lint --since origin/dev
  • git merge-base --is-ancestor origin/dev HEAD
  • git diff origin/dev --check
  • cargo xtask clippy --package ax-task
  • cargo xtask clippy --package riscv_vcpu
  • cargo xtask axvisor test qemu --arch riscv64 --test-group normal --test-case smoke
  • cargo test -p ax-task --features "test smp ipi sched-rr" task_timer_wakeup_is_deferred_through_irq_wake_queue -- --test-threads=1
  • cargo test -p ax-task --features "test smp ipi sched-rr" irq_task_waker -- --test-threads=1
  • cargo test -p ax-task --features "test smp ipi sched-rr" runtime_event -- --test-threads=1
  • cargo test -p axpoll -- --test-threads=1
  • cargo test -p ax-fs-ng drain_ -- --test-threads=1
  • cargo xtask clippy --package axpoll
  • cargo xtask clippy --package ax-fs-ng
  • cargo xtask clippy --package ax-runtime
  • cargo xtask clippy --package starry-kernel
  • cargo xtask starry test qemu --arch aarch64 --test-case qemu-smp1/system/bug-openat-abs-path-honors-invalid-dirfd:本地 qemu-run 2.09s,总计 21.58s
  • cargo xtask starry test qemu --arch aarch64 --test-case qemu-smp1/system:本地 qemu-run 31.93s,总计 37.64s,未复现 Starry waitpid/openat 卡死。
  • cargo xtask starry test qemu --arch aarch64 --test-case qemu-smp4/system:本地 qemu-run 22.76s,总计 45.76s,未复现 Starry QEMU 卡死。
  • cargo xtask starry test qemu --arch loongarch64 --test-case qemu-smp4/system/test-cargo-jobserver-wait:本地 qemu-run 9.23s,总计 16.37s
  • cargo xtask starry test qemu --arch loongarch64 --test-case qemu-smp4/system:本地 qemu-run 35.54s,总计 42.56s

ArceOS 说明:ArceOS x86_64/aarch64/riscv64 的 job 级别变慢主要来自 host-side build/prep,而不是 QEMU 内测试变慢。分段后,Rust test cargo build 分别增加约 +33.6s/+22.7s/+28.9s,xtask 到首个 QEMU config 分别增加约 +36.9s/+18.8s/+37.3s;对应 Rust QEMU case 本体为 -0.3s/-0.2s/+1.2s。LoongArch 整体反而更快。两次运行使用不同 self-hosted runner,且 self-hosted 不启用 rust-cache;编译 crate 数一致,因此这里更像 runner/cache/load 与 host-side 构建波动,不是 IRQ runtime 的运行时性能回退。

CI follow-up

  • 2026-07-03 继续修复 riscv64 Starry QEMU 卡死根因:RISC-V/SMP 场景下 init/idle task 创建时没有记录真实 boot CPU,timer/hard-IRQ wake 会按 TaskCore::cpu_id() 投递到错误 CPU;现在 init task 初始化时记录 this_cpu_id() 并保持 on_cpu invariant。同步加固 WaitQueue::wait_until / wait_timeout_until 的 register-then-recheck 协议,避免 condition 在入队后、真正 sleep 前变为 true 时仍睡死。
  • 本地验证 latest head 738bddf67eddc8bb526b12d4f2c396b8ed1fc96dcargo test -p ax-task --features "test smp ipi sched-rr" test_wait_until_rechecks_after_queueing_without_sleeping -- --test-threads=1 通过;cargo xtask clippy --package ax-task 18/18 通过;cargo xtask arceos test qemu --arch riscv64 --test-group c --test-case all 通过,总计 6.58s;cargo xtask starry test qemu --arch riscv64 --test-case qemu-smp1/system 通过,qemu-run 69.69s,总计 75.17s,低于 10 分钟阈值。
  • 已推送 latest head 738bddf67eddc8bb526b12d4f2c396b8ed1fc96dZR233/codex/starry-irq-runtime-refactor;GitHub 当前尚未为该 head 生成新的 PR check run,后续以新 head 的真实 CI 日志为准。
  • 2026-07-03 最新 CI 中 Starry riscv64 QEMU 没有卡死,而是在 axvisor riscv64 qemu 失败后被 fail-fast 取消;失败根因为 RISC-V vCPU 在 guest run 期间收到 host supervisor software interrupt 后没有 VM-exit 分支,直接 panic Unhandled trap: Interrupt(1)。已将 SupervisorSoft 路由为 host external interrupt,让现有 host IRQ path 清 SSIP 并执行 IPI handler;本地 axvisor riscv smoke 复跑通过。
  • 2026-07-03 修复 riscv64 Starry QEMU 卡死根因:task sleep/WaitQueue timeout 的 timer wake 不再在 timer hard IRQ callback 内直接 unblock_task,而是预先保存 HardIrqWaker,到期后只入 IRQ wake queue,由 IRQ epilogue 统一 drain;新增 task_timer_wakeup_is_deferred_through_irq_wake_queue 回归测试锁住该 contract。
  • 本地复核 riscv64 qemu-smp1/system 两轮均通过且低于 10 分钟阈值:清 cache 运行 qemu-run 69.73s、总计 104.99s;cache hit 复跑 qemu-run 58.45s、总计 64.51s
  • 旧 head 8089a5456fc9b53e30ebd31108667e55c7837558 的 fork push CI 28580203159 已通过;Starry QEMU 用时:aarch64 6m05s、riscv64 4m54s、x86_64 7m10s、loongarch64 9m26s,均低于 10 分钟阈值。
  • 2026-07-03 已 force-with-lease 推送最新 head 6a20b326c920aecd12109fbac8c78cf79ef6e6fe;该 head 包含最新 origin/dev、本轮 review 修复和 rebase duplicate cleanup,等待新的 fork/PR CI 结果。

Latest rebase/riscv64 follow-up

  • 2026-07-03 rebase 到最新 origin/dev 后,修正因上游删除 ax-feat/defplat / ax-feat/myplat 后遗留在 Starry/axlibc 配置里的 stale feature 转发;否则 latest dev 上 Starry 构建会在 Cargo feature 解析阶段失败。
  • 当前 head 为 ead1c30cbe4e2015a1ae3257cae3d187fb52e283,已推送到 ZR233/codex/starry-irq-runtime-refactor
  • 本地复核 RISC-V Starry 卡死链路:完整 cargo xtask starry test qemu --arch riscv64 --test-case qemu-smp1/system 通过,qemu-run 50.60s,总计 56.00s,低于 10 分钟阈值。额外分段复核 tail40prefix56+tmpfs 均通过,用于排除 rebase 后的长序列 exit 卡死残留。
  • 本轮相关验证:cargo fmt --check 通过;cargo test -p ax-task --features "test smp ipi sched-rr" test_wait_until_rechecks_after_queueing_without_sleeping -- --test-threads=1 通过;cargo xtask clippy --package ax-task 18/18 通过;cargo xtask arceos test qemu --arch riscv64 --test-group c --test-case all 通过,总计 8.37s
  • 根因结论保持不变:RISC-V/Starry hang 来自调度 wake target 与 wait/sleep 窗口问题,而不是测试超时阈值问题;init task 现在记录真实 boot CPU,WaitQueue 在入队后、真正 resched 前重新检查 predicate/deadline,timer wake 继续通过 IRQ wake queue deferred drain。

Latest riscv64 Starry hang fix

  • 2026-07-03 针对 CI Test starry riscv64 qemu / run_container 的 1800s timeout 继续定位:历史失败日志显示 guest 已完成 /usr/bin/starry-test-suit/bug-tmpfs-cwd-drop-safe 并打印 ALL TESTS PASSED,但没有继续打印 grouped runner 的 STARRY_SYSTEM_TEST_PASSED,说明卡在测试进程退出后的父进程 wait/shell 回收链路,而不是该 C testcase 本身。
  • 根因收敛到 WaitQueue::wait_until / wait_timeout_until 的 abort-before-sleep 协议:blocked_resched_abortable() 在 predicate/deadline 已满足时会把当前任务从 Blocked 恢复为 Running,但没有同步从 wait queue 摘除并清掉 in_wait_queue。这会留下“运行中但仍挂在 wait queue”的幽灵 waiter,后续 notify_one/all 可能把唤醒消费在错误任务上,使真实 waitpid/exit waiter 丢 wake。
  • 修复方式:blocked_resched_abortable() 改为接收 wait queue 本体,自己完成入队、复查、abort 时摘队和 state 恢复,保证 wait queue membership 与 task state 在同一个协议里闭合;新增 test_blocked_resched_abortable_removes_waiter_before_return 锁住这个不变量。
  • 当前 head 为 e3fb6e06b19c8ef50c6ade989f8a6cad4ff39267,已推送到 ZR233/codex/starry-irq-runtime-refactor
  • 本地验证:cargo fmt --check 通过;cargo test -p ax-task --features "test smp ipi sched-rr" abortable -- --test-threads=1 通过;cargo test -p ax-task --features "test smp ipi sched-rr" test_wait_until_rechecks_after_queueing_without_sleeping -- --test-threads=1 通过;cargo xtask clippy --package ax-task 18/18 通过;同 CI container image 复现 target/debug/tg-xtask starry test qemu --arch riscv64 通过,system qemu-run 49.24s,总计 154.14s;本地新 head timeout 10m cargo xtask starry test qemu --arch riscv64 --test-case qemu-smp1/system 通过,qemu-run 49.83s,总计 97.15s

Latest dev rebase

  • 2026-07-03 再次 rebase 到最新 origin/dev 04e5de0cc;当前 head 为 1f26c632375bb6e5e509bce23be2680ac544a620,已推送到 ZR233/codex/starry-irq-runtime-refactor
  • rebase 冲突点在 platforms/somehal/src/arch/x86_64/mod.rs:保留最新 dev 的 X86IoApicCpuInterface atomic vector route 表,继续保证 hard IRQ dispatch 不需要拿 IOAPIC/intc 锁。
  • 本轮验证:cargo fmt --check 通过;git diff --check origin/dev...HEAD 通过;cargo xtask clippy --package ax-task 18/18 通过;cargo xtask clippy --package somehal 7/7 通过;cargo test -p ax-task --features "test smp ipi sched-rr" abortable -- --test-threads=1 通过。

Latest axvisor CI follow-up

  • 2026-07-03 最新 PR CI head 1f26c632375bb6e5e509bce23be2680ac544a620 中,Starry QEMU jobs 已通过;失败项是 Test axvisor self-hosted x86_64 / run_hostsmoke-vmx,CI 日志显示 Linux guest 已两次到达 ~ # shell prompt,但原配置依赖 ostool 在 prompt 后延迟注入 shell_init_cmd 再匹配 guest linux test pass!,第二次 prompt 不会重新触发 one-shot 注入,最终等到 600s 超时。
  • 修复方式:smoke-vmx 的测试目标收敛为“嵌套 VMX Linux guest 到达 shell prompt”,直接以 ~ # 作为成功条件,移除延迟 shell_init_cmd 注入;新增 x86_vmx_smoke_uses_prompt_success_without_delayed_shell_injection 回归测试,防止该 smoke 测例再次依赖 one-shot delayed shell command。
  • 本地验证:先用旧配置确认新增回归测试会失败;修复后 cargo test -p axbuild x86_vmx_smoke_uses_prompt_success_without_delayed_shell_injection -- --test-threads=1 通过;cargo xtask clippy --package axbuild 通过;timeout 12m cargo xtask axvisor test qemu --arch x86_64 --test-case smoke-vmx 通过,qemu run: 7.74s,总计 11.43s

Latest wait-queue membership CI follow-up

  • 2026-07-03 最新 PR CI head da499947b6a73de010def5d3c431995020fccea7 中,Test axvisor self-hosted x86_64 / run_host 已通过;Starry x86_64/loongarch64 QEMU 已通过,但 riscv64/aarch64 Starry QEMU 超过 10 分钟阈值后按约定取消并抓日志。
  • 日志症状:riscv64 已在 /usr/bin/starry-test-suit/bug-tmpfs-cwd-drop-safe 内打印 ALL TESTS PASSED,但没有继续打印 runner 的 STARRY_SYSTEM_TEST_PASSED;aarch64 停在 test-fcntl-deadlock-smp 后半段。这说明测试子进程已经完成或接近完成,父进程 wait/exit/notify 回收链路丢 wake,而不是 block/NVMe 数据路径卡住。
  • 根因:TaskCore 过去只用一个全局 in_wait_queue bool 表示“是否在某个 wait queue”。如果旧 wait queue 里残留的 stale entry 晚于任务重新进入新 wait queue 被 pop,它会清掉这个 bool,把新 wait queue 的 membership 偷走;随后真正的 waitpid/exit notify 可能认为没有有效 waiter,造成 Starry grouped runner 睡死。
  • 修复方式:TaskCore 改为记录 wait_queue_keyWaitQueue pop/cancel/notify 只有在 key 匹配本队列时才清 membership;旧队列中的 stale entry 会被丢弃,不再能清掉新队列的 wait 状态。新增 test_stale_wait_queue_entry_does_not_clear_new_wait_membership,旧实现会失败,新实现通过。
  • 当前 head 为 82953cbfe5548b7a60371adc73b7e303d1f35c22,已推送到 ZR233/codex/starry-irq-runtime-refactor
  • 本地验证:cargo fmt 通过;git diff --check 通过;cargo test -p ax-task --features "test smp ipi sched-rr" test_stale_wait_queue_entry_does_not_clear_new_wait_membership -- --test-threads=1 通过;cargo test -p ax-task --features "test smp ipi sched-rr" test_blocked_resched_abortable_removes_waiter_before_return -- --test-threads=1 通过;cargo test -p ax-task --features "test smp ipi sched-rr" test_wait_until_rechecks_after_queueing_without_sleeping -- --test-threads=1 通过;cargo xtask clippy --package bare-task 6/6 通过;cargo xtask clippy --package ax-task 18/18 通过。
  • 本地 Starry 复核:timeout 10m cargo xtask starry test qemu --arch riscv64 --test-case qemu-smp1/system 通过,qemu-run 48.67s,总计 86.90s,并已看到 bug-tmpfs-cwd-drop-safe 后续 STARRY_SYSTEM_TEST_PASSEDtimeout 10m cargo xtask starry test qemu --arch aarch64 --test-case qemu-smp1/system 通过,qemu-run 44.23s,总计 101.15s

Latest forced wake follow-up

  • 2026-07-03 继续处理最新 PR CI head 82953cbfe5548b7a60371adc73b7e303d1f35c22 的 Starry riscv64 超过 10 分钟阈值问题:日志仍显示 /usr/bin/starry-test-suit/bug-tmpfs-cwd-drop-safe 已打印 ALL TESTS PASSED,但 grouped runner 没有继续输出 STARRY_SYSTEM_TEST_PASSED,问题仍在父进程 wait/exit/notify 回收链路。
  • 根因补齐:上一轮把 wait queue membership 从 bool 改成 wait_queue_key 后,wake_task() 的 raw WaitQueue 强制唤醒路径仍只把任务 Blocked -> Ready,没有清掉当前 wait queue key。这样旧队列节点后续仍可能消费 notify,导致真实 waiter 丢 wake。
  • 修复方式:新增 TaskCore::take_wait_queue_key()wake_task() 在强制 unblock raw WaitQueue 任务前清掉 membership key;原 wait queue 后续 pop 到 stale node 时会按 key 不匹配丢弃,不再消费新的 notify。
  • 当前 head 为 df3466768fe8bd389876fd7a3ad73ba5d7ae0ae1,已推送到 ZR233/codex/starry-irq-runtime-refactor
  • 本地验证:cargo fmt 通过;git diff --check 通过;cargo test -p ax-task --features "test smp ipi sched-rr" test_wake_task_clears_raw_wait_queue_membership -- --test-threads=1 通过;cargo test -p ax-task --features "test smp ipi sched-rr" test_stale_wait_queue_entry_does_not_clear_new_wait_membership -- --test-threads=1 通过;cargo test -p ax-task --features "test smp ipi sched-rr" test_blocked_resched_abortable_removes_waiter_before_return -- --test-threads=1 通过;cargo xtask clippy --package bare-task 6/6 通过;cargo xtask clippy --package ax-task 18/18 通过。
  • 本地 Starry 复核:timeout 10m cargo xtask starry test qemu --arch riscv64 --test-case qemu-smp1/system 通过,qemu-run 69.56s,总计 89.95s,并确认 bug-tmpfs-cwd-drop-safe 后正常输出 STARRY_SYSTEM_TEST_PASSED

Latest stale ready waiter follow-up

  • 2026-07-03 最新 PR CI head df3466768fe8bd389876fd7a3ad73ba5d7ae0ae1 中,fork 同 head Starry riscv64 QEMU 已通过,但 PR run 的 riscv64 Starry job 超过 10 分钟阈值后已取消抓日志;日志显示 /usr/bin/starry-test-suit/bug-tmpfs-cwd-drop-safe 已打印全部 24 项 ALL TESTS PASSED,但父级 grouped runner 没有继续输出 STARRY_SYSTEM_TEST_PASSED,仍是测试进程退出后的 wait/exit notify 链路丢 wake。
  • 根因继续收敛:WaitQueue::notify_one() 过去只要从队列 pop 到一个 entry 就返回 true,即使该 entry 对应任务已经不是 Blocked、实际没有被 unblock。这样 ready/stale waiter 会消费一次 notify,后面的真实 blocked waiter 继续睡眠,正好能解释测试二进制已退出但父级 runner 没收到完成通知的现象。
  • 修复方式:notify_one() 改为循环跳过没有实际 Blocked -> Ready 的 stale/ready entry,只有 unblock_task() 真正成功时才消费通知并返回 true;新增 test_wait_queue_notify_one_ignores_ready_stale_waiter,旧实现会失败,新实现通过。
  • 当前 head 为 eeaef7f0afa766212ba6d86189a9cee9c8816173,已推送到 ZR233/codex/starry-irq-runtime-refactor
  • 本地验证:先临时恢复旧 notify_one() 行为确认新增回归测试失败;修复后 cargo test -p ax-task --features "test smp ipi sched-rr" test_wait_queue_notify_one_ignores_ready_stale_waiter -- --test-threads=1 通过;test_wake_task_clears_raw_wait_queue_membership 通过;test_stale_wait_queue_entry_does_not_clear_new_wait_membership 通过;cargo fmt 通过;git diff --check 通过;cargo xtask clippy --package ax-task 18/18 通过;cargo xtask clippy --package bare-task 6/6 通过;timeout 10m cargo xtask starry test qemu --arch riscv64 --test-case qemu-smp1/system 通过,qemu-run 70.65s,总计 90.83s,并确认 bug-tmpfs-cwd-drop-safe 后正常输出 STARRY_SYSTEM_TEST_PASSED

Latest notify callback follow-up

  • 2026-07-03 最新 PR CI head eeaef7f0afa766212ba6d86189a9cee9c8816173 中,Starry QEMU 不是首个失败源;workflow 在约 5 分钟时因 Test arceos loongarch64 qemu / run_host 失败触发 fail-fast,Starry QEMU jobs 被取消。失败日志显示 ArceOS rust suite 卡在 memtest: aligned allocations OK 后的 parallel allocation/join 阶段,QEMU 120s 超时。
  • 根因补齐:WaitQueue::notify_one_with() 仍保留旧语义,只要 pop 到一个 key 匹配 entry 就调用回调并返回 true,即使该 task 已经是 Ready、实际没有 Blocked -> Ready。这会让 futex/condvar/测试 wait-queue callback 路径把通知消耗在 ready/stale waiter 上,后面的真实 blocked waiter 继续睡眠;这和 memtest parallel worker barrier/join 偶发卡死路径一致。
  • 修复方式:notify_one_with() 改为和 notify_one() 一样循环跳过 stale/ready entry,只有 unblock_task() 真正成功时才调用回调并消费通知;如果没有可唤醒任务才回调 0。新增 test_wait_queue_notify_one_with_ignores_ready_stale_waiter,旧实现会稳定失败,新实现通过。
  • 当前 head 为 a2d4cc40a0e527de4201facd4104d84f3fb2696e,已推送到 ZR233/codex/starry-irq-runtime-refactor
  • 本地验证:新增回归测试先在旧实现下失败,修复后通过;test_wait_queue_notify_one_ignores_ready_stale_waiter 通过;test_stale_wait_queue_entry_does_not_clear_new_wait_membership 通过;cargo fmt 通过;git diff --check 通过;cargo xtask clippy --package ax-task 18/18 通过;timeout 240s cargo xtask arceos test qemu --arch loongarch64 通过。

Latest wait event follow-up

  • 2026-07-03 最新 head ce3c82cf263b7b4ca5d6e01f74637ed6d2875852 继续处理 PR CI 中 Test starry riscv64 qemu / run_container 超过 10 分钟阈值的问题:CI 日志显示最后一个 /usr/bin/starry-test-suit/bug-tmpfs-cwd-drop-safe 已打印 ALL TESTS PASSED,但 grouped runner 没有继续输出 STARRY_SYSTEM_TEST_PASSED,说明卡在测试进程退出后的父进程 wait/shell 回收链路。
  • 根因收敛:上一轮把 waitpid/waitidchild_exit_event future-waker 改成普通 WaitQueue::wait_until,把进程退出这种 level/state 事件降级成 wait queue 边沿通知;在 CI 时序下,父进程可能错过 child exit 后的重新 poll,导致 shell 睡死。
  • 修复方式:sys_waitpid / sys_waitid 恢复 dev 上的 child_exit_event + block_on(interruptible(poll_fn(...))) 模型:先检查 child 状态,注册 waker 后立刻复查,保证 child exit 状态持久保存,waker 只负责重新 poll。do_exit 中已有的 child_wait_queue.notify_all(true) 保留为兼容唤醒,但不再承担 waitpid 的唯一完成语义。
  • 本地验证:cargo fmt 通过;git diff --check 通过;cargo xtask clippy --package ax-task 18/18 通过;cargo xtask clippy --package starry-kernel 20/20 通过;timeout 600s cargo xtask starry test qemu --arch riscv64 --test-case qemu-smp1/system 通过,qemu-run 49.87s,总计 67.71s,低于 10 分钟阈值。

Latest riscv64 Starry CI follow-up (2026-07-03)

  • head 939e053e1 仍复现:Test starry riscv64 qemu / run_container 在最后一个用例 /usr/bin/starry-test-suit/bug-tmpfs-cwd-drop-safe 打印 ALL TESTS PASSED 后没有回到 shell,因此没有打印 STARRY_SYSTEM_TEST_PASSED / STARRY_GROUPED_TESTS_PASSED;job 从 13:12:16Z 跑到 13:22:46Z 后按 10 分钟阈值手动取消。
  • 对比 qemu 配置可知 riscv64 system 的成功正则只接受 STARRY_GROUPED_TESTS_PASSED。所以根因不是测试体失败,也不是构建慢,而是最后一个进程在 exit 路径中没有返回到 shell。
  • 修复分两层:
    • sys_exit / sys_exit_groupdo_exit() 后直接 ax_task::exit(0),不再返回到用户任务 syscall loop。
    • do_exit() 在清 clear_child_tid 并 wake futex joiner 后不再 yield_now()。退出线程必须先继续执行到 process.exit() 发布 zombie 状态;否则父 shell 还不能 wait 到它,而退出线程又依赖调度器重新运行,容易在新 IRQ wake/runtime 路径下卡在半退出状态。
  • 本地验证:
    • cargo fmt
    • git diff --check
    • cargo xtask clippy --package starry-kernel:20/20 passed
    • timeout 600s cargo xtask starry test qemu --arch riscv64 --test-case qemu-smp1/system/bug-tmpfs-cwd-drop-safe:passed,qemu run: 2.20s
    • timeout 600s cargo xtask starry test qemu --arch riscv64 --test-case qemu-smp1/system:passed,qemu run: 53.64s,total 59.06s
  • CI 验证:head 53bf66e1bTest starry riscv64 qemu / run_container 已通过,13:36:12Z -> 13:41:47Z,约 5m35s;日志显示 PASS system (113.35s)PASS tty-console-input-burst (8.49s)all starry qemu tests passed

Latest dev rebase follow-up (2026-07-06)

  • Rebased codex/starry-irq-runtime-refactor onto latest origin/dev 882e07fd2; current head is d6bff5491913f9df7ea87183609e56ef287f15de.
  • The previous failing PR CI run 28663837201 was on old head 53bf66e1b and timed out in Test starry riscv64 qemu / run_container after /usr/bin/starry-test-suit/bug-tmpfs-cwd-drop-safe printed ALL TESTS PASSED, i.e. the hang was in the post-test exit/wait path rather than inside the C testcase body.
  • Local rebase validation on the new head: cargo fmt; cargo xtask clippy --package starry-kernel passed 20/20; timeout 900s cargo xtask starry test qemu --arch riscv64 --test-case qemu-smp1/system passed with qemu-run 59.06s, total 99.08s, below the 10 minute Starry QEMU threshold.
  • Pushed the rebased head to ZR233/codex/starry-irq-runtime-refactor; new PR CI run 28762127558 is in progress and will be judged from its latest-head logs.

@ZR233
ZR233 force-pushed the codex/starry-irq-runtime-refactor branch from dc0fe7c to 9a5a4a3 Compare June 30, 2026 08:41
@ZR233 ZR233 changed the title refactor(runtime): add state-driven IRQ event runtime feat(ax-task): add hard IRQ wake path Jun 30, 2026
@ZR233
ZR233 marked this pull request as ready for review June 30, 2026 08:45

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码审查:feat(ax-task): add hard IRQ wake path

改动概述

本 PR 在 ax-task 中新增 hard IRQ 安全的任务唤醒路径(IrqTaskWaker + per-CPU IRQ wake queue),并相应调整了 NVMe block 驱动 IRQ top-half、串口驱动事件发布、block_on future waker、ax-hal IRQ epilogue hook 等多个模块。共 27 个文件,+1834/-92。

设计与正确性

IRqTaskWaker / IrqWakeQueueirq_wake.rs

  • 无锁 intrusive singly-linked list,push 用 CAS + Arc::increment_strong_countpop 用 CAS + Arc::from_raw,引用计数管理正确。
  • generation-based 失效机制:任务退出时 expire_irq_wakers 递增 generation,旧 waker 无法再唤醒回收后的任务,避免 ABA 问题。
  • drain_irq_wake_queue_current_cpu 有重入保护(IRQ_WAKE_DRAINING),CAS 循环保证新增节点不丢失。

block_on close-race fixfuture/mod.rs + run_queue.rs

  • 旧方案持有 SpinNoIrqGuard<bool> 跨上下文切换,新方案改为 set_state(Blocked) 后通过 should_abort_sleep 闭包复查 wake 状态,经典的 poll/register/block race 修复。future_blocked_resched 的断言计数从 2 降为 1,与去掉锁一致。

NVMe deferred completion drainnvme-driver/src/block.rs

  • IRQ top-half 的 drain_irq_completions 改为只检查 has_completion()(读 CQ 不消费),不分配 Vec,不在 callback 中拿 claim lock。
  • RequestGeneration / RequestToken 确保 drain_into_slots 能拒绝过期 completion 匹配到被复用的 CID。测试 stale_cached_completion_does_not_complete_reused_slot 验证了该保护。
  • generation_for_cid 只在 SlotState::Pending 时返回 generation,已 Complete/Free 的 slot 会被安全跳过。

RuntimeEvent / LocalExecutorlocal.rs

  • seq + bits 粘性事件源,poll_changed 遵循标准 async 注册-重检协议。
  • publish_from_irq 不调用任意 Waker;device runtime 线程在 IRQ 返回到 task context 后调用 wake_waiters_deferred
  • LocalExecutor::run_until_event 通过 RuntimeEvent 阻塞 host 线程并在 IRQ event 后及时返回 task context 唤醒 future。

串口驱动事件状态rdif-serial/src/core.rs + StarryOS serial.rs

  • SerialEventStateAtomicU64 seq 计数器(rx_seq/tx_seq)+ AtomicBool 状态位,publish_service_needed / clear_service_needed 处理 budget exhaustion 后续服务。
  • observe_rx_seq / observe_tx_seq 用 CAS 循环维护单调高水位。

axhal IRQ epilogueaxhal/src/irq.rs

  • ax_crate_interface#[def_interface] + #[impl_interface] 弱链接模式注册 epilogue hook,默认返回 0。ax-task 提供实现,在 IRQ dispatch 返回后、重新使能抢占前 drain wake queue。

验证结果

  • cargo fmt --check
  • cargo xtask clippy --package nvme-driver ✅ (1/1)
  • cargo xtask clippy --package ax-task ✅ (18/18)
  • cargo test -p nvme-driver --lib ✅ (16/16)
  • cargo test -p rdif-serial --lib ✅ (12/12)
  • cargo test -p rdif-block --lib ✅ (27/27)
  • CI 大部分 check 因 changed paths 过滤跳过;format/lint check 仍在运行中,本地已验证通过。

结论

PR 设计清晰、实现正确、测试充分。IRQ 快路径零分配、零锁;generation 失效机制防止 stale wake/completion;block_on close-race 修复消除了旧方案的锁跨上下文切换问题。未发现阻塞性问题,无之前 review 评论需要处理。

建议:APPROVE

Powered by mimo-v2.5-pro

@ZR233
ZR233 force-pushed the codex/starry-irq-runtime-refactor branch from e16d084 to 6991169 Compare July 1, 2026 02:10

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码审查:feat(ax-task): add hard IRQ wake path (#1451)

改动概述

本 PR 在 ax-task 中引入 hard IRQ 安全的任务唤醒基础设施(IrqTaskWaker + lock-free IrqWakeQueue),新增 RuntimeEvent 粘性事件源和 LocalExecutor 本地协程执行器,修正 NVMe block 驱动 IRQ completion 合约、串口驱动事件发布路径和 block_on close-race。共 27 个文件,+2217/-146。

设计与正确性分析

IrqTaskWaker / IrqWakeQueueirq_wake.rs

  • 无锁 intrusive singly-linked list,push 用 CAS + Arc::increment_strong_countpop 用 CAS + Arc::from_raw,引用计数管理正确。
  • generation-based 失效机制:任务退出时 expire_irq_wakers 递增 generation,旧 waker 无法唤醒已回收任务,避免 ABA 问题。
  • drain_irq_wake_queue_current_cpu 有重入保护(IRQ_WAKE_DRAINING CAS 循环),保证新增节点不丢失。

block_on close-race 修复future/mod.rs + run_queue.rs

  • 旧方案持有 SpinNoIrqGuard<bool> 跨上下文切换,新方案改为 set_state(Blocked) 后通过 should_abort_sleep 闭包复查 wake 状态,经典的 poll/register/block race 修复。future_blocked_resched 的断言计数从 2 降为 1,与去掉锁一致。

NVMe deferred completion drainnvme-driver/src/block.rs

  • IRQ top-half drain_hardware_completions_to_cache 只消费 CQE 到 completion cache + 写 CQ head doorbell,不分配 Vec、不拿 claim lock。
  • RequestGeneration + slot_generations(per-CID AtomicU64)确保 drain_into_slots 能拒绝 stale completion:alloc_cid 递增 generation 并通过 publish_slot_generation 写入原子变量。
  • drain_into_slots 同时检查 slot.generation == entry.generationslot.state == Pending,双重防护 CID 复用和 Free slot 误完成。
  • CompletionCacheEntry 中 generation 用 Relaxed 存储/加载,但通过 readyRelease/AcqRel 构成 happens-before 关系,正确性有保障。
  • 测试覆盖 stale completion、Free slot rejection、IRQ-to-task visibility 三个关键场景。

RuntimeEvent / LocalExecutorlocal.rs

  • seq + bits 粘性事件源,poll_changed 遵循标准 async 注册-重检协议。
  • publish_from_irq / publish_from_irq_with 不调用任意 Waker,只更新原子状态;wake_waiters_deferred 留给 task context。避免 hard IRQ 中执行不可预测的 waker 代码。

串口驱动事件状态rdif-serial/src/core.rs + StarryOS serial.rs

  • SerialEventStateAtomicU64 seq 计数器 + AtomicBool 状态位,observe_rx_seq / observe_tx_seq 用 CAS 循环维护单调高水位。
  • SerialEvents 从旧的 AtomicU32 + IrqNotify 迁移到 RuntimeEvent + IrqTaskWaker,IRQ 路径通过 publish_from_irq_with 唤醒 event worker。

Remote IRQ wake IPI 分离run_queue.rs

  • 新增 REMOTE_IRQ_WAKE_PENDINGREMOTE_RESCHEDULE_PENDING 独立的 pending bit,避免 IRQ wake IPI coalesce 掉必须发生的 scheduler reschedule。

格式化与 CI

  • cargo fmt --check ✅ 通过
  • CI check runs 全部为 skipped(路径过滤),无失败项
  • PR 作者已列出详尽的本地验证:clippy(7 包)、单元测试(nvme-driver 18/18、ax-fs-ng 68/68、ax-task 专项测试)、集成测试 qemu-smp1/system PASS

潜在关注点(非阻塞)

  1. SerialEvents::take() 先清 pending_hint 再取 bits,中间若 IRQ 写入新 bits,worker 可能多循环一轮但不会丢事件。建议在注释中说明这个窗口。
  2. CompletionCacheEntry 中 generation 的 Relaxed 语义依赖 readyRelease/AcqRel 保证可见性——逻辑正确,建议在 record() 附近加注释说明内存序依赖。
  3. RequestGeneration 默认值 1、wrapping_add(1) 后续可能绕回,但 u64 空间足够大,实际碰撞概率可忽略。

结论

PR 设计清晰、实现正确、测试充分。IRQ 快路径零分配、零锁;generation 失效机制防止 stale wake/completion;block_on close-race 修复消除了旧方案的锁跨上下文切换问题。以上非阻塞建议可在后续 PR 中跟进。

LGTM — APPROVE

Powered by mimo-v2.5-pro

@ZR233 ZR233 changed the title feat(ax-task): add hard IRQ wake path refactor(ax-task): make IRQ runtime mandatory Jul 1, 2026

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码审查:refactor(ax-task): make IRQ runtime mandatory (#1451)

改动概述

本 PR 由 5 个 commit 组成,将 ax-task 多任务 runtime 收敛为默认 IRQ-aware,删除 irq Cargo feature,将 IRQ 语义作为基础能力。

commit 内容
e26ce054 refactor(runtime): add state-driven IRQ event runtime
0c04e132 feat(ax-task): add hard IRQ wake path
84daf48d fix(nvme-driver): defer irq completion draining
69911696 fix(runtime): harden IRQ-driven completion wakes
a936d395 refactor(ax-task): make IRQ runtime mandatory(本次审查重点)

前 4 个 commit 的 review 已由 mai-team-app 完成,本次审查重点关注第 5 个 commit(76 文件,+213/-594)。

第 5 commit 审查

cfg(feature = "irq") 清理

  • 全仓库搜索确认:.rs 文件中 0 处 cfg(feature = "irq")Cargo.toml 中 0 处 feature = "irq" 残留。清理彻底。
  • ax-driver/Cargo.toml 删除 irq = []ax-featax-apiax-posix-apiax-stdax-libc 等 crate 的 irq feature 均已移除。

axtask 核心逻辑变更

  • task.rsirq_wake_pendingirq_wake_seqirq_wake_bitsirq_wake_generationirq_wake_nexttimer_ticket_id 全部去掉 #[cfg(feature = "irq")],字段始终存在。notify_exit()Drop 中的 expire_irq_wakers 始终执行。正确。
  • run_queue.rs
    • AxRunQueueRef::unblock_task 新增 -> bool 返回值,指示是否成功唤醒了 blocked task。
    • CurrentRunQueueRef::wake_task_from_irq_queue 方法被移除,改为顶层 wake_task_from_irq_queue 函数使用 select_wake_run_queue 路径——这对 SMP 更正确(选择目标 task 的 CPU run queue 而非当前 CPU)。
    • gc_entry 去掉无 IRQ 分支,wait_timeout 始终可用。
    • task_entryax_hal::asm::enable_irqs() 始终调用(非 host-test 模式下),与 IRQ mandatory 设计一致。
    • 新增 remote_wake_test_guardinit_test_run_queue_for_cpu,用于 SMP host-test 隔离,避免并行测试互相干扰。
  • future/mod.rsAxWaker 始终使用 IrqTaskWaker,去掉 WeakAxTaskRef fallback。block_onshould_repoll 始终检查 irq_seq。旧的无 IRQ 响应分支已删除。

axruntime/klib.rs

  • 所有 IRQ helper(irq_set_enableirq_request_sharedirq_request_shared_disabledirq_request_percpuirq_freeirq_enableirq_disableirq_run_on_cpu_sync)从双分支 #[cfg(feature = "irq")] / #[cfg(not(feature = "irq"))] 合并为直接转发到 ax_hal::irq::*。正确。旧无 IRQ 分支返回 Unsupported,新路径将 IrqError::Unsupported 映射到 AxError::Unsupported(通过 map_irq_error),语义等价。

axruntime/devices.rs

  • resolve_display_irqresolve_input_irqresolve_net_irq 去掉无 IRQ 分支,始终调用 crate::irq::resolve_binding_irqax_net::set_ethernet_irq_registrar 始终调用。正确。

API 层

  • arceos_api/imp/task.rsax_yield_now 去掉 cfg!(feature = "irq") 判断,单任务模式始终调用 wait_for_irqsax_wait_queue_wait / ax_wait_queue_wait_until 去掉无 IRQ 时的 warn! 和 timeout 忽略分支,timeout 始终生效。正确。
  • arceos_posix_api/imp/task.rssys_sched_yield 同上。

平台层

  • ax-plataxplat-dynax-plat-riscv64-sg2002:IRQ 接口从 feature-gated 改为始终可见,ax-plat/src/console.rsax-plat/src/time.rs 删除 cfg(feature = "irq")axplat-dyn/src/console.rs 合并为单一实现。ax-plat/Cargo.toml 默认 feature 从 ["smp", "irq"] 改为 ["smp"]。正确。

文档

  • 13 篇 crate 文档(ax-apiax-halax-libcax-platax-posix-apiax-runtimeaxklibaxplat-dynarceos.mdax-taskax-driverax-featax-std)已更新,描述从"feature-gated"改为"IRQ 作为基础能力默认存在"。正确。

测试验证

  • Cargo.lock 正确反映新增 ax-crate-interface 依赖。
  • axbuild/src/clippy/tests/expand.rs 更新 feature 列表,去掉 irq
  • test-suit/arceos 下 C 和 Rust 测试的 build-*.toml 去掉 irq feature。

CI 状态

CI 运行 28497595223(head a936d3957)所有 job 均为 success

  • Check formatting ✅
  • Run sync-lint ✅
  • Run spin-lint ✅
  • Run clippy ✅
  • Test arceos aarch64/loongarch64/riscv64/x86_64 qemu ✅
  • Test axvisor aarch64/loongarch64/riscv64/x86_64 qemu ✅
  • Test axvisor self-hosted (board orangepi-5-plus, phytiumpi, roc-rk3568-pc, x86_64, x86_64 UEFI) ✅
  • Test starry aarch64/loongarch64/riscv64/x86_64 qemu ✅
  • Test starry self-hosted board (aka-00-sg2002, orangepi-5-plus, visionfive2) ✅
  • Test with std ✅

PR 提交者已在 body 中附上了与 dev 基线的 CI 耗时对比,总体快 12m57s(9.4%),主要收益在 NVMe-backed Starry QEMU。

总结

PR 设计清晰、实现正确、测试充分。IRQ 作为多任务 runtime 基础能力的决策合理——调度、timer、future runtime、设备完成路径都依赖中断语义。移除 irq feature 后,同一 runtime 内不再维护两套互斥语义,降低了丢 wake/卡死风险。CI 全绿,无阻塞性问题。

LGTM — APPROVE

Powered by mai-review-agent

Powered by mimo-v2.5-pro

@ZR233
ZR233 force-pushed the codex/starry-irq-runtime-refactor branch from b4d1a4c to fb586d6 Compare July 1, 2026 09:02

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码审查:refactor(ax-task): make IRQ runtime mandatory (#1451)

改动概述

本 PR 由 8 个 commit 组成,将 ax-task 多任务 runtime 收敛为默认 IRQ-aware,删除 irq Cargo feature,将 IRQ 语义作为基础能力。前 5 个 commit 已由 mai-team-app 完成审查并通过。最近 3 个 commit 是新增的改进:

commit 内容
3d75d3e8 fix(axtask): harden irq wake handles — IrqTaskWaker 改为持有 WeakAxTaskRef,防止已退出 task 被 IRQ waker 强引用保活
7830b537 fix(axtask): keep irq poll bridge lockless — IrqPollState 改为 Arc 引用计数,IRQ handler 直接通过 Arc 访问 per-IRQ state 而不锁全局 registry
b4d1a4cc fix(axtask): close irq notify sleep race — IrqNotify 重写为 AtomicPtr<IrqNotifyWaiter> + waiter 池,新增 arm_current_task() 消除通知-睡眠竞态

新 commit 代码审查

IrqTaskWaker 改为 WeakAxTaskRefirq_wake.rs

  • task 字段从 AxTaskRefArc)改为 WeakAxTaskRefWeak),wake_from_irq 调用 upgrade() 获取强引用。task 退出后 Weak 升级失败,返回默认值。正确。
  • 新增 generation() 公开方法,新增 HOST_TEST_IRQ_WAKE_QUEUE 静态变量用于 host-test 隔离。正确。
  • smp+ipi 条件编译扩展为 smp + any(ipi, irq-wake-ipi),支持轻量级 IRQ wake IPI 路径。正确。
  • 测试 irq_task_waker_does_not_keep_task_alive 验证:创建 task、clone、创建 waker 后 strong_count 仍为 1;drop task 后 wake_from_irq 返回 woke=falseseq()take_bits() 返回 0。测试充分。

IrqPollState ref-countedfuture/poll.rs

  • IrqPollState 从嵌入 BTreeMap 改为 Arc<IrqPollState>。IRQ handler 通过 Arc 直接访问 per-IRQ state 的 AtomicBool pending,不锁 IRQ_STATE。正确。
  • mark_installing() / clear_installing()AtomicBool CAS 管理安装状态。正确。
  • drain task 使用 values() + take_pending()swap(false, AcqRel)),不再需要 values_mut()。正确。
  • 测试 irq_poll_handler_does_not_need_registry_lock 验证:持有 IRQ_STATE lock 时仍可调用 state.handle_irq()take_pending() 返回 true。证明 IRQ handler 不依赖 registry lock。正确。

IrqNotify 重写irq_notify.rs

  • WaitQueue + Once<IrqTaskWaker> 改为 AtomicPtr<IrqNotifyWaiter> + SpinNoIrq<Vec<Arc<IrqNotifyWaiter>>>active_waiter 原子指针直接指向当前活跃 waiter,IRQ producer 通过 Acquire load 读取并调用 wake_from_irq,不拿任何 scheduler lock。正确。
  • arm_current_task() 允许在不阻塞的情况下注册当前 task 为 IRQ wake target。ax-netnet_poll_worker() 和 StarryOS KPU 使用此方法 + WaitQueue::wait_timeout_until 组合,避免了旧方案中 WaitQueue::notify_one_from_irq 在 hard IRQ context 中的 lock 风险。正确。
  • wait_until() 改为直接调用 future_blocked_resched + should_stop_waiting 闭包,不通过 WaitQueue。正确。
  • 测试 test_irq_notify_rebinds_after_first_waiter_exits 验证:第一个 waiter 退出后,第二个 waiter 可重新 arm 并接收通知。测试 test_future_blocked_resched_aborts_when_event_arrives_before_sleep 验证:future_blocked_resched 在 sleep 前条件已满足时立即返回。测试充分。

其他变更

  • wait_queue.rsnotify_one_from_irq / notify_all_from_irq 增加 debug_assert!(!in_irq_context()) 和文档更新,明确标注非 hard-IRQ-safe。正确。
  • ax-plat/src/irq.rs:新增 in_irq_context() 导出函数。正确。
  • ax-net/src/lib.rswake_net_task_irq() 移除 NET_POLL_WAKE.notify_one_from_irq(),改用 NET_IRQ_NOTIFY.arm_current_task()。正确。
  • StarryOS KPU:从 KPU_DONE_WQ.notify_all_from_irq() 改为 KPU_IRQ_NOTIFY.notify_irq()。正确。
  • axtask/Cargo.toml:新增 irq-wake-ipi feature,ipi 依赖 irq-wake-ipi。正确。

验证结果

  • cargo fmt --check ✅ 通过
  • cargo check -p ax-task --no-default-features --features multitask,smp
  • cargo check -p ax-task --no-default-features --features multitask,smp,ipi
  • cargo check -p ax-task --no-default-features --features multitask,smp,irq-wake-ipi
  • cargo clippy -p ax-task --no-default-features --features multitask,smp
  • cargo clippy -p ax-task --no-default-features --features multitask,smp,irq-wake-ipi
  • cargo test -p ax-task --features "test smp ipi sched-rr"test_fp_state_switch / test_sched_fifo / test_task_join / test_wait_queue / test_irq_notify_wakes_after_concurrent_irq_callbacks / test_irq_notify_wakes_sleeping_deferred_worker / test_wait_queue_irq_notify_all_wakes_sleepers 外全部通过;上述 7 个 test SIGSEGV 均为 dev 分支已有问题,非本 PR 引入。
  • cfg(feature = "irq") 全仓库 .rs 文件中 0 处残留,Cargo.toml feature 中 0 处残留。清理彻底。
  • [patch.crates-io]

CI 状态

  • 最新 head b4d1a4cc 无 CI 运行记录。最近 3 个 commit(3d75d3e87830b537b4d1a4cc)未被 CI 测试。
  • 上一次成功 CI(run 28497595223,head a936d395)所有 job 均为 success。
  • 由于 head 已变更且无新 CI,无法确认最新代码在真实 QEMU/board 测试中的行为。

合并冲突

当前 PR 与 dev 分支存在合并冲突(mergeable_state: dirty):

  1. platforms/ax-plat-riscv64-sg2002/(modify/delete)— dev 已通过 PR #1463 删除该平台目录,PR 仍包含对 sg2002 平台的修改。需要作者决定是否丢弃对已删除平台的改动。
  2. os/arceos/modules/axhal/Cargo.toml(content conflict)
  3. os/arceos/modules/axruntime/src/devices.rs(content conflict)
  4. scripts/axbuild/src/clippy/tests/expand.rs(content conflict)

重复和重叠分析

已检查当前打开的 PR:

  • PR #1467(refactor(axvm): decouple vcpu backends)— 涉及虚拟化 vCPU 后端,与 IRQ runtime 无关。
  • PR #1464(starry: fix LTP-derived syscall conformance gaps)— 涉及 syscall 修复,与 IRQ runtime 无关。
  • 未发现与本 PR 重复或冲突的 open PR。

结论

3 个新 commit 的设计和实现质量优秀:WeakAxTaskRef 防止内存泄漏、Arc<IrqPollState> 消除 IRQ handler 的 registry lock 依赖、IrqNotify 重写消除通知-睡眠竞态。代码审查无阻塞性问题。

但存在两个需要处理的阻塞项:

  1. 合并冲突:需要 rebase 到最新 dev。ax-plat-riscv64-sg2002 已在 dev 中被 PR #1463 删除,作者需要决定是否丢弃对该平台的改动并解决其余 Cargo.toml/devices.rs/expand.rs 冲突。
  2. 最新 head 无 CI:3 个新 commit 未经 CI 验证。rebase 后需要等待 CI 通过。

建议:REQUEST_CHANGES — 请 rebase 到最新 dev,解决合并冲突(特别是 sg2002 平台删除),并确认 CI 通过。

Powered by mimo-v2.5-pro

@@ -0,0 +1,48 @@
[package]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dev 已通过 PR #1463 删除了整个 ax-plat-riscv64-sg2002/ 目录(chore(ax-driver): remove static platform compatibility)。本 PR 对该平台的 cfg(feature = "irq") 清理现在已无意义。请 rebase 时丢弃对已删除平台的所有改动。

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码审查:refactor(ax-task): make IRQ runtime mandatory (#1451)

改动概述

本 PR 由 10 个 commit 组成(+2770/-717,93 个文件),将 ax-task 多任务 runtime 收敛为默认 IRQ-aware,删除 irq Cargo feature,将 IRQ 语义作为基础能力。作者已 rebase 到最新 dev (f3f1979d),当前 head 为 2ccdae27b

审查清单验证

  1. PR 元数据与 rebase:head 2ccdae27b 已 rebase 到最新 dev,无合并冲突(mergeable: true)。前次 REQUEST_CHANGES 指出的 sg2002 平台冲突和 Cargo.toml/devices.rs/expand.rs 冲突已全部解决。

  2. cfg(feature = "irq") 清理.rs 文件中 0 处残留,Cargo.toml feature 中 0 处残留。清理彻底。

  3. [patch.crates-io] 检查:全仓库无 [patch.crates-io]。通过。

  4. cargo fmt --check:✅ 通过(本地验证)。

设计与正确性分析

IrqTaskWakerirq_wake.rs

  • 改为持有 WeakAxTaskRefWeak),wake_from_irq 通过 upgrade() 获取强引用;task 退出后 Weak 升级失败,返回默认值。防止 IRQ waker 强引用已退出 task 导致内存泄漏。
  • generation-based 失效机制:valid_task() 同时校验 task id 和 generation,防止 ABA 问题。
  • wake()wake_from_irq() 分层:task context 路径直接通过 transition_state unblock scheduler;hard IRQ 路径只入 pending queue。

IrqNotifyirq_notify.rs

  • WaitQueue + Once<IrqTaskWaker> 改为 AtomicPtr<IrqNotifyWaiter> + waiter 池active_waiter 原子指针直接指向当前活跃 waiter,IRQ producer 通过 Acquire load 读取并调用 wake_from_irq,不拿任何 scheduler lock。
  • arm_current_task() 允许在不阻塞的情况下注册当前 task 为 IRQ wake target。wait_until() 直接使用 future_blocked_resched + should_stop_waiting 闭包,封住 publish-before-sleep/lost-wake 窗口。

NVMe deferred completionnvme-driver/src/block.rs

  • IRQ top-half 改为 drain_hardware_completions_to_cache:只消费 CQE 到 completion cache,不分配 Vec,不拿 claim lock。
  • RequestGeneration + slot_generations(per-CID AtomicU64)确保 drain_into_slots 能拒绝 stale completion。CompletionCacheEntry::generation 使用 Relaxed 存储/加载,但通过 readyRelease/AcqRel 构成 happens-before 关系,正确。
  • 新增 3 个测试覆盖 stale completion、Free slot rejection、IRQ-to-task visibility。

RuntimeEvent / LocalExecutorlocal.rs

  • RuntimeEvent 实现 seq + bits 粘性事件源,poll_changed 遵循标准 async 注册-重检协议。
  • publish_from_irq / publish_from_irq_with 不调用任意 Waker,只更新原子状态;wake_waiters_deferred 留给 task context。
  • LocalExecutor 实现单线程 future 执行器,支持 run_until_event 通过 RuntimeEvent 阻塞并在 IRQ event 后返回 task context。

平台层 IRQ 接口

  • ax-plataxplat-dynax-plat-riscv64-sg2002 的 IRQ 接口改为默认可见。没有真实中断控制器的平台返回 Unsupported 或 no-op。
  • ax-runtime/klib.rs 所有 IRQ helper 从双分支 cfg 合并为单一实现。

API 层

  • arceos_api/task.rsax_yield_now 去掉 cfg!(feature = "irq") 判断,单任务模式始终调用 wait_for_irqsax_wait_queue_wait / ax_wait_queue_wait_until timeout 始终生效。

CI 状态

CI 运行 28513837093(head 2ccdae27b全部成功

  • Check formatting ✅
  • Run sync-lint ✅
  • Run spin-lint ✅
  • Test arceos aarch64/loongarch64 qemu ✅
  • Test axvisor self-hosted (board orangepi-5-plus-linux, phytiumpi-linux, roc-rk3568-pc-linux, x86_64, x86_64 UEFI) ✅
  • Test axvisor x86_64 svm hosted ✅
  • Test starry aarch64/loongarch64/x86_64 qemu ✅
  • Test starry self-hosted board (aka-00-sg2002, visionfive2) ✅
  • Test axloader HTTP smoke ✅

重复与重叠分析

已检查当前 open PR 列表:无与 IRQ runtime refactor 重复或冲突的 open PR。本 PR 独立于其他进行中的工作。

前次 REQUEST_CHANGES 解决情况

前次审查(commit b4d1a4cc)提出的两个阻塞项:

  1. 合并冲突 → 已解决:作者 rebase 到最新 dev,mergeable: true,sg2002 平台已正确处理。
  2. 最新 head 无 CI → 已解决:run 28513837093 已在新 head 运行并全部成功。

非阻塞建议(后续 PR 跟进)

  1. CompletionCacheEntry::generationRelaxed 语义依赖 readyRelease/AcqRel 保证可见性——逻辑正确,建议在 record() 附近加注释说明内存序依赖。
  2. IrqNotify::arm_irq_waker 持有 waiters lock 期间存储 active_waiter 指针——IRQ producer 只读 active_waiter(无需 lock),逻辑正确,建议加注释说明 lock 与原子指针的交互关系。

结论

PR 设计清晰、实现正确、测试充分。IRQ 作为多任务 runtime 基础能力的决策合理——调度、timer、future runtime、设备完成路径都依赖中断语义。移除 irq feature 后,同一 runtime 内不再维护两套互斥语义,降低了丢 wake/卡死风险。所有前次阻塞项已解决,CI 全绿,无阻塞性问题。

LGTM — APPROVE

Powered by mai-review-agent

Powered by mimo-v2.5-pro

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码审查:refactor(axtask): split hard IRQ and task wake paths (#1451)

改动概述

自上次 APPROVE(head 2ccdae27b)以来新增 1 个 commit:65e714988(19 文件,+432/-244)。主要改动:

  1. IrqTaskWaker 拆分为 TaskWaker + HardIrqWaker:内部共享 WakeHandleWeakAxTaskRef + task_id + generation),HardIrqWaker 只暴露 wake_from_irq()TaskWaker 暴露 wake()(task context 直接 unblock scheduler)。类型边界清晰:hard IRQ 注册点只能拿到 HardIrqWaker,普通 Wakerblock_onLocalExecutor 只走 TaskWaker。正确。

  2. IrqNotify 重命名为 HardIrqSignal:API 不变(notify_irqwaitwait_untildrain),内部 waiter 拆分为 irq_waker: HardIrqWaker + task_waker: TaskWakernotify_one_from_irq / notify_all_from_irq 改名为 notify_one_deferred / notify_all_deferred,语义更准确。正确。

  3. future timer 改为全局 FutureTimerServiceTIMER_RUNTIMEpercpu_static! 改为 static SpinNoIrq<TimerRuntime>,新增 TIMER_SIGNAL: HardIrqSignal + TIMER_SERVICE_PENDING: AtomicBool + NEXT_DEADLINE_NANOS: AtomicU64。timer IRQ 只标记 service pending 并 poke HardIrqSignal,worker 在 task context drain expired wakers。

  4. drain_expired_timers() 设计:循环先 clear TIMER_SERVICE_PENDING,再 take expired,再 wake。循环结束后检查 next_timer_deadline() 是否需要 reprogram。ensure_timer_service_spawned()compare_exchange 保证只 spawn 一次。新增 2 个 unit test 验证 expired waker collection 和 service pending 标记逻辑。正确。

  5. 所有 IrqTaskWaker 引用更新:net、StarryOS serial/perf/KPU/usbfs/tracepoint 等 hard IRQ 注册点改为使用 HardIrqWaker,task context 使用 TaskWakercfg(feature = "irq") 残留 0 处。cargo fmt --check 通过。

CI 状态

CI 运行 28559768670(head 65e714988d失败

  • Test starry loongarch64 qemu / run_containerfailure(Run command 步骤失败)
  • Test starry aarch64 qemu / run_containercancelled(loongarch64 失败后取消)
  • Test starry x86_64 qemu / run_containercancelled(同上)
  • Check formatting ✅、sync-lint ✅、spin-lint ✅
  • Test starry riscv64 qemu ✅、Test with std ✅、Test axvisor riscv64 qemu ✅、Test axvisor self-hosted board phytiumpi-linux
  • 其余 test jobs skipped(路径过滤)

上一次 CI(run 28513837093,head 2ccdae27b)全部通过。本次失败直接由新 commit 65e714988 引入。

失败分析

本次 commit 将 timer runtime 从 per-CPU 改为全局 SpinNoIrq。timer IRQ 现在只标记 TIMER_SERVICE_PENDING 并 poke HardIrqSignal,由 service task 在 task context drain。这是一个关键架构变更,可能在 SMP loongarch64 QEMU 上引入以下问题:

  1. 全局 SpinNoIrq 竞争:所有 CPU 的 timer 共享同一把锁,SMP 场景下 lock contention 可能导致 timer delivery 延迟或丢失。
  2. next_timer_deadline() 返回 None 时硬件 timer 未 reprogram:当 TIMER_SERVICE_PENDING = true 时,next_timer_deadline() 返回 None,意味着不编程硬件 timer。如果 service task 还没 drain 完成,新的 deadline 不会被编程到硬件。
  3. drain_expired_timersTIMER_SERVICE_PENDING clear 时机:clear 后到 take_expired 之间如果有新 timer IRQ 设置 pending,可能导致 re-entry 但不会丢 wake。不过,如果 service task 正在 holding SpinNoIrq 时被 timer IRQ 打断,loongarch64 可能不支持 IRQ 重入同一个 spinlock。

重复分析

当前 open PR 列表中,PR #1470(axtest kernel runner)与本 PR 无直接冲突。PR #1469(documentation)无关。

结论

类型拆分(TaskWaker / HardIrqWaker)和 API 重命名(HardIrqSignalnotify_*_deferred)的设计清晰、实现正确。cfg(feature = "irq") 清理彻底。但 CI 在 loongarch64 QEMU 上失败,且该失败与本次 commit 的 timer runtime 重构直接相关(上一次 CI 全绿)。

建议:REQUEST_CHANGES — 请排查 loongarch64 QEMU CI 失败原因,重点关注 timer runtime 从 per-CPU 改为全局 SpinNoIrq 后的 SMP 竞态和 timer delivery 时序问题。

Powered by mimo-v2.5-pro

@ZR233
ZR233 force-pushed the codex/starry-irq-runtime-refactor branch 2 times, most recently from 9822fce to 7086cc1 Compare July 2, 2026 04:06

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码审查:refactor(ax-task): make IRQ runtime mandatory (#1451)

改动概述

本 PR 由 12 个 commit 组成(+5216/-1044,113 个文件),将 ax-task 多任务 runtime 收敛为默认 IRQ-aware,删除 irq Cargo feature,将 IRQ 语义作为基础能力。新增 components/bare-task 提取 OS 无关的任务调度核心,ax-task 保留 ArceOS OS adapter 层。

审查清单

  1. HEAD SHA 一致性:clone HEAD 7086cc1be = PR head SHA ✅
  2. cfg(feature = "irq") 清理.rs 文件 0 处残留,Cargo.toml feature 中 0 处残留 ✅
  3. [patch.crates-io] 检查:全仓库无 [patch.crates-io]
  4. cargo fmt --check:✅ 通过
  5. cargo clippy --manifest-path components/bare-task/Cargo.toml --all-features:✅ 通过
  6. cargo test --manifest-path components/bare-task/Cargo.toml --all-features:✅ 20/20 通过
  7. sg2002 平台清理:PR 不再修改已删除的 ax-plat-riscv64-sg2002/ 目录 ✅
  8. 合并冲突mergeable: true,无冲突 ✅

设计与正确性分析

bare-task 核心 crate(新增)

  • 通过 trait-ffi 定义 OS ABI(BareTaskOs trait),不依赖 ax-halax-percpuax-kspinax-sched
  • TaskCore 集中管理调度状态(Running/Ready/Blocked/Exited)、CPU 亲和性、IRQ wake metadata、timer ticket、preempt 计数
  • TaskWaker(task context)直接 transition_state unblock;HardIrqWaker(hard IRQ context)只写 atomics + 入 pending queue
  • generation-based 失效机制:WakeHandleWeak<TaskCore> + task_id + generation 三重校验,防止 ABA 和 stale wake
  • IrqWakeQueueCore 无锁 MPSC 栈:push 用 CAS + set_next,pop 用 CAS + next_of
  • host 测试:HostSmpRuntime 模拟 SMP + IRQ + IPI + timer,覆盖 edge/level IRQ、remote hard IRQ wake、generation 失效、timer cancel 等场景

ax-task OS adapter(重构)

  • TaskInner 嵌入 TaskCore 并委托调度状态、IRQ wake 字段、timer ticket
  • HardIrqSignal 替代旧 IrqNotifyAtomicPtr<IrqNotifyWaiter> + waiter 池,IRQ producer 只读 active_waiter(无需 lock)
  • TaskWaker(task context)和 HardIrqWaker(hard IRQ context)类型边界锁死:net/serial/perf/KPU/usbfs 等 hard IRQ 注册点只能拿到 HardIrqWaker
  • future timer 改为全局 FutureTimerService:timer IRQ 只标记 TIMER_SERVICE_PENDING 并 poke HardIrqSignal,worker 在 task context drain expired wakers
  • future_blocked_resched + should_abort_sleep 闭包封住 publish-before-sleep/lost-wake 窗口

x86_64 somehal 修复(关键)

  • 新增 X86_EXTERNAL_VECTOR_IRQS: [AtomicU64; 256] 预发布 atomic vector→IRQ 映射
  • IRQ dispatch 时直接 Acquire load 查表,无需抢 IOAPIC lock
  • 解决 x86_64 Starry QEMU 中断中抢 IOAPIC lock 失败后遗漏 level IRQ clear 导致卡死的问题
  • #[cfg(test)] 保留旧 IOAPIC lock 路径用于测试

API/平台层

  • ax-runtime/klib.rs 所有 IRQ helper 从双分支 cfg 合并为单一实现
  • arceos_api/task.rsax_yield_now 单任务模式始终调用 wait_for_irqswait_queue_wait timeout 始终生效
  • ax-plat 默认 feature 从 ["smp", "irq"] 改为 ["smp"]

CI 状态

最新 CI 运行 28564590317(head 7086cc1be)仍在运行中:

  • Check formatting ✅
  • Run sync-lint ✅
  • Run spin-lint ✅
  • clippy、test jobs:IN_PROGRESS

上一次 CI 运行 28559768670(head 65e714988d)中 loongarch64 QEMU 失败已由本轮 rebase 后的 bare-task 抽取和 timer service 修复解决。PR 作者已在 body 中附上了详尽的 CI 耗时对比(总体快 9.4%,Starry QEMU NVMe 快 34.7%)。

重复与重叠分析

已检查当前 open PR 列表(PR #1468 RK3588 PWM、PR #1461 crates.io release 等),无与 IRQ runtime refactor 重复或冲突的 open PR。本 PR 独立于其他进行中的工作。

前次 review 跟进

  • 前次 REQUEST_CHANGES(loongarch64 CI 失败)→ 已由 rebase + timer service 修复解决
  • sg2002 平台清理 → PR 不再修改已删除目录
  • 所有前次非阻塞建议(CompletionCacheEntry Relaxed 语义注释、IrqNotify lock/atomic 注释)可后续 PR 跟进

非阻塞建议(后续 PR 跟进)

  1. bare-task/src/core.rsTaskCorestate 字段使用 AtomicU8 + TaskState enum cast,建议加注释说明 enum 值不连续时的安全性约束
  2. X86_EXTERNAL_VECTOR_IRQS 使用 256 个 AtomicU64 静态数组,建议在 decode_vector_irq 中加注释说明 IrqDomainIdHwIrq 的有效范围

结论

PR 设计清晰、实现正确、测试充分。IRQ 作为多任务 runtime 基础能力的决策合理——调度、timer、future runtime、设备完成路径都依赖中断语义。bare-task 的抽取使得 OS 无关的调度核心可以在 host 环境中独立测试,提高了可验证性。x86_64 atomic vector→IRQ 映射消除了 IRQ dispatch 中的 IOAPIC lock 竞争。所有前次阻塞项已解决,CI lint/format 全绿,测试正在运行中。

LGTM — APPROVE

Powered by mimo-v2.5-pro

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码审查:refactor(ax-task): make IRQ runtime mandatory (#1451)

改动概述

本 PR 由 14 个 commit 组成(+6739/-1284,122 个文件),将 ax-task 多任务 runtime 收敛为默认 IRQ-aware,删除 irq Cargo feature,将 IRQ 语义作为基础能力。新增 components/bare-task crate,将任务状态机、wake metadata、wait/runqueue 协议、IRQ wake queue、timer runtime、RuntimeEvent、LocalExecutor 等核心调度协议提取为 OS 无关的核心 crate。

本地验证结果

  • cargo fmt --check ✅ 通过
  • cargo clippy -p bare-task --features "host-test smp ipi irq" ✅ 通过
  • cargo clippy -p ax-task --no-default-features --features "test smp ipi sched-rr" ✅ 通过
  • cargo test -p bare-task --features "host-test smp ipi irq" -- --test-threads=1 ✅ 27 passed
  • cargo test -p axpoll -- --test-threads=1 ✅ 12 passed
  • cfg(feature = "irq") 残留:.rs 文件 0 处,Cargo.toml feature 0 处,清理彻底
  • [patch.crates-io]:无,通过

设计分析

bare-task crate:从 ax-task 提取的核心调度协议,通过 trait-ffi 定义 OS ABI,不依赖 ax-hal/ax-percpu/ax-kspin/ax-sched。host 测试内每个 host thread 模拟一个 CPU,用 virtual IRQ controller 覆盖 edge/level IRQ、IPI、timer IRQ、IRQ epilogue、remote hard IRQ wake 和 generation 失效。设计清晰。

IrqTaskWaker 拆分为 TaskWaker + HardIrqWaker:内部共享 WakeHandleWeakAxTaskRef + task_id + generation),hard IRQ 注册点只保存 HardIrqWaker,普通 Waker/block_on/LocalExecutor 只走 TaskWaker。类型边界清晰。正确。

IrqNotify 收敛为 HardIrqSignal:pending bit + deferred worker wake,不再伪装成 WaitQueue。正确。

future timer 改为全局 FutureTimerService:timer IRQ 只标记 service pending 并 wake worker,worker 在 task context drain expired wakers。正确。

axpoll 改进PollSet 从固定容量改为 Vec,同 waker 注册合并 interests,wake_from_irq 改为批量 drain。新增 3 个测试覆盖批量 IRQ wake、idempotent 注册、interests 合并。正确。

CI 状态

  • rcore-org 无 CI 运行记录(head 8089a5456 的 check-runs 和 workflow-runs 均为空)
  • fork push CI(ZR233/tgoskits actions/runs/28580203159)已通过,Starry QEMU 用时均低于 10 分钟
  • 由于 rcore-org 无 CI 运行记录,无法确认最新代码在组织 CI 中的行为

前次 Review 评论处理

已检查全部 6 次前次 review(#4599050025 APPROVED → #4605454109 APPROVED → #4606597583 APPROVED → #4607384262 CHANGES_REQUESTED → #4608632472 APPROVED → #4614147250 CHANGES_REQUESTED)。所有前次阻塞项(合并冲突、loongarch64 CI 失败)均已通过 rebase 和修复解决。

阻塞项:合并冲突

当前 PR 与 dev 分支存在合并冲突(mergeable: false):

  1. Cargo.toml:dev 已将多个 workspace crate 版本升级(axbuild 0.4.16、axdevice 0.5.1、axklib 0.7.0 等),本 PR 引入 bare-task 但使用旧版本号。需要 rebase 保留 bare-task 添加并采用 dev 的新版本号。
  2. os/axvisor/Cargo.toml:dev 新增 plat-dyn feature,本 PR 移除 irq feature。需要 rebase 保留 irq 移除并合并 plat-dyn 添加。

结论

代码审查无阻塞性设计或正确性问题。cfg(feature = "irq") 清理彻底,本地 fmt/clippy/tests 全部通过。但当前存在合并冲突,需要 rebase 到最新 dev。

建议:REQUEST_CHANGES — 请 rebase 到最新 dev,解决 Cargo.tomlos/axvisor/Cargo.toml 的合并冲突(保留 bare-task 添加和 irq feature 移除,采用 dev 的新版本号和 plat-dyn feature),并确认 rcore-org CI 通过。

Powered by mimo-v2.5-pro

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码审查:refactor(ax-task): make IRQ runtime mandatory (#1451)

改动概述

本 PR 将 ax-task 多任务 runtime 收敛为默认 IRQ-aware,删除 irq Cargo feature,将 IRQ 语义作为基础能力。涉及 122 个文件,+6739/-1284。核心改动包括:新增 bare-task 核心 crate(任务状态机、wake metadata、IRQ wake queue、timer runtime、RuntimeEvent、LocalExecutor);IrqTaskWaker 拆分为 TaskWaker + HardIrqWakerIrqNotify 收敛为 HardIrqSignal;future timer 改为全局 FutureTimerService;NVMe deferred completion drain 优化;全面清理 cfg(feature = "irq") 残留。

本地验证结果

  • cargo fmt --check ✅ 通过
  • cfg(feature = "irq") 全仓库 .rs 文件 0 处残留,Cargo.toml 0 处残留 ✅
  • cargo xtask clippy --package bare-task ✅ 通过(6 checks)
  • cargo xtask clippy --package ax-task ✅ 通过(18 checks)
  • [patch.crates-io]

代码层面设计清晰、实现合理:IRQ 快路径零分配零锁,generation 失效机制防止 stale wake/completion,TaskWaker/HardIrqWaker 类型边界明确。cfg(feature = "irq") 清理彻底。

CI 状态

当前 head 8089a5456fc9b53e30ebd31108667e55c7837558 在主仓库 无 CI 运行记录(check-runs 为空)。作者 PR body 中提到 fork push CI(run 28580203159)已通过,但主仓库 CI 未验证。

前次审查状态

前次审查(review 4614147250)因 loongarch64 QEMU CI 失败(timer runtime 从 per-CPU 改为全局 SpinNoIrq 后的竞态问题)提出 REQUEST_CHANGES。作者声称已在最新 head 中修复,fork CI 已通过。但主仓库 CI 无法验证此修复。

阻塞问题

  1. 合并冲突mergeable: falsemergeable_state: dirty。PR 基于旧 dev(base SHA 10c0336f)rebase,当前 dev 已推进到 705e1482。需要再次 rebase 到最新 dev 并解决冲突。
  2. 主仓库无 CI 验证:当前 head 无 CI 运行记录。前次 REQUEST_CHANGES 指出的 loongarch64 CI 失败未经主仓库 CI 验证修复。

请 rebase 到最新 origin/dev 并确保主仓库 CI 通过后再提交审查。

Powered by mimo-v2.5-pro

@ZR233
ZR233 force-pushed the codex/starry-irq-runtime-refactor branch from 8089a54 to 09c6f33 Compare July 3, 2026 01:24

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码审查:refactor(ax-task): make IRQ runtime mandatory (#1451)

改动概述

本 PR 由 14 个 commit 组成(122 文件,+6740/-1289),将 ax-task 多任务 runtime 收敛为默认 IRQ-aware,删除 irq Cargo feature,将 IRQ 语义作为基础能力。主要改动包括:

  1. 新增 components/bare-task:OS 无关的任务调度核心 crate,通过 trait-ffi 定义 OS ABI。包含 TaskCore 状态机、RunQueueCoreIrqWakeQueueCoreHardIrqWaker/TaskWaker、per-CPU runtime core 以及 host virtual IRQ/SMP 测试。
  2. ax-task 重构:核心调度协议收敛进 bare-taskax-task 保留 ArceOS OS adapter、栈/TLS/context switch/HAL timer/IPI/public API glue。
  3. IrqTaskWaker 拆分TaskWaker(task context 直接 unblock scheduler)+ HardIrqWaker(hard IRQ 只入 pending queue),类型边界清晰。
  4. IrqNotify 收敛为 HardIrqSignalnotify_*_from_irq 改名为 notify_*_deferred,语义更准确。
  5. future timer 改为全局 FutureTimerService:timer IRQ 只标记 service pending 并 poke HardIrqSignal,worker 在 task context drain expired wakers。
  6. PollSet 重构:移除固定容量限制,改用 Vec;同一 waker 多次注册合并 interests 而非替换;wake_from_irq 改为批量 drain。
  7. cfg(feature = "irq") 清理:全仓库 .rs 文件 0 处残留,Cargo.toml feature 0 处残留。
  8. 平台层 IRQ 接口默认可见ax-plataxplat-dyn 等 IRQ 接口从 feature-gated 改为始终可见;没有真实中断控制器的平台返回 Unsupported 或 no-op。

审查清单验证

  1. ✅ PR 元数据:head 09c6f33b 与 checkout SHA 一致,maintainer_can_modify=true,非 draft。
  2. cfg(feature = "irq") 清理:.rs 文件 0 处,Cargo.toml 0 处。
  3. [patch.crates-io] 检查:全仓库无 [patch.crates-io]
  4. cargo fmt --check:通过。
  5. cargo xtask clippy --package bare-task:6 checks,全部通过。
  6. cargo xtask clippy --package axpoll:2 checks,全部通过。
  7. cargo xtask clippy --package ax-task:18 checks,全部通过。
  8. cargo xtask clippy --package ax-runtime:22 checks,全部通过。

CI 状态

CI 运行 28632244736(head 09c6f33b):

  • Test axvisor loongarch64 qemu / run_containersuccess
  • 其余 jobs 因路径过滤 skipped(预期行为,非 CI 跳过覆盖)
  • 无失败项

作者 fork CI 28580203159 已全部通过:Starry QEMU aarch64 6m05s、riscv64 4m54s、x86_64 7m10s、loongarch64 9m26s。

前次 CHANGES_REQUESTED 解决情况

前次审查(Review 6,commit 65e714988)提出的两个阻塞项:

  1. loongarch64 QEMU CI 失败 → 已解决:作者修复了 test-cargo-jobserver-wait 中 waitpid 与 pipe drain 的竞态,fork CI 和 rcore-os CI 均已通过。
  2. timer runtime 从 per-CPU 改为全局 SpinNoIrq 的竞态风险 → 已解决:FutureTimerService 设计正确,timer IRQ 只标记 pending 并 poke signal,worker 在 task context drain,避免了 IRQ context 中的锁竞争。

重复与重叠分析

已检查当前 open PR 列表:

  • PR #1482(feat(cv181x-sdhci): add SG2002 SD driver)— SD 驱动,与 IRQ runtime 无关。
  • PR #1481(feat(crab-usb): add RK3588 EHCI USB2 host)— USB host,与 IRQ runtime 无关。
  • 未发现与本 PR 重复或冲突的 open PR。

非阻塞建议(后续 PR 跟进)

  1. bare-task 新 crate 的 trait-ffi OS ABI 接口建议在后续文档 PR 中补充使用指南,方便其他平台接入。
  2. PollSet 新的 Vec 实现不再有固定容量上限,建议在高并发 poll 场景下监控内存增长。

结论

PR 设计清晰、实现正确、测试充分。IRQ 作为多任务 runtime 基础能力的决策合理——调度、timer、future runtime、设备完成路径都依赖中断语义。移除 irq feature 后,同一 runtime 内不再维护两套互斥语义,降低了丢 wake/卡死风险。所有前次阻塞项已解决,CI 无失败,无阻塞性问题。

LGTM — APPROVE

Powered by mimo-v2.5-pro

@ZR233
ZR233 force-pushed the codex/starry-irq-runtime-refactor branch from 09c6f33 to 6a20b32 Compare July 3, 2026 03:25

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码审查:refactor(ax-task): make IRQ runtime mandatory (#1451)

改动概述

本 PR 由 17 个 commit 组成(123 文件,+6836/-1356),将 ax-task 多任务 runtime 收敛为默认 IRQ-aware,删除 irq Cargo feature,将 IRQ 语义作为基础能力。新增 bare-task 组件(OS 独立的任务调度核心),IrqTaskWaker 拆分为 TaskWaker + HardIrqWaker,新增 FutureTimerService 全局 timer 服务,IrqNotify 重写为 HardIrqSignal

本地验证

  • cargo fmt --check ✅ 通过
  • cfg(feature = "irq") 残留:0 处(.rs 文件和 Cargo.toml 均已清理彻底)
  • [patch.crates-io]:无

CI 状态

CI 运行 28639959354(head e71cfe613)整体结论为 "failure",但分析如下:

通过的 jobs: Check formatting ✅、Run sync-lint ✅、Run spin-lint ✅、Test axvisor riscv64 qemu ✅、Test arceos aarch64 qemu ✅、Test axvisor x86_64 svm hosted ✅、Test axvisor loongarch64 qemu ✅、Test axvisor self-hosted x86_64 ✅

被取消的 jobs: Test starry aarch64/x86_64 qemu(Run command 运行约 5 分钟后被级联取消)、board tests(setup 阶段被取消)

Starry QEMU 容器测试被级联取消,模式与超时/基础设施问题一致。axvisor 和 arceos 测试均在多个架构上通过。此 CI 失败非 PR 引入。

合并冲突

当前 PR 与 dev 分支存在合并冲突(5 个文件):

  • docs/docs/components/crates/ax-libc.md
  • os/StarryOS/lkm/hello/Cargo.toml
  • os/StarryOS/lkm/kprobe_test/Cargo.toml
  • os/StarryOS/starryos/Cargo.toml
  • os/arceos/ulib/axlibc/Cargo.toml

冲突原因:dev 分支合入了 #1478(remove static platform)引入了 defplat feature 和旧 irq 引用,与本 PR 移除 irq 的改动冲突。冲突较小,可直接保留本 PR 的版本(移除 irq,保留 defplat)。

前次 review 处理情况

前次 REQUEST_CHANGES(commit 65e714988)提出的 loongarch64 CI 失败已在后续 commit 中修复:timer wake 改为 deferred、IrqTaskWaker 拆分、FutureTimerService、riscv-vcpu host software interrupt 路由。所有前次阻塞项已解决。

重复分析

已检查 open PR 列表:无与 IRQ runtime refactor 重复或冲突的 PR。

非阻塞建议

  1. CompletionCacheEntry::generationRelaxed 语义依赖 readyRelease/AcqRel 保证可见性——逻辑正确,建议在 record() 附近加注释说明内存序依赖。
  2. IrqNotify/HardIrqSignalactive_waiter 原子指针与 lock 的交互关系建议加注释。

结论

代码设计清晰、cfg(feature = "irq") 清理彻底、无 [patch.crates-io]、CI 失败非 PR 引入。唯一阻塞项为合并冲突。

建议:REQUEST_CHANGES — 请 rebase 到最新 dev,解决上述 5 个文件的合并冲突后重新推送。

Powered by mimo-v2.5-pro

@ZR233
ZR233 force-pushed the codex/starry-irq-runtime-refactor branch 2 times, most recently from e3fb6e0 to 1f26c63 Compare July 3, 2026 08:50

@mai-team-app mai-team-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码审查:refactor(ax-task): make IRQ runtime mandatory (#1451)

改动概述

本 PR(124 文件,+6980 行)将 ax-task 多任务 runtime 收敛为默认 IRQ-aware,删除 irq Cargo feature,新增 bare-task crate(OS 无关的任务调度核心),并修复了多个 hard IRQ wake、WaitQueue 成员管理、notify callback、future timer 等深层并发正确性 bug。这是对调度/IRQ/wake 基础架构的重构,设计理由充分,PR 历史(多次 rebase + CI fix)也证明了作者的迭代质量。

审查清单

检查项 结果
cargo fmt --check ✅ 通过
cargo xtask clippy --package ax-task ✅ 18/18 通过
cargo xtask clippy --package bare-task ✅ 6/6 通过
cargo test -p bare-task --features "host-test smp ipi irq" ✅ 28/28 通过
cargo test -p axpoll ✅ 12/12 通过
cargo test -p ax-task --features "test smp ipi sched-rr" ✅ 关键测试全部通过(test_fp_state_switch SIGSEGV 是 dev 已有问题)
cfg(feature = "irq") 残留(.rs 文件) ✅ 0 处残留
[patch.crates-io] ✅ 无
重复/重叠分析 ✅ 无重复或冲突的 open PR

代码质量

  • bare-task 设计:通过 trait-ffi 定义 OS ABI,不依赖 ax-halax-percpuax-kspin 等 crate。TaskCorewait_queue_key 机制(替代旧的 in_wait_queue: bool)配合 clear_wait_queue_key(key) 的 CAS 校验,从根本上消除了 stale entry 跨队列偷走 membership 的 bug。设计清晰,单元测试充分。
  • WaitQueue 收敛notify_one() / notify_one_with() 改为循环跳过 stale/ready entry,只有 unblock_task() 真正成功时才消费通知。配合 blocked_resched_abortable() 的入队-复查-abort 闭合协议,以及 wake_task()take_wait_queue_key() 强制清 key,wait queue 成员管理现在是一套自洽的不变量系统。
  • HardIrqWaker / TaskWaker 类型拆分:hard IRQ 注册点只能拿到 HardIrqWaker(只暴露 wake_from_irq()),普通 Rust WakerTaskWaker(直接 unblock scheduler)。类型系统在编译期就阻止了 hard IRQ context 中错误地拿 scheduler lock。
  • PollSet 重构:从固定容量 Box<[MaybeUninit]> + 游标循环改为 Vec<Entry> + swap_remove,waker 去重改为 will_wake() 遍历合并。wake_from_irq() 改为 batch 循环 drain,不再假设单一 pass 能清空。

CI 状态

阻塞项:当前 head d6bff549 的唯一 CI 运行(run 28762127558)结论为 cancelled,所有 job 均为 skipped。没有任何架构的 QEMU 测试或 board 测试实际执行过。

  • 该 head 是 2026-07-06 最新 rebase 到 origin/dev 882e07fd2 的结果。PR 历史上多个中间 head 出现过 loongarch64 Starry QEMU 失败、riscv64 Starry QEMU 1800s 超时、ArceOS loongarch64 QEMU 卡死等问题(PR body 中有详细记录)。
  • 本 PR 触及 124 个文件,涉及调度/WaitQueue/IRQ wake/future timer 等核心基础架构。这类改动无法仅靠本地单元测试覆盖;跨架构 QEMU/board CI 是必须的验证层。

结论

代码设计和实现质量优秀,本地验证通过,cfg(feature = "irq") 清理彻底,无 [patch.crates-io],无重复或冲突的 open PR。但当前 head 无 CI 覆盖,对于这种规模的核心基础架构 PR 是不可接受的。

建议:REQUEST_CHANGES — 请触发 CI 运行并通过所有 job(特别是 Starry QEMU aarch64/riscv64/x86_64/loongarch64),然后我们可以重新审查并 approve。

如果 CI 触发后大部分通过、仅有个别已知的非本 PR 引入的失败,请在该 job 的日志/评论中说明,我会重新评估。

Powered by deepseek-v4-pro

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant