线程切换(2)
线程切换过程中锁的限制
在线程切换的过程中需要一直持有p->lock
防止两个CPU核使用同一个栈运行同一个线程
XV6中,不允许进程在执行switch函数的过程中,持有任何其他的锁。
防止死锁。
示例:如果xv6在内核中关闭了中断,P1的内核线程持有了p->lock以外的其他锁,这些锁可能是在使用磁盘,UART,console过程中持有的。之后内核线程在持有锁的时候,通过调用switch/yield/sched函数出让CPU,这会导致进程P1持有了锁,但是进程P1又不在运行。假设P2也想使用磁盘,UART或者console,它会对P1持有的锁调用acquire,这是对于同一个锁的第二个acquire调用。当然这个锁现在已经被P1持有了,所以这里的acquire并不能获取锁。
sleep和wakeup接口
进程有时候需要等待特定事件的。特定事件可能来自于I/O,也可能来自于另一个进程,并且它描述了某件事情已经发生。Coordination是帮助我们解决这些问题并帮助我们实现这些需求的工具。
实现方式:
- busy-wait:只适用于等待时间很短的事件中
- Coordination:出让CPU,直到等待的事件发生再恢复执行
sleep函数:睡眠该线程,等待一个特定的事件。
wakeup函数:唤醒正在等待刚刚发生的特定事件的线程。
sleep函数和wakeup函数都带有一个叫做sleep channel的参数。我们在调用wakeup的时候,需要传入与调用sleep函数相同的sleep channel。不过sleep和wakeup函数只是接收表示了sleep channel的64bit数值,它们并不关心这个数值代表什么。当我们调用sleep函数时,我们通过一个sleep channel表明我们等待的特定事件,当调用wakeup时我们希望能传入相同的数值来表明想唤醒哪个线程。
线程切换(2)
http://example.com/2024/02/29/操作系统/xv6-labs/线程切换2/