免费注册 查看新帖 |

Chinaunix

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

[内核同步] 关中断或关软中断后,禁抢占是否必要 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2012-06-03 20:43 |只看该作者
回复 10# firkraag

我想楼主的意思是:
1) local_irq_disable和local_bh_disable能否保证不会发生抢占?
2) 如果能的话, spin_lock_irq的实现里面的preempt_disable是否可以去掉
   

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
12 [报告]
发表于 2012-06-04 08:40 |只看该作者
回复 1# zhenggn123
看看这个链接吧http://bbs.chinaunix.net/thread-3598312-2-1.html,答案在17楼
假设有这么个情况:
1、CPU-1在进程A的上下文调用了spin_lock_irqsave;
2、CPU-2调用wake_up_process唤醒了CPU-1上的进程B,由于进程B的优先级高于进程A,进程A的TIF_NEED_RESCHED标记被设置。(CPU-2还会用IPI通知CPU-1进行resched,但是CPU-1禁用了中断而不会响应);
3、CPU-1调用了某某函数,这个函数包含了preempt_disable和preempt_enable(没有规定关中断的情况下不能调用这样的函数吧~);
那么,如果spin_lock_irqsave没有preempt_disable,第3步中的preempt_enable将触发preempt_check_resched,从而让进程B抢占掉进程A。


   

论坛徽章:
0
13 [报告]
发表于 2012-06-04 09:28 |只看该作者
禁止其他cpu进入是通过自旋锁保证的   

论坛徽章:
0
14 [报告]
发表于 2012-06-04 09:29 |只看该作者

如果在临界区中, 唤醒某一线程 wake_up_interruptible
在这个函数里面, 是否会发生调度? (如果不禁止内核抢占的话)

应该不会啊
回复 6# wangzx99


   

论坛徽章:
0
15 [报告]
发表于 2012-06-04 09:34 |只看该作者
瀚海书香 发表于 2012-06-04 08:40
回复 1# zhenggn123
看看这个链接吧http://bbs.chinaunix.net/thread-3598312-2-1.html,答案在17楼


这个解释好像不太对吧,在preempt_schedule()里,如果irqs_disabled(),就不会做调度。

觉得合理的解释是在spin_unlock_irq的时候,会调用preempt_enable(),这样的话,如果有更高优先级的process B ready, 会保证尽快地(在释放spinlock的时候)做一次调度preempt_schedule()。而不是等待A的时间片用完被切换出去。

论坛徽章:
0
16 [报告]
发表于 2012-06-04 09:37 |只看该作者
回复 7# honkiko

有同样的想法。

只想到,如果有人写下面这样的代码,而spin_lock_irq又没有preempt_disable()的话,就有问题了。
spin_lock_irq()
...
local_irq_enable()
...                             /* --> could be preempted with spinlock held*/
spin_unlock()
   

临界区的代码肯定是审慎的,否则不管怎么样都会出错,比如说,即使spin_lock_irq里面加了preempt_disable(), 代码写成
spin_lock_irq()
...

preempt_enable()
local_irq_enable()
...                             /* --> could be preempted with spinlock held*/
spin_unlock()
也会出错啊,呵呵
   

论坛徽章:
0
17 [报告]
发表于 2012-06-04 09:48 |只看该作者
回复 12# 瀚海书香

假设有这么个情况:
1、CPU-1在进程A的上下文调用了spin_lock_irqsave;
2、CPU-2调用wake_up_process唤醒了CPU-1上的进程B,由于进程B的优先级高于进程A,进程A的TIF_NEED_RESCHED标记被设置。(CPU-2还会用IPI通知CPU-1进行resched,但是CPU-1禁用了中断而不会响应);
3、CPU-1调用了某某函数,这个函数包含了preempt_disable和preempt_enable(没有规定关中断的情况下不能调用这样的函数吧~);
那么,如果spin_lock_irqsave没有preempt_disable,第3步中的preempt_enable将触发preempt_check_resched,从而让进程B抢占掉进程A。

我的疑问在于,cpu-1在进程A的临界区没退出之前,怎么会调用某某函数(第3条)。虽然进程B的优先级高,但是关中断或关软中断后,cpu-1无法切换到其他进程。


   

论坛徽章:
0
18 [报告]
发表于 2012-06-04 09:57 |只看该作者
回复 15# eexplorer
瀚海书香 发表于 2012-06-04 08:40 
回复 1# zhenggn123 
看看这个链接吧http://bbs.chinaunix.net/thread-3598312-2-1.html,答案在17楼








这个解释好像不太对吧,在preempt_schedule()里,如果irqs_disabled(),就不会做调度。




觉得合理的解释是在spin_unlock_irq的时候,会调用preempt_enable(),这样的话,如果有更高优先级的process B ready, 会保证尽快地(在释放spinlock的时候)做一次调度preempt_schedule()。而不是等待A的时间片用完被切换出去。

基本同意,只是调用preempt_enable(),不会主动做一次调度,只是允许切换。

论坛徽章:
0
19 [报告]
发表于 2012-06-04 10:06 |只看该作者
回复 9# captivated




本帖最后由 captivated 于 2012-06-03 06:54 编辑








回复 8# firkraag 




嗯... 基本同意你的看法, 以下是我个人的想法, 请指正:




1. LZ给的代码好像就是某个内核函数的实现? 可以想像, 调用这个函数的时候, 是在内核进程上下文中.




2. preempt_disable()的实现是增加preempt_count:
  #define preempt_disable() \
  do { \
      inc_preempt_count(); \
      barrier(); \
  } while (0)
内核抢占在抢占之前都会检查 preempt_count, 如果 preempt_count 不为 0 则无法抢占.




3. 内核抢占发生的时机是在中断处理程序完成返回内核空间之前(或者显式地调用schedule()). 既然禁止了本地处理器的所有中断, 意味着时钟中断也是禁止的. 这样的话本地处理器上的内核调度根本没机会发生.




4. 个人猜测, 在smp系统上, 考虑到其它处理机的存在, 其它的处理器是可以调度的. 虽然某种程度上来说, 每个处理器只会调度自己的task队列, 但是考虑到这里处于内核空间(加上处理器负载均衡之类的?...) -- 因此其它的处理器可能有机会调度到这里并接着执行余下的代码? -- 由于其它的处理器并没有禁止中断, (假设这里没有preempt_disable的话)又发现preempt_count不为0, 所以可能发生调度?




期待正解ing...

当前的cpu没有放弃当前的进程,别的cpu无法调度到这里并接着执行余下的代码。
   

论坛徽章:
0
20 [报告]
发表于 2012-06-04 10:22 |只看该作者
回复 18# zhenggn123

回复 15# eexplorer 
瀚海书香 发表于 2012-06-04 08:40 
回复 1# zhenggn123 
看看这个链接吧http://bbs.chinaunix.net/thread-3598312-2-1.html,答案在17楼

这个解释好像不太对吧,在preempt_schedule()里,如果irqs_disabled(),就不会做调度。


觉得合理的解释是在spin_unlock_irq的时候,会调用preempt_enable(),这样的话,如果有更高优先级的process B ready, 会保证尽快地(在释放spinlock的时候)做一次调度preempt_schedule()。而不是等待A的时间片用完被切换出去。




基本同意,只是调用preempt_enable(),不会主动做一次调度,只是允许切换。
   
我错了,看了代码,调用preempt_enable(),会schedule()。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP