Operating system 为什么在上下文切换之前禁用中断

Operating system 为什么在上下文切换之前禁用中断,operating-system,synchronization,semaphore,interrupt,Operating System,Synchronization,Semaphore,Interrupt,我在读操作系统教科书,在同步章节中,它说: 特别是,, 大多数线程系统的实现都强制执行线程的不变量 在执行上下文切换之前始终禁用中断 因此,当在进入睡眠之前写入Aquire时,它将首先禁用中断 我的问题是,为什么在上下文切换之前需要中断禁用,它是用来保护寄存器和保持获取原子的吗 在临界截面之前使用隔水层,如下所示: Aquire(){ disable interrupt; if (is busy){ put on wait queue; sleep(); } else s

我在读操作系统教科书,在同步章节中,它说:

特别是,, 大多数线程系统的实现都强制执行线程的不变量 在执行上下文切换之前始终禁用中断

因此,当在进入睡眠之前写入Aquire时,它将首先禁用中断

我的问题是,为什么在上下文切换之前需要中断禁用,它是用来保护寄存器和保持获取原子的吗

在临界截面之前使用隔水层,如下所示:

Aquire(){
 disable interrupt;
 if (is busy){
    put on wait queue;
    sleep();
 }
 else set_busy;
 enable interrupt;
}
进入睡眠状态将实现上下文切换,为什么我们应该在上下文切换期间禁用中断?我们可以将代码更改为:

Aquire(){
 disable interrupt;
 if (is busy){
    enable interrupt;
    put on wait queue;
    sleep();
 }
 else set_busy;
 enable interrupt;
}

也就是说,在线程A中启用中断,而不是让上下文切换后的其他线程B在进入睡眠后启用中断?

通常,同步原语需要同时更新多个数据位置。例如,信号量获取可能需要将当前线程的状态更改为阻塞,更新信号量的计数,从队列中删除当前线程并将其放置在另一个队列中。因为同时进行是不可能的,所以有必要设计一个访问协议来模拟这种情况。在单cpu系统中,最简单的方法是禁用中断,执行更新,然后重新启用中断。遵循此协议的所有软件将立即看到更新

多cpu系统通常需要一些额外的东西来同步独立cpu上的线程,以避免干扰。禁用中断是不够的,因为这只会影响当前的cpu。额外的东西通常是一个旋转锁,它的行为很像互斥或二进制信号量,只是调用方在可用之前一直处于重试循环中

即使在多cpu系统中,也必须在禁用中断的情况下执行操作。假设Thread0在cpu0上获得了一个自旋锁;然后,cpu0上的中断导致Thread1抢占,Thread1随后尝试获取相同的自旋锁。有很多情况都是这样的


*事务al内存提供类似的功能,但适用性有限,并且实现必须提供独立的实现以确保向前推进。此外,由于事务不嵌套,因此它们也确实需要禁用中断。

什么是Aquire?Aquire有多种类型,我已经纠正了我的问题。请注意,虽然较旧的编译器会将所有asm指令视为潜在的内存阻塞器,较新的编译器忽略了启用和禁用中断等操作可能被用于保护对其他执行上下文使用的对象的访问的可能性,而跨中断启用/禁用原语移动访问的优化是不必要的危险;所谓的智能链接器完全不适合系统代码。智能链接器没有理由不支持适合系统代码的模式。很少有程序关心函数调用是否实际使用函数调用进行处理。重要的是,通常函数中的一些关键操作不会在调用代码中的操作之间重新排序。如果工具设计师认识到他们的客户比标准的作者更了解他们的特殊需求,对他们来说,添加逻辑应该很简单,例如,如果一个函数执行任何易失性访问……那么潜在的内存崩溃需要被识别为发生在这些访问和调用代码之间的某个地方。编译器作者坚持认为,从来没有将易失性访问视为内存阻塞的传统,但这是因为对包含此类访问的函数的调用与对所有其他被视为内存阻塞的函数的调用一样。有人编写了一个依赖于易失性的函数,将其作为内存阻塞器,可能能够确保所有需要保护的访问都是易失性的,但是……调用代码通常无法做到这一点。