同步内存序检查
sync-lint 是仓库里的一个静态检查工具,入口命令是:
cargo xtask sync-lint
它的目标是:检查Atomic原子变量的使用,抓那些承担同步语义、但仍然写成了 Relaxed 的用法。
典型情况包括:
- 这个原子变量是不是在决定“别的线程/任务/CPU 能不能继续执行”
- 它是不是在负责“发布状态,再唤醒别人”
如果是,那么用 Relaxed 就有可能过弱,尤其是在 AArch64、RISC-V 这类弱内存序架构上。
当前检查范围
1. 在等待条件里使用 Relaxed
当前实现主要检查两种高置信等待场景:
wait_until/wait_timeout_until/wait_while这类等待接口的条件闭包- 带有明显阻塞或让出动作的
while循环条件,例如循环体里出现thread::yield_now()、thread::sleep(...)、spin_loop()或park()
这类代码会被报告:
WQ.wait_until(|| COUNTER.load(Ordering::Relaxed) == NUM_TASKS);
while !READY.load(Ordering::Relaxed) {
thread::yield_now();
}
原因是这里的原子变量不是“看一眼统计值”,而是在决定:
- 当前线程是否继续等待
- 当前阶段是否已经完成
- 另一个执行流是否已经把状态准备好
2. 用 Relaxed 写状态后立刻触发唤醒或调度事件
这类代码也会被报告:
COUNTER.fetch_add(1, Ordering::Relaxed);
WQ.notify_one(true);
GO.store(true, Ordering::Relaxed);
WQ.notify_all(true);
READY.store(true, Ordering::Relaxed);
ax_hal::irq::send_ipi(IPI_IRQ, target);
HAS_SIGNAL.store(true, Ordering::Relaxed);
send_signal_to_thread(None, tid, Some(sig));
这种模式通常表示:
- 先发布状态
- 再唤醒等待者、远端 CPU 或被调度任务去观察这个状态
如果发布动作还是 Relaxed,等待者就可能虽然被唤醒了,但看不到你刚刚写入的最新状态。
当前高置信事件包括 wait queue notify / wake、Waker::wake*、task unblock、IPI、futex wake,以及 StarryOS 中明确会唤醒目标任务的信号发送入口。