补充
This commit is contained in:
24
LIST
Normal file
24
LIST
Normal file
@@ -0,0 +1,24 @@
|
||||
### 问题 3:isr32_handler 中调用 _yield() 的安全性
|
||||
idt.py:165-169 :
|
||||
|
||||
```
|
||||
def isr32_handler():
|
||||
timer.timer_handler()
|
||||
if s.needs_reschedule:
|
||||
sched.Scheduler._yield()
|
||||
```
|
||||
_yield() 内部会切换栈帧( _do_switch 修改 RSP)。但在中断上下文中,当前栈是中断帧(由 ISR_NOERR 32 宏 push 的寄存器)。如果 _yield() 切换到另一个线程,那个线程的 _do_switch 返回时会 ret 到 _yield() 的调用者——而不是 iretq 返回中断。
|
||||
|
||||
这意味着中断帧被"遗弃"在旧线程的栈上 ,直到旧线程再次被调度回来时, _yield() 返回,然后 isr32_handler 返回,ISR_NOERR 宏执行 iretq 。
|
||||
|
||||
这个设计是 可以工作的 ,因为:
|
||||
|
||||
1. _yield() 保存了完整的 callee-saved 寄存器
|
||||
2. 中断帧在旧线程栈上,旧线程恢复时会继续执行 iretq
|
||||
3. _yield() 内部有自旋锁保护
|
||||
但有一个隐患:如果在中断上下文中 _yield() 切换到的线程也触发了定时器中断,就会 嵌套中断 + 嵌套 _yield() 。虽然自旋锁 _yield_lock 会阻止第二次 _yield() ,但这意味着时间片到期后无法切换,直到第一次 _yield() 返回。
|
||||
|
||||
|
||||
继续进行剩余的进程隔离,内存管理增强,以及上述的几个工作,依旧是分步
|
||||
注意,需要循序渐进,每一步后立即进行测试,也就是在每个小改进后立即进行测试,我将在出现任何问题后立即告诉你
|
||||
|
||||
Reference in New Issue
Block a user