ARM STLR 内存排序语义
ARM STLR memory ordering semantics
我正在努力解决 ARM STLR 的确切语义问题。
根据文档,它具有发布语义。所以如果你有 STLR 商店,你会得到:
[StoreStore][LoadStore]
X=r1
其中X
是内存,r1
是一些寄存器。
问题是发布存储和获取负载无法提供顺序一致性:
[StoreStore][LoadStore]
X=r1
r2=Y
[LoadLoad][LoadStore]
在上述情况下,允许重新排序 X=r1 和 r2=Y。为了使这个顺序一致,需要添加一个[StoreLoad]:
[StoreStore][LoadStore]
X=r1
[StoreLoad]
r2=Y
[LoadLoad][LoadStore]
而且您通常在店内这样做,因为进货频率更高。
在 X86 上,普通存储是发布存储,普通加载是获取加载。 [StoreLoad] 可以通过 MFENCE 或使用 LOCK ADDL %(RSP),0
实现,就像在 Hotspot JVM 中所做的那样。
看ARM的文档,好像LDAR已经获得了语义;所以那将是 [LoadLoad][LoadStore].
但 STLR 的语义含糊不清。当我使用 memory_order_seq_cst 编译 C++ atomic 时,只有一个 STLR;没有 DMB。因此,STLR 似乎比发布存储具有更强的内存排序保证。对我来说,似乎在栅栏级别上,STLR 相当于:
[StoreStore][LoadStore]
X=r1
[StoreLoad]
有人能解释一下吗?
我只是在学习这方面的知识,所以请持保留态度。但我的理解是,在 ARMv8/AArch64 中,STLR/LDAR
确实提供了超出 release/acquire 的通常定义的额外语义,但不如你的建议那么强烈。也就是说,发布存储 STLR
确实与按程序顺序跟随它的获取加载 LDAR
具有顺序一致性,但与普通 LDR
加载不一致。
摘自 ARMv8 体系结构参考手册,B2.3.7,“Load-Acquire、Load-AcquirePC 和 Store-Release”:
Where a Load-Acquire appears in program order after a Store-Release, the memory access generated by the
Store-Release instruction is Observed-by each PE to the extent that PE is required to observe the access coherently,
before the memory access generated by the Load-Acquire instruction is Observed-by that PE, to the extent that the
PE is required to observe the access coherently.
从 B2.3.2 开始,“排序关系”:
A read or a write RW1 is Barrier-ordered-before a read or a write RW2 from the
same Observer if and only if RW1 appears in program order before RW2 and any of the following
cases apply: [...] RW1 is a write W1 generated by an instruction with Release semantics and RW2 is a read R2
generated by an instruction with Acquire semantics.
作为测试,我借用了. With clang 11.0 on godbolt,可以看到即使要求顺序一致性,编译器还是会生成STLR, LDAR
拿锁(汇编第18-19行) , 没有 DMB
。我 运行 使用了一段时间(Raspberry Pi 4B,Cortex A72,4 核)并且没有违规。
然而,与您的想法相反,STLR
仍然可以针对其后的普通(非获取)加载进行重新排序,因此它不会隐含地具有完整的 StoreLoad 栅栏。我修改了 LWimsey 的程序,改为使用 STLR, LDR
,在添加了一些额外的垃圾来引发竞争后,我能够看到锁定违规。
同样,LDAR
可以针对其之前的普通(非发行)商店重新排序。我同样能够在测试程序中使用 STR, LDAR
获得锁冲突。
我正在努力解决 ARM STLR 的确切语义问题。
根据文档,它具有发布语义。所以如果你有 STLR 商店,你会得到:
[StoreStore][LoadStore]
X=r1
其中X
是内存,r1
是一些寄存器。
问题是发布存储和获取负载无法提供顺序一致性:
[StoreStore][LoadStore]
X=r1
r2=Y
[LoadLoad][LoadStore]
在上述情况下,允许重新排序 X=r1 和 r2=Y。为了使这个顺序一致,需要添加一个[StoreLoad]:
[StoreStore][LoadStore]
X=r1
[StoreLoad]
r2=Y
[LoadLoad][LoadStore]
而且您通常在店内这样做,因为进货频率更高。
在 X86 上,普通存储是发布存储,普通加载是获取加载。 [StoreLoad] 可以通过 MFENCE 或使用 LOCK ADDL %(RSP),0
实现,就像在 Hotspot JVM 中所做的那样。
看ARM的文档,好像LDAR已经获得了语义;所以那将是 [LoadLoad][LoadStore].
但 STLR 的语义含糊不清。当我使用 memory_order_seq_cst 编译 C++ atomic 时,只有一个 STLR;没有 DMB。因此,STLR 似乎比发布存储具有更强的内存排序保证。对我来说,似乎在栅栏级别上,STLR 相当于:
[StoreStore][LoadStore]
X=r1
[StoreLoad]
有人能解释一下吗?
我只是在学习这方面的知识,所以请持保留态度。但我的理解是,在 ARMv8/AArch64 中,STLR/LDAR
确实提供了超出 release/acquire 的通常定义的额外语义,但不如你的建议那么强烈。也就是说,发布存储 STLR
确实与按程序顺序跟随它的获取加载 LDAR
具有顺序一致性,但与普通 LDR
加载不一致。
摘自 ARMv8 体系结构参考手册,B2.3.7,“Load-Acquire、Load-AcquirePC 和 Store-Release”:
Where a Load-Acquire appears in program order after a Store-Release, the memory access generated by the Store-Release instruction is Observed-by each PE to the extent that PE is required to observe the access coherently, before the memory access generated by the Load-Acquire instruction is Observed-by that PE, to the extent that the PE is required to observe the access coherently.
从 B2.3.2 开始,“排序关系”:
A read or a write RW1 is Barrier-ordered-before a read or a write RW2 from the same Observer if and only if RW1 appears in program order before RW2 and any of the following cases apply: [...] RW1 is a write W1 generated by an instruction with Release semantics and RW2 is a read R2 generated by an instruction with Acquire semantics.
作为测试,我借用了STLR, LDAR
拿锁(汇编第18-19行) , 没有 DMB
。我 运行 使用了一段时间(Raspberry Pi 4B,Cortex A72,4 核)并且没有违规。
然而,与您的想法相反,STLR
仍然可以针对其后的普通(非获取)加载进行重新排序,因此它不会隐含地具有完整的 StoreLoad 栅栏。我修改了 LWimsey 的程序,改为使用 STLR, LDR
,在添加了一些额外的垃圾来引发竞争后,我能够看到锁定违规。
同样,LDAR
可以针对其之前的普通(非发行)商店重新排序。我同样能够在测试程序中使用 STR, LDAR
获得锁冲突。