我经常在互联网上发现LFENCE
在x86处理器中毫无意义,也就是说,它什么也没有做,因此使用MFENCE
绝对可以轻松使用SFENCE
,因为MFENCE
= SFENCE
+ LFENCE
= SFENCE
+ NOP
= SFENCE
。
但是,如果LFENCE
没有意义,那么为什么我们有四种在x86 / x86_64中实现顺序一致性的方法:
LOAD
(无围栏)和STORE
+ MFENCE
LOAD
(无围栏)和LOCK XCHG
MFENCE
+ LOAD
和STORE
(无围栏)LOCK XADD
(0)和STORE
(无围栏)从这里拍摄:http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
以及底部第34页的Herb Sutter的表演:https://skydrive.live.com/view.aspx?resid=4E86B0CF20EF15AD!24884&app=WordPdf&wdo=2&authkey=!AMtj_EflYn2507c
如果
LFENCE
没有执行任何操作,则方法(3)具有以下含义:SFENCE + LOAD and STORE (without fence)
,但是在SFENCE
之前执行LOAD
毫无意义。即,如果LFENCE
不执行任何操作,则方法(3)没有意义。在处理器x86 / x86_64中有意义
LFENCE
指令吗?解答:
1.如果接受的答案如下所述,则需要
LFENCE
。2. 方法(3)不应单独查看,而应与先前的命令结合使用。例如,方法(3):
MFENCE
MOV reg, [addr1] // LOAD-1
MOV [addr2], reg //STORE-1
MFENCE
MOV reg, [addr1] // LOAD-2
MOV [addr2], reg //STORE-2
我们可以如下重写方法(3)的代码:
SFENCE
MOV reg, [addr1] // LOAD-1
MOV [addr2], reg //STORE-1
SFENCE
MOV reg, [addr1] // LOAD-2
MOV [addr2], reg //STORE-2
在这里,
SFENCE
可以防止对STORE-1和LOAD-2重新排序。为此,在STORE-1命令之后,SFENCE
刷新存储缓冲区。 最佳答案
底线(TL; DR):仅LFENCE
确实对内存排序毫无用处,但是并不能使SFENCE
代替MFENCE
。问题中的“算术”逻辑不适用。
这是Intel's Software Developers Manual, volume 3第8.2.2节(2014年9月的版本325384-052US)的摘录,与我在another answer中使用的相同
从这里开始:
MFENCE
是所有内存类型(无论是否为非临时性)上所有操作的完整内存防护。 SFENCE
仅阻止对写入进行重新排序(换句话说,这是StoreStore的障碍),并且仅与非临时存储和其他列为异常的指令一起使用。 LFENCE
可以防止对读取和后续读取和写入进行重新排序(即,它结合了LoadLoad和LoadStore屏障)。但是,前两个项目符号说LoadLoad和LoadStore障碍始终存在,没有异常(exception)。因此,仅LFENCE
不能用于内存排序。 为了支持最后一个要求,我查看了英特尔手册的所有3卷中提到
LFENCE
的所有地方,但没有发现会说LFENCE
是内存一致性所必需的。甚至MOVNTDQA
-迄今为止唯一的非时间加载指令-都提到了MFENCE
,但没有提到LFENCE
。更新:查看Why is (or isn't?) SFENCE + LFENCE equivalent to MFENCE?上答案的正确答案,以查看
MFENCE
是否等于其他两个范围的“和”是一个棘手的问题。一眼看去,在这三个栅栏指令中,只有MFENCE
提供了StoreLoad屏障,即防止使用较早的写入对读取进行重新排序。然而,正确的答案需要了解的不仅仅是上述规则;也就是说,重要的是所有栅栏指令都必须相对于彼此排序。这使SFENCE LFENCE
序列比仅仅结合单个效果更强大:此序列还防止了StoreLoad重新排序(因为加载无法通过LFENCE
,而不能通过SFENCE
,而不能通过存储而无法通过),从而构成了完整的内存屏障(也请参见下面的注释(*))。但是请注意,这里的顺序很重要,并且LFENCE SFENCE
序列没有相同的协同作用。但是,虽然可以说
MFENCE ~ SFENCE LFENCE
和LFENCE ~ NOP
,但这并不意味着MFENCE ~ SFENCE
。我故意使用等价(〜)而非等号(=)来强调算术规则不适用于此处。 SFENCE
和LFENCE
的互作用使两者有所不同。即使负载没有相互重新排序,也需要使用LFENCE
来防止使用SFENCE
对负载进行重新排序。(*)仍然可以说
MFENCE
比其他两个篱笆的组合要强。特别是,英特尔手册第2卷中的CLFLUSH
指令说明说:“CLFLUSH
仅由MFENCE
指令排序。不能保证由任何其他防护或序列化指令或其他CLFLUSH
指令排序。”(更新后,
clflush
现在被定义为严格排序的(就像普通商店一样,因此,如果您想阻止以后的加载,则只需要mfence
即可),但是clflushopt
的排序很弱,但是可以被sfence
围起来。)关于assembly - 在x86/x86_64处理器上使用LFENCE指令有意义吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20316124/