免费注册 查看新帖 |

Chinaunix

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

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

论坛徽章:
0
21 [报告]
发表于 2012-06-04 10:23 |只看该作者
zhenggn123 发表于 2012-06-04 09:57
回复 15# eexplorer
瀚海书香 发表于 2012-06-04 08:40 
回复 1# zhenggn123 


preempt_enable -> preempt_check_resched -> preempt_schedule 会主动调用__schedule()

论坛徽章:
0
22 [报告]
发表于 2012-06-04 10:39 |只看该作者
回复 21# eexplorer
是我错了。前一贴已经说了。呵呵

   

论坛徽章:
0
23 [报告]
发表于 2012-06-04 11:20 |只看该作者
回复 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。

刚才我误解了你的意思,但是15楼说的对,在preempt_schedule()中,if (likely(ti->preempt_count || irqs_disabled()))     return;  
关中断,irqs_disable()为真,关软中断,ti->preempt_count为真,当前进程就不会被调度。

论坛徽章:
0
24 [报告]
发表于 2012-06-04 12:56 |只看该作者
回复 15# eexplorer
觉得合理的解释是在spin_unlock_irq的时候,会调用preempt_enable(),这样的话,如果有更高优先级的process B ready, 会保证尽快地(在释放spinlock的时候)做一次调度preempt_schedule()。而不是等待A的时间片用完被切换出去。

我个人认为这种解释稍显牵强,如果其作用仅仅只是这样,那么将代码改成去掉preempt_disable/preempt_enable对,而在unlock时调用一下preempt_check_resched(),锁的开销将会减小,效果却相同。

   

论坛徽章:
0
25 [报告]
发表于 2012-06-04 15:41 |只看该作者
zhenggn123 发表于 2012-06-04 12:56
回复 15# eexplorer
觉得合理的解释是在spin_unlock_irq的时候,会调用preempt_enable(),这样的话,如果 ...


想了半天,想到如下情况,如果spinlock嵌套的话,如果只是在unlock的时候只调用preempt_check_resched()的话,就有可能在unlock lockb的时候,被错误的抢占出去(因为preempt_count为0,irq在spin_unlock_irq的时候被enable了)。但是如果调用preempt_disable/preempt_enable的话就没问题,因为preempt_count不会为0。

当然实际的code一般不会这么写。。。

spin_lock_irqsave(&locka, &flags);

spin_lock_irq(&lockb);
spin_unlock_irq(&lockb);

spin_unlock_irqrestore(&locka, &flags);

论坛徽章:
0
26 [报告]
发表于 2012-06-04 16:15 |只看该作者
回复 25# eexplorer
想了半天,想到如下情况,如果spinlock嵌套的话,如果只是在unlock的时候只调用preempt_check_resched()的话,就有可能在unlock lockb的时候,被错误的抢占出去(因为preempt_count为0,irq在spin_unlock_irq的时候被enable了)。但是如果调用preempt_disable/preempt_enable的话就没问题,因为preempt_count不会为0。

当然实际的code一般不会这么写。。。
spin_lock_irqsave(&locka, &flags);
spin_lock_irq(&lockb);
spin_unlock_irq(&lockb);
spin_unlock_irqrestore(&locka, &flags);


你说的情况我表示认同。确实如此。但我觉得锁对临界区的保护,不是保护临界区的代码在有问题的时候不出问题,而是确保临界区外的系统运行,不要干扰临界区的代码的正常有序运行。在第一层的spinlock关中断,必然是要假定整个临界区都在关中断的环境中运行,如果这一点得不到保证,就会像3楼和7楼说的那样,无论怎样保护都可能出问题。这是我的理解,呵呵。
   

论坛徽章:
0
27 [报告]
发表于 2012-06-04 16:40 |只看该作者
本帖最后由 eexplorer 于 2012-06-04 16:40 编辑

回复 26# zhenggn123


呵呵,那就换一种顺序:

spin_lock(&locka);

spin_lock_irqsave(&lockb, flags);
spin_unlock_irqrestore(&lockb, flags);

spin_unlock(&locka);

论坛徽章:
0
28 [报告]
发表于 2012-06-04 16:52 |只看该作者
回复 27# eexplorer
呵呵,那就换一种顺序:
spin_lock(&locka);
spin_lock_irqsave(&lockb, flags);
spin_unlock_irqrestore(&lockb, flags);
spin_unlock(&locka);


呵呵,我可不敢说spin_lock里面禁抢占是多余的。只是说在禁中断或软中断后再禁抢占似乎多余。

   

论坛徽章:
0
29 [报告]
发表于 2012-06-04 17:17 |只看该作者
回复 28# zhenggn123


不好意思,刚才没多细想就回了。

如果这样的话,好像只有这种case了:

spin_lock_irq(&locka, flags);

local_irq_enable();
...
local_irq_disable();

spin_unlock_irq(&locka, flags);

还有我觉得,抓住spinlock就意味着disable了preemption,如果不手动disable的话,就是比较隐晦的认为disable了irq就相当于disable了preemption.

论坛徽章:
0
30 [报告]
发表于 2012-06-04 17:40 |只看该作者
回复 29# eexplorer
不好意思,刚才没多细想就回了。
如果这样的话,好像只有这种case了:
spin_lock_irq(&locka, flags);
local_irq_enable();
...
local_irq_disable();
spin_unlock_irq(&locka, flags);
还有我觉得,抓住spinlock就意味着disable了preemption,如果不手动disable的话,就是比较隐晦的认为disable了irq就相当于disable了preemption.

呵呵,local_irq_enable/local_irq_disable可不能随便用哦,除非你能确定当前的中断位状态。不错,试图获得spinlock前必须禁止抢占,但不一定要调用preempt_disable,我认为。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP