免费注册 查看新帖 |

Chinaunix

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

[C] 内存屏障asm volatile("mfence":::"memory")疑问 [复制链接]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-12-24 09:53 |只看该作者 |倒序浏览
如题,从LINUX内核代码找了3个内存屏障函数,用于支持SSE2的X86/X64体系的

#define        mb()        asm volatile("mfence":::"memory")
#define        rmb()        asm volatile("lfence":::"memory")
#define        wmb()        asm volatile("sfence":::"memory")

用这个同步内存是不是比pthread_mutex代价低些,我的目的仅仅是同步多线程的公用变量,不做流程控制
书上把这三个指令归类在SSE指令章节,执行这些指令应该是针对所有内存操作而不仅仅是SIMD寄存器和内存的交互吧?

论坛徽章:
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
2 [报告]
发表于 2012-12-24 10:17 |只看该作者
这三条指令根本无法取代pthread_mutex,目的不同。

倒是pthread_mutex实现过程中,需要调用了这三条指令(要看具体实现)。

论坛徽章:
30
摩羯座
日期:2013-12-23 17:28:38牛市纪念徽章
日期:2015-07-13 11:35:582022北京冬奥会纪念版徽章
日期:2015-08-07 17:10:57青铜圣斗士
日期:2015-11-27 17:45:3815-16赛季CBA联赛之天津
日期:2016-02-15 13:44:3615-16赛季CBA联赛之江苏
日期:2018-05-02 16:56:2715-16赛季CBA联赛之辽宁
日期:2018-08-08 13:41:1015-16赛季CBA联赛之深圳
日期:2018-10-02 18:05:0315-16赛季CBA联赛之天津
日期:2019-05-31 15:05:0615-16赛季CBA联赛之北京
日期:2022-06-30 13:34:1115-16赛季CBA联赛之同曦
日期:2022-07-06 19:33:5415-16赛季CBA联赛之吉林
日期:2022-12-28 14:16:22
3 [报告]
发表于 2012-12-24 11:23 |只看该作者
你这个只能保证每个进程或者线程读取的是内存的数据而不是某个寄存器中的数据,但是不能保存在一个线程把数据写入之后另一个线程去读取这个数据,也不能保证两个进程同时写这个数据,所以必须要在操作数据时给数据上锁

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
4 [报告]
发表于 2012-12-24 13:15 |只看该作者
siseniao 发表于 2012-12-24 11:23
你这个只能保证每个进程或者线程读取的是内存的数据而不是某个寄存器中的数据,但是不能保存在一个线程把数据 ...


“你这个只能保证每个进程或者线程读取的是内存的数据而不是某个寄存器中的数据”
这三个指令可不是用来干这个的,它并没有绕过CACHE去读内存
我的程序被设计成对顺序不那么敏感,公用变量数组中,每个线程只能写固定的某一部分,不会有超过一个线程去写同一个内存地址的内容
基本上是在模仿PCI驱动程序中DMA传输的做法:
(1)拷贝数据到环形DMA缓冲区的某一块内存
(2)调用wmb()
(3)写入IO寄存器告知设备这块内存的首地址,
(4)调用wmb(),进而激活DMA传输

到我的程序就是:
(1)线程拷贝数据到二维数组某个下标的内存区域
(2)调用wmb()
(3)线程写入步骤(1)拷贝的内存区域的某个字段(标志位)
(4)调用wmb()

我关心的是当其它线程看到数组中某个内存区域的标志位改变后,读取到的内容在调用rmb()之后是最新的

论坛徽章:
0
5 [报告]
发表于 2012-12-27 12:10 |只看该作者
回复 4# safedead


看起来没问题。

另外,这些指令是跟着 SSE/SSE2 加进指令集的,但是和 SIMD 没什么关系,也不只作用于 XMM 寄存器和内存的交互。

论坛徽章:
0
6 [报告]
发表于 2012-12-27 12:51 |只看该作者
内存屏障的作用是设一个标志,在这标志之前的指令一定比在这之后的指令先执行。
如果没有内存屏障,因为流水线的原因,会造成指令执行乱序。
但它不能保证线程安全吧,你最好还是用锁

论坛徽章:
0
7 [报告]
发表于 2013-07-08 01:34 |只看该作者
在intel cpu下,这三个宏不产生任何代码。仅仅是给编译器看的。

论坛徽章:
1
申猴
日期:2014-02-11 14:50:31
8 [报告]
发表于 2013-07-08 10:46 |只看该作者
回复 7# snnn


   你理解的不太对。这些指令是实实在在的指令,当然如果有些cpu已经内部实现了这些指令(比如;ia64、power系列等),
  那这些指令是没意义了,但"memory"还是有用的,给编译器hint,约束编译器

   可以这样说:lfence和sfence都是lock锁的一个特例,就是为了减少lock的开销而设计的
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP