免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3424 | 回复: 19
打印 上一主题 下一主题

[内核同步] 内核抢占时的内核屏障作用 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-06-11 13:04 |只看该作者 |倒序浏览
对于内核抢占实现,源码如下:

030 #define preempt_disable() \
031 do { \
032         inc_preempt_count(); \
033         barrier(); \
034 } while (0)

036 #define preempt_enable_no_resched() \
037 do { \
038         barrier(); \
039         dec_preempt_count(); \
040 } while (0)
041
042 #define preempt_check_resched() \
043 do { \
044         if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \
045                 preempt_schedule(); \
046 } while (0)
047
048 #define preempt_enable() \
049 do { \
050         preempt_enable_no_resched(); \
051         barrier(); \
052         preempt_check_resched(); \
053 } while (0)

我的问题是:为什么在preempt_disable()中先增加preempt_count的字段再进行内存屏障barrier();而在preempt_enable_no_resched()中却先进行内存屏障,再减少preempt_count?

其间的顺序有什么奥妙么?

论坛徽章:
0
2 [报告]
发表于 2012-06-11 13:17 |只看该作者
inc_preempt_count();
barrier();
do_xxx;     //需要非抢占执行

---------------------------------

do_yyy;    //需要非抢占执行
barrier();
dec_preempt_count();


barrier防止优化编译指令顺序。很明显,barrier的位置很重要。


--------------------------------
由于只要保证单cpu上的安全,所以无需使用内存屏障。

论坛徽章:
0
3 [报告]
发表于 2012-06-11 13:21 |只看该作者
回复 2# blake326

谢谢了!讲得很明白,~ 此处的内存屏障主要主要是在非抢占任务和操作preempt_count之间保存其顺序正确性,~

论坛徽章:
0
4 [报告]
发表于 2012-06-11 13:24 |只看该作者
回复 3# icanth


    这是优化屏障。

论坛徽章:
0
5 [报告]
发表于 2012-06-11 13:36 |只看该作者
能否在具体点吗?

论坛徽章:
0
6 [报告]
发表于 2012-06-11 15:37 |只看该作者
icanth 发表于 2012-06-11 13:21
回复 2# blake326

谢谢了!讲得很明白,~ 此处的内存屏障主要主要是在非抢占任务和操作preempt_count之 ...


很明白吗?我没明白。barrier()是优化屏障,不是内存屏障,不能防止编译器改变指令执行顺序-这一点是内存屏障作的事。优化屏障是禁止编译器用存放在寄存器的内存的值直接代替对内存值的访问,这是以假定内存的值在此间没有变化为前提的。优化屏障否定这一前提,要求编译器重新从内存取值。

论坛徽章:
0
7 [报告]
发表于 2012-06-11 16:07 |只看该作者
回复 6# zhenggn123


    饿,我对于优化屏障不太清楚。但刚查资料说,优化屏障是为阻止GCC编译器为适应CPU并行执行而将源代码的指令进行重排序,防止编译器级别的乱序执行。volatile关键字,不是用来干你说的这个工作的么?求指教啊!~ 按照你所解释的优化屏障,这里不能保证:
do_xxx
barrier()
inc_preempt_count()

其中 do_xxx和inc_preempt_count在CPU的执行顺序喽?

论坛徽章:
0
8 [报告]
发表于 2012-06-11 16:27 |只看该作者
回复 7# icanth


inc_preempt_count();
barrier();
do_xxx;     //需要非抢占执行

假设这里没有barrier的话,编译器可能优化成:
do_xxx;     //需要非抢占执行
inc_preempt_count();

这样do_xxx会在可抢占的情况下执行,如果来个中断,然后另外一个内核路径抢占了它也去执行do_xxx的共享资源的话就麻烦了。


???为什么不要内存屏障mb()呢,即使有barrier的话。cpu还是可以乱序执行成下面的样子啊:
do_xxx;     //需要非抢占执行
inc_preempt_count();

这个问题原因是cpu的乱序执行时有条件的,并不是随心所欲的。我的理解是,由于cpu的流水线等特点,cpu可以一次发射多条指令,然后对这多条指令可以进行有条件的(指令之间没有依赖的)重新排序执行。但是,cpu每发射一批指令之后,不管有没有乱序执行,必须等到所有指令全部执行完成后,才能接着处理中断等问题。所以现在即使cpu的乱序使do_xxx在inc_preempt_count之前执行了,由于这个时候cpu上没有办法产生中断,其他内核路径无法抢占它也去执行do_xxx之类的代码,所以说是安全的。

内存屏障对于smp同时访问共享资源才有意义。

禁止/开启 抢占是单cpu上的概念。

论坛徽章:
0
9 [报告]
发表于 2012-06-11 16:42 |只看该作者
本帖最后由 icanth 于 2012-06-11 16:43 编辑

哦,有些明白了。你的意思是,内核抢占由于针对某个CPU而言,barrier()虽然不能保证CPU乱序执行,但CPU的乱序执行却仍然保证其执行do_xxx时必然执行inc_preempt_count的安全性。可以这么理解么?

论坛徽章:
0
10 [报告]
发表于 2012-06-11 16:44 |只看该作者
回复 8# blake326

哦,有些明白了。你的意思是,内核抢占由于针对某个CPU而言,barrier()虽然不能保证CPU乱序执行,但CPU的乱序执行却仍然保证其执行do_xxx时必然执行inc_preempt_count的安全性。可以这么理解么?


   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP