正常
导引:点亮什么
052 让两个核真跑起了线程,当时留了一笔债:本机 QEMU
-smp 2下 AHCI identify 偶发踩时序竞态(单核完全正常)。这一章把那笔债还了——但还的方式有点戏剧性:它不是被直接查出来的,而是被一个看起来人畜无害的重构(把内联的启动逻辑抽成一个函数)踩成每次必现的 panic,才逼着把潜伏的竞态挖出来。根因是任务跨核迁移时,旧核存上下文、新核取同一份上下文,两头并发读写同一个ctx字段——写花之后ret跳到垃圾地址。修法对齐 Linux 的task_struct->on_cpu:给每个任务一个「现在归哪个核」的标记,调度时跳过正在被别的核存上下文的任务。验证靠单核内核测试不回归(全绿)+ 双核-smp 2panic 归零。诚实边界:这套
on_cpu纪律是「可调试优先于性能」的取舍——被跳过的任务留在队列里等下一轮,而不是死等;对 hobby OS 够用,生产内核会做得更精细(比如 Linux 的 wake/wait 机制)。本机 QEMU 的-smp 2AHCI heisenbug 是环境相关的时序问题,这个修法堵的是它背后的调度竞态根因,不是 QEMU 本身的时序怪癖。
这章咱们要点亮什么
- 潜伏竞态长什么样:一个能跑的 SMP 调度器,为什么还会在「任务迁移」这个窗口写花上下文。
- heisenbug 怎么被坐实:靠对照实验(内联 vs 抽函数、有内容 vs 空循环)+ 几行诊断打印,把「偶现」逼成「必现」,再定位到根因。
on_cpu纪律:给任务标「归哪个核」,为什么这个标记能让存/取上下文不再撞车。- 跳过而不是死等:为什么两个核互等对方存完会死锁,改成「挑别的任务」反而对。