首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >spin_lock_irqsave vs spin_lock_irq

spin_lock_irqsave vs spin_lock_irq
EN

Stack Overflow用户
提问于 2010-04-01 18:11:30
回答 6查看 77.8K关注 0票数 31

在SMP机器上,我们必须从中断上下文中使用spin_lock_irqsave,而不是spin_lock_irq

为什么我们要保存标志(包含IF)?

有没有另一个中断例程可以中断我们?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2010-04-03 16:27:40

如果在您的代码开始锁定之前已经禁用了中断,那么当您调用spin_unlock_irq时,您将以一种可能有害的方式强制重新启用中断。相反,如果您还通过spin_lock_irqsave将当前中断启用状态保存在flags中,并在释放锁定后尝试使用相同的flags重新启用中断,则该函数将仅恢复以前的状态(因此不一定启用中断)。

使用spin_lock_irqsave的示例

代码语言:javascript
复制
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 ):

代码语言:javascript
复制
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...
票数 27
EN

Stack Overflow用户

发布于 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

票数 48
EN

Stack Overflow用户

发布于 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()的相应调用会无条件地启用中断,尽管它们一开始就是关闭的。相反,需要一种机制来将中断恢复到以前的状态。这是一个常见的问题,因为内核中的给定代码路径可以在启用和不启用中断的情况下访问,具体取决于调用链。例如,假设前面的代码片段是一个更大的函数的一部分。假设这个函数被另外两个函数调用,一个禁用中断,另一个不禁用。由于随着内核大小和复杂性的增加,知道通向某个函数的所有代码路径变得越来越困难,因此在禁用中断系统之前保存它的状态要安全得多。然后,当您准备好重新启用中断时,您只需将它们恢复到其原始状态:

代码语言:javascript
复制
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中断的调用必须发生在同一函数中。

前面的所有函数都可以从中断和进程上下文中调用。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2559602

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档