我正在查看来自 gcc 的 rmw 原子的编译器输出,并注意到一些奇怪的东西 - 在 Aarch64 上,诸如 fetch_add 之类的 rmw 操作可以在宽松的负载下部分重新排序。
在 Aarch64 上,可能会为以下代码生成 value.fetch_add(1, seq_cst)
.L1:
ldaxr x1, [x0]
add x1, x1, 1
stlxr w2, x1, [x0]
cbnz L1
Run Code Online (Sandbox Code Playgroud)
但是,在 ldaxr 之前发生的加载和存储可能会被重新排序,超过 stlxr 之后发生的加载和加载/存储(请参阅此处)。GCC 不会添加围栏来防止这种情况发生 - 这里有一小段代码演示了这一点:
void partial_reorder(std::atomic<uint64_t> loader, std::atomic<uint64_t> adder) {
loader.load(std::memory_order_relaxed); // can be reordered past the ldaxr
adder.fetch_add(1, std::memory_order_seq_cst);
loader.load(std::memory_order_relaxed); // can be reordered past the stlxr
}
Run Code Online (Sandbox Code Playgroud)
生成
partial_reorder(std::atomic<int>, std::atomic<int>):
ldr w2, [x0] @ reordered down …Run Code Online (Sandbox Code Playgroud)