也许这只是我,但是在第二man 2页面上的membarrIEr似乎毫无意义。
基本上, membarrIEr()是一个asynchronous内存屏障,给定两个协调的代码片段(让我们调用快速path和慢速path ),可以将障碍的所有硬件成本移动到慢速path ,并保留快速path只有一个编译器障碍1 。 有几种不同的方式来完成membarrIEr行为,例如发送IPI给每个相关的处理器,或者等待每个处理器上运行的代码被取消调度 – 但是在这里确切的实现细节并不重要。
现在,这是在手册页中给出的示例转换:
原始代码
static volatile int a,b; static voID fast_path(voID) { int read_a,read_b; read_b = b; asm volatile ("mfence" : : : "memory"); read_a = a; /* read_b == 1 implIEs read_a == 1. */ if (read_b == 1 && read_a == 0) abort(); } static voID slow_path(voID) { a = 1; asm volatile ("mfence" : : : "memory"); b = 1; }
转换后的代码
(省略了一些系统调用和init模板)
是否使用匿名pipe道为线程间通信引入了内存障碍?
static volatile int a,read_b; read_b = b; asm volatile ("" : : : "memory"); read_a = a; /* read_b == 1 implIEs read_a == 1. */ if (read_b == 1 && read_a == 0) abort(); } static voID slow_path(voID) { a = 1; membarrIEr(MEMbarRIER_CMD_SHARED,0); b = 1; }
在这里, slow_path正在执行两次写 *** 作( a , b ),并且fast_path正在执行两次读 *** 作( b ,然后a ),这两个读 *** 作也被一个障碍隔开。
但x86内存模型不允许加载或存储重新sorting! 所以,据我所知,在这种情况下不需要membarrIEr() ,原始代码中也不需要mfence 。 看起来,简单的编译器障碍在两个地方都是足够的2 。
一个实际上是有道理的例子,海事组织,应该有一个商店,后面是一个负载,在快速path的障碍分开。
我错过了什么吗?
1编译器的障碍阻止了编译器在其上的加载或存储的移动(并且取决于实现可能强制某些寄存器值到内存),但是不会发出任何types的primefaces *** 作或内存围栏,这些指令固有的幅度放缓。
2当然,在较弱的平台上,可能发生负载重新sorting,这个例子可能是有道理的,但是这个例子是明确的x86和membarrIEr()只在x86上实现。
你是对的。 在x86上, membarrIEr()这种特殊用法是完全没有用的。 实际上, 这个确切的例子是Intel SDM中第一个用来说明x86内存排序规则的例子:
英特尔SDM卷。 3§8.2.3.2既不加载也不加入类似的 *** 作
我正在提交一个修复这个手册页来代替使用一个Dekker的例子。 请参阅https://lkml.org/lkml/2017/9/18/779
顺便说一下,影片系统调用不是特定于x86的,而是现在在大多数linux架构上实现的。
感谢您的反馈!
马蒂厄
总结以上是内存溢出为你收集整理的x86中的手册页中的示例是无意义的吗?全部内容,希望文章能够帮你解决x86中的手册页中的示例是无意义的吗?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)