免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12
最近访问板块 发新帖
楼主: xinshirn
打印 上一主题 下一主题

[内核同步] 抢占+SMP+中断上下文->临界区资源保护方式 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2012-12-23 23:16 |只看该作者
自旋锁特点:
(1)        自旋锁机制本身不会休眠,所以可以用于不能休眠的代码中(如IRQ 例程)。
(2)        自旋锁有性能优势(加锁/解锁 约7us)

并发是需要同步操作的根源,在SMP上并发的来源如下:
       A 进程间的抢占
       B 异步中断事件
       C 两个以上的CPU,执行同一段代码

如果有一段critical code需要在上面的A、B、C三种情况下都有可能执行到,可使用spin_lock_irq(&lock),因为
(1)        自旋锁本身是禁止本CPU上的抢占,所以A不可能发生
(2)        Spin_lock_irq(&lock)是关本CPU上的中断的,所以B不可能发生
(3)        对于C情况,CPU0没有释放自旋锁时,CPU1一直忙等待,但不会死锁

总结,需思考所要保护的资源的并发执行场景。然后决定是否使用自旋锁,以及使用哪种自旋锁。自旋锁使用不当会有如下问题:
(1)        死锁
(2)        受保护的critical code太多,可能阻止本CPU的任务调度(更高优先级的任务不得不等待),或者其它CPU忙等(不做任何事情)。

论坛徽章:
4
天秤座
日期:2013-10-18 13:58:33金牛座
日期:2013-11-28 16:17:01辰龙
日期:2014-01-14 09:54:32戌狗
日期:2014-01-24 09:23:27
12 [报告]
发表于 2012-12-24 09:26 |只看该作者
当然!!  有什么不安全的么?

论坛徽章:
4
天秤座
日期:2013-10-18 13:58:33金牛座
日期:2013-11-28 16:17:01辰龙
日期:2014-01-14 09:54:32戌狗
日期:2014-01-24 09:23:27
13 [报告]
发表于 2012-12-24 09:56 |只看该作者
11楼总结的非常全了。

事实上恰恰是在SMP的的情况下才引入的spin lock,因为smp是的“原子性”更为复杂。

在UP模式下,要想使其某段数据访问“原子的(或事务的)”发生,仅需要关调度或者关中断即可。

但是在smp环境下,关调度和关中断都无法达到“原子”的目的,因此,引入spin lock这种忙等待锁。

论坛徽章:
0
14 [报告]
发表于 2012-12-25 16:45 |只看该作者
嗯,了解了。
我之前以为spin_lock_irqsave()这个函数没有spin_lock功能(在单CPU里面确实用不着spin_lock,它只起着禁止抢占的作用),
原来如果CPU支持SMP,那么该函数就包含了spin_lock.
也就是说,在SMP情况下:
spin_lock_irqsave() = spin_lock() + local_irq_save().

论坛徽章:
1
双子座
日期:2014-09-25 13:38:50
15 [报告]
发表于 2012-12-25 17:21 |只看该作者
想问一下 spin_lock_irqsave(&lock,flags); 保存这个flags是干什么用的呢? 一直没有想明白

回复 11# wangfeifeiwc


   

论坛徽章:
0
16 [报告]
发表于 2012-12-25 18:38 |只看该作者
回复 15# wjydlut


  至于具体怎么用可以追踪一下内核的代码。但是作用是很明显的:
这个函数的作用就是用来保存中断状态的。

在这个函数执行之前的中断是否被开启了,用flag参数介入,类似于保存标志(其实实际机制并并不是简单的保存到flags);
等临界区出来的时候,调用restore的时候同样根据上次保存的标志,来恢复到之前的中断状态。

如果不要标志,禁中断的时候就不知道本来是禁止的还是使能的。
出了临界区要恢复到之前的状态,而不是一定要打开中断。

有点比较有意思,定义一个flags,但是并没将这个变量的地址,而是作为形参传入,所以在函数返回后并不能改变定义的flags,究竟是怎么实现保存中断状态的,可以追踪内核代码。

论坛徽章:
0
17 [报告]
发表于 2012-12-25 21:14 |只看该作者
spin_lock_irqsave()做了如下工作:
1)关闭本CPU内核抢占;
2)保存本地eflags到外部变量,以便于后续恢复eflags;
3)关闭本地中断;
4)加自旋锁保护;
此时无论从本地CPU上还是其他CPU上都无法进入临界区(本地关闭硬件中断,同时关闭本地CPU内核抢占,其他CPU的进程则在当前CPU上自旋);

spin_unlock_irqrestore()做了如下工作:
1)释放自旋锁;
2)从外部变量恢复本地eflags;
3)开启本地CPU内核抢占;
此时本地CPU上若在spin_lock_irqsave()之前中断是开启的则此时中断恢复开启状态,否则中断仍为关闭状态。本地CPU允许内核抢占。其他CPU可以退出自旋状态进入临界区;

论坛徽章:
0
18 [报告]
发表于 2012-12-26 09:57 |只看该作者
回复 16# xinshirn


    哈哈,你好,这个函数spin_lock_irqsave(&lock,flag)是个宏,所以实际上flags是被改变了;(发现宏比函数强大啊!)

论坛徽章:
0
19 [报告]
发表于 2012-12-26 14:13 |只看该作者
自旋锁是smp安全的
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP