coj*_*car 26 linux-kernel spinlock
在SMP机器上,我们必须使用 spin_lock_irqsave而不是spin_lock_irq中断上下文.
为什么我们要保存标志(包含IF)?
还有其他中断程序可能会打断我们吗?
小智 42
spin_lock_irqsave在进行自旋锁定之前,这主要用于保存中断状态,这是因为当在中断上下文中进行锁定时,自旋锁定会禁用中断,并在解锁时重新启用它.保存中断状态,以便它可以再次恢复中断.
例:
spin_lock_irq 将禁用中断x并获取锁定spin_unlock_irq 将启用中断x.因此,在释放锁之后的第3步中,我们将启用中断x,这在获取锁之前已被禁用.
因此,只有当您确定中断没有被禁用时,spin_lock_irq否则您应该始终使用spin_lock_irqsave.
Hag*_*gai 22
我是内核的新手,但是从Robert Love的书"Linux内核开发"中收集的内容,如果在代码开始锁定之前处理器上已经禁用了中断,当你调用spin_unlock_irq时,你将以错误的方式释放锁.如果保存标志并使用标志释放它,则函数spin_lock_irqsave将仅将中断返回到其先前的状态.
用例子 spin_lock_irqsave
spinlock_t mLock = SPIN_LOCK_UNLOCK;
unsigned long flags;
spin_lock_irqsave(&mLock, flags); // save the state, if locked already it is saved in flags
// Critical section
spin_unlock_irqrestore(&mLock, flags); // return to the formally state specified in flags
Run Code Online (Sandbox Code Playgroud)
示例spin_lock_irq(没有irqsave):
spinlock_t mLock = SPIN_LOCK_UNLOCK;
unsigned long flags;
spin_lock_irq(&mLock); // Does not know if already locked
// Critical section
spin_unlock_irq(&mLock); // Could result in an error unlock...
Run Code Online (Sandbox Code Playgroud)
需要spin_lock_irqsave除了spin_lock_irq颇为相似,其原因local_irq_save(flags)是需要之外local_irq_disable。这是Robert Love从Linux Kernel Development Second Edition中获取的对此要求的很好解释。
如果中断在调用之前已被禁用,则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 */
Run Code Online (Sandbox Code Playgroud)
请注意,这些方法至少部分地实现为宏,因此flags参数(必须定义为无符号long型)似乎是通过值传递的。此参数包含特定于体系结构的数据,其中包含中断系统的状态。因为至少一个受支持的体系结构将堆栈信息合并到值(ahem,SPARC)中,所以不能将标志传递给另一个函数(特别是,它必须保留在同一堆栈帧中)。因此,保存调用和恢复中断调用必须在同一函数中发生。
可以从中断和过程上下文中调用所有先前的函数。
| 归档时间: |
|
| 查看次数: |
64728 次 |
| 最近记录: |