Spinlock的目的是用来同步SMP中会被多个CPU同时存取的变量。在Linux中,普通的spinlock由于不带额外的语义,是用起来反而要非常小心。
在Linux kernel中执行的代码大体分normal和interrupt
context两种。tasklet/softirq可以归为normal因为他们可以进入等待;nested
interrupt是interrupt context的一种特殊情况,当然也是interrupt
context。Normal级别可以被interrupt抢断,interrupt会被另一个interrupt抢断,但不会被normal中断。各个
interrupt之间没有优先级关系,只要有可能,每个interrupt都会被其他interrupt中断。
我们先考虑单CPU的情况。在这样情况下,不管在什么执行级别,我们只要简单地把CPU的中断关掉就可以达到独占处理的目的。从这个角度来说,spinlock的实现简单地令人乍舌:cli/sti。只要这样,我们就关闭了preemption带来的复杂之门。
单CPU的情况很简单,多CPU就不那么简单了。单纯地关掉当前CPU的中断并不会给我们带来好运。当我们的代码存取一个shared
variable时,另一颗CPU随时会把数据改得面目全非。我们需要有手段通知它(或它们,你知道我的意思)——spinlock正为此设。这个例子是
我们的第一次尝试:
extern spinlock_t lock;
// ...
spin_lock(&lock);
// do something
spin_unlock(&lock);
他能正常工作吗?答案是有可能。在某些情况下,这段代码可以正常工作,但想一想会不会发生这样的事:
// in normal run level
extern spinlock_t lock;
// ...
spin_lock(&lock);
// do something
// interrupted by IRQ ...
// in IRQ
extern spinlock_t lock;
spin_lock(&lock);
喔,我们在normal级别下获得了一个spinlock,正当我们想做什么的时候,我们被interrupt打断了,CPU转而执行interrupt level的代码,它也想获得这个lock,于是“死锁”发生了!解决方法很简单,看看我们第二次尝试:
extern spinlock_t lock;
// ...
cli; // disable interrupt on current CPU
spin_lock(&lock);
// do something
spin_unlock(&lock);
sti; // enable interrupt on current CPU
在获得spinlock之前,我们先把当前CPU的中断禁止掉,然后获得一个lock;在释放lock之后再把中断打开。这样,我们就防止了死锁。事实上,Linux提供了一个更为快捷的方式来实现这个功能:
extern spinlock_t lock;
// ...
spin_lock_irq(&lock);
// do something
spin_unlock_irq(&lock);
如果没有nested interrupt,所有这一切都很好。加上nested interrupt,我们再来看看这个例子:
// code 1
extern spinlock_t lock;
// ...
spin_lock_irq(&lock);
// do something
spin_unlock_irq(&lock);
// code 2
extern spinlock_t lock;
// ...
spin_lock_irq(&lock);
// do something
spin_unlock_irq(&lock);
Code 1和code 2都运行在interrupt context下,由于中断可以嵌套执行,我们很容易就可以想到这样的运行次序:
Code 1
Code 2
extern spinlock_t lock;
// ...
spin_lock_irq(&lock);
|
|
|
extern spinlock_t lock;
// ...
spin_lock_irq(&lock);
// do something
|
|
spin_unlock_irq(&lock);
|
// do something
spin_unlock_irq(&lock);
|
|
问题是在第一个spin_unlock_irq后这个CPU的中断已经被打开,“死锁”的问题又会回到我们身边!
解决方法是我们在每次关闭中断前纪录当前中断的状态,然后恢复它而不是直接把中断打开。
unsigned long flags;
local_irq_save(flags);
spin_lock(&lock);
// do something
spin_unlock(&lock);
local_irq_restore(flags);
Linux同样提供了更为简便的方式:
unsigned long flags;
spin_lock_irqsave(&lock, flags);
// do something
spin_unlock_irqrestore(&lock, flags);
http://chequerjiang.spaces.live.com/?_c11_BlogPart_pagedir=Next&_c11_BlogPart_handle=cns!5EC2FCDD9FECBAF2!211&_c11_BlogPart_BlogPart=blogview&_c=BlogPart
分享到:
相关推荐
自旋锁(Spin Lock)是操作系统中用于多线程同步的一种机制,特别是在处理并发和实时系统中非常常见。自旋锁的基本思想是当一个线程试图获取已被其他线程持有的锁时,它不会立即阻塞,而是不断地循环检查锁的状态,...
《Python库spin_and_heave-0.3.0-py3-none-any.whl深度解析》 在Python的生态系统中,库扮演着至关重要的角色,它们为开发者提供了丰富的功能,简化了编程过程。本文将深入探讨名为`spin_and_heave`的Python库,...
Python库“spin_and_heave-3.1.0-py3-none-any.whl”是一个用于后端开发的软件包,特别适用于使用Python编程语言的项目。这个whl(wheel)文件是Python的一种二进制分发格式,它使得安装Python库变得更加简单和快速...
资源来自pypi官网。 资源全名:spin_and_heave-3.1.0-py3-none-any.whl
资源来自pypi官网。 资源全名:spin_and_heave-0.3.0-py3-none-any.whl
SPIN PROTOCOL FOR WIRELESS SENSOR NETWORK
SPIN PROTOCOL FOR ONE TO ONE NODE FOR WIRELESS SENSOR NETWORK
资源分类:Python库 所属语言:Python 资源全名:spin_clustering-0.0.2-py3-none-any.whl 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
SPIN PROTOCOL FOR ONE TO MANY FOR WIRELESS SENSOR NETWORK
**顺磁共振(ESR)/电子自旋共振(EPR)模拟软件——Spin_AD** 在物理学和化学领域,顺磁共振(ESR)或电子自旋共振(EPR)是一种广泛使用的实验技术,用于研究含有未成对电子的体系,如自由基、过渡金属离子等。...
- 在中断服务程序中使用自旋锁时,应选择`spin_lock_irq()` 或 `spin_lock_irqsave()` 来确保不会被新的中断打断。 3. **底半部处理** - 当需要在底半部处理过程中使用自旋锁时,可选用`spin_lock_bh()` 来避免...
spin_lock(&thing_lock); t->contents = some_value; old = global_thing; global_thing = t; spin_unlock(&thing_lock); synchronize_rcu(); kfree(old); } ``` 在这个例子中,写者首先创建一个新的数据...
I coded to transform an original image to spin image. It is only available in matlab.
Spin_Slide_ToolBar.zip
SPIN算法由Dana D. Holcombe于2001年提出,其目标是高效地处理传感器网络中的数据查询和传播。 **SPIN算法概述:** SPIN算法的核心理念是基于需求的数据传输,即只有当传感器节点收到对特定数据的需求时,它才会...
标题中的"WT.rar_ SPIN _SPIN_visual c"表明这是一个关于使用Visual C++开发的项目,其中涉及到了SPIN控件的使用。SPIN控件在Windows编程中,特别是MFC(Microsoft Foundation Classes)库中,是用于创建数字输入框...
下载spin_nuke_gizmos存储库的全部内容。 如果以.ZIP格式下载,请在所需位置解压缩zip。 对于以下步骤,我们假定该文件夹在磁盘上的位置为: /my_nuke_gizmos/spin_nuke_gizmos/ 。 通过环境变量( )或现有/新的...
2. 在硬中断上下文与其他上下文间共享数据时,使用 **spin_lock_irq** 或 **spin_lock_irqsave**。 3. 如果仅在下半部中断(soft IRQs、tasklets、timers)之间共享数据,则使用普通的 **spin_lock**。 #### 四、...
8. `spin_lock_irqsave(lock, flags)`:获取自旋锁并保存中断状态,禁用本地中断。 9. `spin_lock_irq(lock)`:禁用本地中断并获取自旋锁。 10. `spin_lock_bh(lock)`:在获取自旋锁时禁用本地软中断。 11. `spin_...