Skip to content

睡眠锁

有时 xv6 需要长时间持有一个锁。例如,文件系统(第 8 章)在磁盘上读写文件内容时会保持文件锁定,而这些磁盘操作可能需要几十毫秒。如果另一个进程想要获取它,长时间持有自旋锁会导致浪费,因为获取进程在自旋时会浪费很长时间的 CPU。自旋锁的另一个缺点是进程在保留自旋锁的同时不能让出 CPU;我们希望这样做,以便其他进程可以在持有锁的进程等待磁盘时使用 CPU。在持有自旋锁时让出是非法的,因为如果第二个线程然后尝试获取自旋锁,可能会导致死锁;因为 acquire 不会让出 CPU,第二个线程的自旋可能会阻止第一个线程运行和释放锁。在持有锁时让出也会违反在持有自旋锁时必须关闭中断的要求。因此,我们想要一种在等待获取时让出 CPU,并在持有锁时允许让出(和中断)的锁。

Xv6 以睡眠锁的形式提供了这种锁。acquiresleep 在等待时让出 CPU,使用的技术将在第 7 章中解释。在较高的层次上,睡眠锁有一个由自旋锁保护的 locked 字段,acquiresleepsleep 的调用会原子地让出 CPU 并释放自旋锁。结果是其他线程可以在 acquiresleep 等待时执行。

因为睡眠锁保持中断启用,所以它们不能在中断处理程序中使用。因为 acquiresleep 可能会让出 CPU,所以睡眠锁不能在自旋锁临界区内使用(尽管自旋锁可以在睡眠锁临界区内使用)。

自旋锁最适合短的临界区,因为等待它们会浪费 CPU 时间;睡眠锁适用于冗长的操作。