第二十六周工作总结
概述
本周围绕 rt-async-amp 项目的 AMP IPC 通信,完成了三个阶段的工作:
- 定位并修复 IPC 死锁:根因是
PollSet内部spin::Mutex不关中断,IPI handler 与 register 在同一 hart 上死锁 - 重构 StarryOS 侧 await 机制:彻底移除中间计数器,改为直接读取 ring buffer 状态 + Waker 唤醒
- ov-channels 库泛型化重构并发布 v0.2.0:
SharedMemory<const N>泛型化,新增flagsfeature 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_WAKERapps/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 存储AWAITioctl:先检查ch1_has_pending()→ 加锁注册 waker → 二次检查 → Pending/Readyipi_irq_handler():仅IPC_WAKER.lock().take()+waker.wake()CLR_PENDINGioctl 变为 no-op(保留 ABI 兼容)
3. ov-channels v0.2.0 泛型化重构
动机
SharedMemory 硬编码 MAX_CHANNELS = 4,外部无法自定义通道数量。作为通用库应允许调用方在编译时指定。
核心改动
| 变更 | 说明 |
|---|---|
SharedMemory<const N: usize = 2> | const generics 泛型化,默认 2 通道 |
新增 flags feature | 门控 busy: AtomicBool 及 set_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-ampworkspace 改为 crates.io 依赖 +flagsfeatureov-rpcserver/client 使用SharedMemory<3>(CH0 请求、CH1 响应、CH2 急停)StarryOS移除未使用的ov-channalgit 依赖
测试
- ov-channels:33 个测试全部通过(含
std+flagsfeature 组合) - ov-rpc:35 个测试全部通过