Wakeup函数详解
wakeup 的逻辑相对简单,但必须遵守锁的协议。
逻辑
void wakeup(void *chan)
- 遍历进程表 (
proc[NPROC])。 - 对每个进程
p,必须先acquire(&p->lock)。- 原因: 防止 P 正在
sleep的过程中(还没切走),或者防止其他 CPU 同时修改 P 的状态。
- 原因: 防止 P 正在
- 检查:
if (p->state == SLEEPING && p->chan == chan)。 - 唤醒:
p->state = RUNNABLE。 release(&p->lock)。
配合 Sleep
正是因为 wakeup 必须获取 p->lock,而 sleep 在释放条件锁之后、切换进程之前一直持有 p->lock,所以 Wakeup 永远不可能插入到 Sleep 的“检查”和“状态修改”之间。这就解决了 Lost Wakeup 问题。