Skip to content

fix(loongarch64): ack timer irq before dispatch#1222

Merged
ZR233 merged 1 commit into
rcore-os:devfrom
ZR233:fix/loongarch64-timer-irq-ack
Jun 11, 2026
Merged

fix(loongarch64): ack timer irq before dispatch#1222
ZR233 merged 1 commit into
rcore-os:devfrom
ZR233:fix/loongarch64-timer-irq-ack

Conversation

@ZR233

@ZR233 ZR233 commented Jun 11, 2026

Copy link
Copy Markdown
Member

问题

starry test qemu --arch loongarch64 在 CI 中概率性超时,最近失败点出现在 signal 相关 system tests 中,例如 test-pidfd-send-signaltest-rt_sigpending。继续对比日志后发现,卡住点并不固定在某个 signal syscall,而是共同发生在 signal 操作后进入 usleep / nanosleep 等 timer-based sleep 后不再被唤醒。

修改

  • 调整动态 LoongArch 平台的 timer IRQ 处理顺序:先 acknowledge 当前 timer interrupt,再进入 _handle_irq()
  • 同步调整静态 ax-plat-loongarch64-qemu-virt 的 timer IRQ 处理顺序:先清 TICLR,再 dispatch timer IRQ。
  • 在架构移植调试 skill 中补充 one-shot timer IRQ ACK 顺序排查规则。

逻辑

LoongArch timer 当前作为 one-shot timer 使用。timer IRQ dispatch 路径会重新 arm 下一次 timer event。如果在 dispatch 之后才清 TICLR,当下一次 near-deadline event 已经变为 pending 时,这个 late acknowledge 可能把新事件也清掉,导致等待 timer 的任务无法再被唤醒,从而表现为概率性 hang。

因此 timer IRQ 需要先清掉本次 interrupt,再进入会重新编程下一次 one-shot timer 的 dispatch 路径。这样不会把 dispatch 期间新 arm 出来的 pending timer event 清掉。

验证

  • cargo fmt --all -- --check
  • cargo xtask clippy --package somehal
  • cargo xtask clippy --package ax-plat-loongarch64-qemu-virt
  • cargo xtask starry test qemu --arch loongarch64 -c qemu-smp1/system/syscall-test-rt_sigpending,顺序压力 5 次通过
  • cargo xtask starry test qemu --arch loongarch64 -c qemu-smp1/system/syscall-test-pidfd-send-signal,顺序压力 5 次通过
  • cargo xtask starry test qemu --arch loongarch64qemu-smp1/systemqemu-smp4/system 均通过

@mai-team-app mai-team-app Bot mentioned this pull request Jun 11, 2026
@ZR233
ZR233 merged commit 88ca1d7 into rcore-os:dev Jun 11, 2026
93 of 100 checks passed
@ZR233
ZR233 deleted the fix/loongarch64-timer-irq-ack branch June 11, 2026 08:05

@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.

审查结论:变更正确,已合并

该 PR 已在审查前被合并至 dev 分支,以下为事后审查意见。

变更内容

PR 修复了 LoongArch 平台 one-shot timer IRQ 处理中的竞态条件:timer IRQ 的中断应答(TICLR 清除 / someboot::timer::ack())原在 dispatch_irq() / _handle_irq() 之后执行,而 dispatch 路径会重新编程下一次 one-shot 定时器事件。当新事件 deadline 很近时,late acknowledge 可能将刚 arm 的 pending 中断也一并清除,导致依赖 timer 的 sleep 任务永远无法被唤醒,表现为 usleep/nanosleep 后概率性 hang。

修改将 timer IRQ 应答移至 dispatch 之前,确保只清除当前中断,不会误伤 dispatch 期间新 arm 的事件。

涉及三个文件:

  • platforms/ax-plat-loongarch64-qemu-virt/src/irq.rs:静态平台,ticlr::clear_timer_interrupt() 移到 dispatch 前,并用 match 分支替代原来分离的 else/match 结构
  • platforms/somehal/src/arch/loongarch64/mod.rs:动态平台,someboot::timer::ack() 移到 _handle_irq()
  • .claude/skills/arch-platform-porting/SKILL.md:归档排查规则

实现逻辑评估

one-shot timer 先 ack 再 dispatch 是标准实践。Linux 内核 timer 驱动同样遵循此顺序。LoongArch 手册中 TICLR 为写 1 清 0 寄存器,对当前 pending 位操作,不会影响后续新产生的中断——但前提是 ack 在 dispatch/rearm 之前完成。本次修改正确。

静态平台的 handle() 重构同时消除了原 else 分支中 Timer 未做特殊处理的潜在问题(原代码 Timer 走通用 dispatch 路径但缺少 ack),新 match 结构使每种 IRQ 类型的处理路径清晰可见。

CI 状态

CI workflow 结论为 success。关键 job 均通过:

  • Check formatting / run_host: success
  • Run sync-lint / run_container: success(含 fmt + clippy)
  • Run clippy / run_host: success
  • Test arceos loongarch64 qemu / run_host: success(覆盖变更的静态平台)
  • 其他架构测试(x86_64, aarch64, riscv64)因路径过滤被 skip,符合预期

部分 check runs 显示 conclusion: skipped 是 CI 矩阵中 run_host/run_container 互斥和路径过滤的正常行为,不是 CI 缺失。

重复/重叠分析

  • base 分支 (dev) 中不存在等效修复
  • 搜索 repo:rcore-os/tgoskits type:pr state:open loongarch timer 返回 PR #1207(AxVisor LoongArch guest 支持)和 PR #1150(IRQ binding 重构),均不与此 timer ack 修复重叠
  • 无冲突或重复

总结

修复逻辑正确,CI 全部通过,无重复或重叠。虽然 PR 已合并,但从代码审查角度应予以通过。

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