Skip to content

导引:点亮什么

052 让两个核真跑起了线程,当时留了一笔债:本机 QEMU -smp 2 下 AHCI identify 偶发踩时序竞态(单核完全正常)。这一章把那笔债还了——但还的方式有点戏剧性:它不是被直接查出来的,而是被一个看起来人畜无害的重构(把内联的启动逻辑抽成一个函数)踩成每次必现的 panic,才逼着把潜伏的竞态挖出来。根因是任务跨核迁移时,旧核存上下文、新核取同一份上下文,两头并发读写同一个 ctx 字段——写花之后 ret 跳到垃圾地址。修法对齐 Linux 的 task_struct->on_cpu:给每个任务一个「现在归哪个核」的标记,调度时跳过正在被别的核存上下文的任务。验证靠单核内核测试不回归(全绿)+ 双核 -smp 2 panic 归零。

诚实边界:这套 on_cpu 纪律是「可调试优先于性能」的取舍——被跳过的任务留在队列里等下一轮,而不是死等;对 hobby OS 够用,生产内核会做得更精细(比如 Linux 的 wake/wait 机制)。本机 QEMU 的 -smp 2 AHCI heisenbug 是环境相关的时序问题,这个修法堵的是它背后的调度竞态根因,不是 QEMU 本身的时序怪癖。

这章咱们要点亮什么

  1. 潜伏竞态长什么样:一个能跑的 SMP 调度器,为什么还会在「任务迁移」这个窗口写花上下文。
  2. heisenbug 怎么被坐实:靠对照实验(内联 vs 抽函数、有内容 vs 空循环)+ 几行诊断打印,把「偶现」逼成「必现」,再定位到根因。
  3. on_cpu 纪律:给任务标「归哪个核」,为什么这个标记能让存/取上下文不再撞车。
  4. 跳过而不是死等:为什么两个核互等对方存完会死锁,改成「挑别的任务」反而对。

035_multi_terminal-45-gf25de18 · f25de18 · 2026-08-04