免费注册 查看新帖 |

Chinaunix

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

preempt_disable()中怎么只有barrier而没有CPU内存屏障呢 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-05-23 13:38 |只看该作者 |倒序浏览
为什么只需要barrier就可以了?

论坛徽章:
0
2 [报告]
发表于 2008-05-23 17:00 |只看该作者
原帖由 iterator 于 2008-5-23 13:38 发表
为什么只需要barrier就可以了?

因为preepmt_count只被当前CPU访问

论坛徽章:
0
3 [报告]
发表于 2008-05-23 17:46 |只看该作者

回复 #2 flw2 的帖子

mb也只能用来限制当前CPU的乱序执行吧。
preempt_disable是一个write操作,在X86下write是保证顺序的。

论坛徽章:
0
4 [报告]
发表于 2008-05-23 18:16 |只看该作者
原帖由 bluesky_jxc 于 2008-5-23 17:46 发表
mb也只能用来限制当前CPU的乱序执行吧。
preempt_disable是一个write操作,在X86下write是保证顺序的。


恩,所以preempt_disable用不着更重量级的smp_mb了吧

论坛徽章:
0
5 [报告]
发表于 2008-05-23 20:46 |只看该作者
原帖由 flw2 于 2008-5-23 18:16 发表


恩,所以preempt_disable用不着更重量级的smp_mb了吧


可是它并不是用宏来实现的.那么对于可以乱序写的CPU,preempt_disable也实现不了内存屏障才对呀.

论坛徽章:
0
6 [报告]
发表于 2008-05-23 20:58 |只看该作者

回复 #5 iterator 的帖子

你能说出 如果不用mb会发生什么吗?

在很多情况下,mb是不必要的。

论坛徽章:
0
7 [报告]
发表于 2008-05-23 20:58 |只看该作者
原帖由 iterator 于 2008-5-23 20:46 发表


可是它并不是用宏来实现的.那么对于可以乱序写的CPU,preempt_disable也实现不了内存屏障才对呀.

LZ设想一下乱序执写的CPU在什么情况下会导致preempt_disable出错?为什么需要内存屏障?
如果可以设想出这么一种情况,这个问题才有意义。不然连下面这个程序

  1. int i = 0;
  2. int a;
  3. i ++;
  4. a = i;
复制代码

你都可以问一句为什么不加内存屏障。

论坛徽章:
0
8 [报告]
发表于 2008-05-23 21:07 |只看该作者
原帖由 zx_wing 于 2008-5-23 20:58 发表

LZ设想一下乱序执写的CPU在什么情况下会导致preempt_disable出错?为什么需要内存屏障?
如果可以设想出这么一种情况,这个问题才有意义。不然连下面这个程序

int i = 0;
int a;
i ++;
a = i;

你都 ...


惭愧地说,其实你举了这个例子后,我就更加不懂了.
可能是因为刚接触这个概念,整个弄糊涂了.
能简单讲讲么.多谢了

论坛徽章:
0
9 [报告]
发表于 2008-05-23 21:23 |只看该作者
原帖由 iterator 于 2008-5-23 21:07 发表


惭愧地说,其实你举了这个例子后,我就更加不懂了.
可能是因为刚接触这个概念,整个弄糊涂了.
能简单讲讲么.多谢了

当然,我也是不太懂的,但大概原理还是可以说说。
乱序,并非是全乱执行,它只是对于没有依赖性的指令乱序执行。
在我上面举的这个例子中,a=i就不会在i++之前执行,因为两条指令之间有依赖,称为WAW依赖(write after write )。同样,还有RAW、WAR依赖。

所以preempt_disable中对抢占计数器加是个安全的操作,和这个计数器有关联的指令不会被乱序执行,只需要防止编译器把相关指令提前即可,用barrier足够。

那么什么时候要防止乱序呢?通常在一个块内存,既对CPU可见,又对设备可见时。举个例子:
一个结构体

  1. struct dev
  2. {
  3.     int enable;
  4.     void *ptr;
  5. }dev;
复制代码

这个结构体所处的内存,设备和CPU都可以看到。正确操作设备的顺序是先给ptr指针赋值,在对enable写1启用设备。那么,下面的代码反应了这个过程:

  1. dev.ptr = buffer;
  2. dev.enable = 1;
复制代码

这里的两个写操作是没有相关性的。所以CPU可以乱序执行它们。这就造成了一个情况,ptr还没赋值之前,enable就已经写1了。那么设备可能在ptr为非法值时启动执行。我们要防止这种情况,就要用内存屏障。如下:

  1. dev.ptr = buffer;
  2. wmb();
  3. dev.enable = 1;
复制代码


大概的原理就是这样。

论坛徽章:
0
10 [报告]
发表于 2008-05-23 21:29 |只看该作者

回复 #8 iterator 的帖子

内存屏障太复杂了,我想版内应该没有人敢说自己理解了这玩意儿吧。
概念上很简单,就是每条指令执行的时候是否能感知到前面指令执行所产生的结果。
如果想深入理解,给你推荐一篇博士论文《Memory consistency Models for SMP》
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP