Skip to content

第二十六周工作总结

概述

本周围绕 rt-async-amp 项目的 AMP IPC 通信,完成了三个阶段的工作:

  1. 定位并修复 IPC 死锁:根因是 PollSet 内部 spin::Mutex 不关中断,IPI handler 与 register 在同一 hart 上死锁
  2. 重构 StarryOS 侧 await 机制:彻底移除中间计数器,改为直接读取 ring buffer 状态 + Waker 唤醒
  3. ov-channels 库泛型化重构并发布 v0.2.0SharedMemory<const N> 泛型化,新增 flags feature gate

1. AMP IPC 死锁排查与修复

问题现象

user-test-sched 三明治计时测试中,客户端 await_ipi 永久阻塞。死锁只在完整 RPC 流程(DELAY + ECHO 连续调用)中出现,单步调用正常。

根因分析

PollSet 内部使用 spin::Mutex(裸自旋锁,不关中断)保护 waker 队列。当 Task 在 hart 0 上调用 register(waker) 持有锁时,同一 hart 的 IPI 中断到达,ipi_irq_handler 尝试调用 wake() 获取同一把锁——中断 handler 等待被中断的代码释放锁,锁永远不会被释放。

修复

  • 服务端send_notify_ipi() 封装 IPI 发送,每个 Notify 响应立即回 IPI
  • Linux 侧SpinNoIrq<Option<Waker>> 替换 PollSet(关中断保护 waker 注册);移除 IPC_PENDING,改为直接读 CH1 ring buffer 判断消息可用性
  • IPI handler 仅 wake 已注册的 Waker,spurious wakeup 安全因为 ring buffer 是权威状态

详细排查过程记录在 AMP 死锁排查技术报告

相关文件变更

  • apps/rt-async-app/src/intercom.rs:IPI 策略重构、弹性自旋窗口扩大(1000→100000)、新增日志
  • StarryOS/kernel/src/pseudofs/dev/rt_shm.rs:移除 IPC_PENDING/PollSet,改用 ch1_has_pending() + IPC_WAKER
  • apps/rt-async-app/src/ipc_wait.rs:ISR 唤醒日志

2. StarryOS rt_shm 设备重构

移除的机制

  • IPC_PENDING: AtomicBool — 中间标志,与实际消息数不一致时导致死锁
  • IPC_POLLSET: PollSet — spin::Mutex 不关中断,同 hart 死锁
  • IPI handler 中手动清除 MSIP/SIP 的代码

新机制

  • ch1_has_pending():直接读 CH1 ring buffer 的 read/write 原子变量(offset 从 amp.toml 生成)
  • IPC_WAKER: SpinNoIrq<Option<Waker>>:IRQ-safe 的 waker 存储
  • AWAIT ioctl:先检查 ch1_has_pending() → 加锁注册 waker → 二次检查 → Pending/Ready
  • ipi_irq_handler():仅 IPC_WAKER.lock().take() + waker.wake()
  • CLR_PENDING ioctl 变为 no-op(保留 ABI 兼容)

3. ov-channels v0.2.0 泛型化重构

动机

SharedMemory 硬编码 MAX_CHANNELS = 4,外部无法自定义通道数量。作为通用库应允许调用方在编译时指定。

核心改动

变更说明
SharedMemory<const N: usize = 2>const generics 泛型化,默认 2 通道
新增 flags feature门控 busy: AtomicBoolset_busy/clear_busy/is_busy API
移除 MAX_CHANNELS不再硬编码通道数上限
ChannelId 简化去掉 is_valid() 和范围检查,校验下沉到 SharedMemory<N>
sender()/receiver()(id.get() as usize) < N 动态校验
recv_from_interrupt<N> / has_pending_interrupt<N>泛型化
新增 channel_count()返回 N

依赖更新

  • 发布到 crates.io(ov-channels = "0.2.0"
  • rt-async-amp workspace 改为 crates.io 依赖 + flags feature
  • ov-rpc server/client 使用 SharedMemory<3>(CH0 请求、CH1 响应、CH2 急停)
  • StarryOS 移除未使用的 ov-channal git 依赖

测试

  • ov-channels:33 个测试全部通过(含 std + flags feature 组合)
  • ov-rpc:35 个测试全部通过