在SMP机器上,我们必须从中断上下文中使用spin_lock_irqsave,而不是spin_lock_irq。
为什么我们要保存标志(包含IF)?
有没有另一个中断例程可以中断我们?
发布于 2010-04-03 16:27:40
如果在您的代码开始锁定之前已经禁用了中断,那么当您调用spin_unlock_irq时,您将以一种可能有害的方式强制重新启用中断。相反,如果您还通过spin_lock_irqsave将当前中断启用状态保存在flags中,并在释放锁定后尝试使用相同的flags重新启用中断,则该函数将仅恢复以前的状态(因此不一定启用中断)。
使用spin_lock_irqsave的示例
spinlock_t mLock = SPIN_LOCK_UNLOCK;
unsigned long flags;
spin_lock_irqsave(&mLock, flags); // Save the state of interrupt enable in flags and then disable interrupts
// Critical section
spin_unlock_irqrestore(&mLock, flags); // Return to the previous state saved in flags使用spin_lock_irq的示例(不带irqsave ):
spinlock_t mLock = SPIN_LOCK_UNLOCK;
unsigned long flags;
spin_lock_irq(&mLock); // Does not know if interrupts are already disabled
// Critical section
spin_unlock_irq(&mLock); // Could result in an unwanted interrupt re-enable...发布于 2013-02-20 01:34:09
spin_lock_irqsave基本上用于在获取自旋锁定之前保存中断状态,这是因为当在中断上下文中获取锁定时,自旋锁定禁用中断,而在解锁时重新启用它。保存中断状态,以便再次恢复中断。
示例:
假设在自旋锁定之前中断x被禁用,acquired
spin_lock_irq将禁用中断x,并且lock
spin_unlock_irq将启用中断x。因此,在上面的第三步中,在释放锁之后,我们将启用中断x,该中断x在获取锁之前是禁用的。
因此,只有当您确定中断没有被禁用时,您才应该使用spin_lock_irq,否则您应该始终使用spin_lock_irqsave。
发布于 2015-05-31 02:46:16
除了spin_lock_irq之外,对spin_lock_irqsave的需求与除了local_irq_disable之外还需要local_irq_save(flags)的原因非常相似。这里很好地解释了这个需求,取自Robert Love的Linux内核开发第二版。
如果在调用local_irq_disable()例程之前已经禁用了中断,那么该例程是危险的。对local_irq_enable()的相应调用会无条件地启用中断,尽管它们一开始就是关闭的。相反,需要一种机制来将中断恢复到以前的状态。这是一个常见的问题,因为内核中的给定代码路径可以在启用和不启用中断的情况下访问,具体取决于调用链。例如,假设前面的代码片段是一个更大的函数的一部分。假设这个函数被另外两个函数调用,一个禁用中断,另一个不禁用。由于随着内核大小和复杂性的增加,知道通向某个函数的所有代码路径变得越来越困难,因此在禁用中断系统之前保存它的状态要安全得多。然后,当您准备好重新启用中断时,您只需将它们恢复到其原始状态:
unsigned long flags;
local_irq_save(flags); /* interrupts are now disabled */ /* ... */
local_irq_restore(flags); /* interrupts are restored to their previous
state */请注意,这些方法至少部分是作为宏实现的,因此标志参数(必须定义为无符号的长整型)似乎是通过值传递的。此参数包含特定于体系结构的数据,其中包含中断系统的状态。因为至少有一个支持的体系结构将堆栈信息合并到值中(嗯,SPARC),所以不能将标志传递给另一个函数(具体地说,它必须保留在同一堆栈帧上)。因此,对save的调用和对restore中断的调用必须发生在同一函数中。
前面的所有函数都可以从中断和进程上下文中调用。
https://stackoverflow.com/questions/2559602
复制相似问题