我实现了一个引用计数模式,为此我需要互锁设施,但没有内存围栏(据我所知)。
不幸的是,只有 Windows 具有 InterlockedDecrementNoFence 编译器内在函数。我如何使用 asm 内联来做到这一点?我也需要这个用于 gcc/clang。
我实现了一个引用计数模式,为此我需要互锁设施,但没有内存围栏(据我所知)。
不幸的是,只有 Windows 具有 InterlockedDecrementNoFence 编译器内在函数。我如何使用 asm 内联来做到这一点?我也需要这个用于 gcc/clang。
这不是一个直接的答案,而是一个替代建议。如果你可以使用 C11(或 C++11),那么原子操作memory_order_relaxed
呢?您的编译器可能不会在弱内存模型平台上生成内存栅栏。(这取决于编译器供应商/版本)
#include <stdatomic.h>
atomic_int var;
int oldval;
oldval = atomic_fetch_sub_explicit(&var, 1, memory_order_relaxed);
对于该操作的语义而言,缺少至少一个内在的内存栅栏操作(取决于平台)几乎是不可能的。为了使原子递增/递减工作,其他处理器必须保证在对变量执行自己的操作之前看到原子操作的值,并且对变量的操作的可见性必须有一定的保证总数命令。内存屏障,即使是像 x86 这样标准内存操作具有获取/释放语义的强内存模型中的隐式屏障,对于原子递增/递减操作的正确性也是至关重要的。
请记住,即使 MSVC/gcc 的文档说存在内存屏障,由于平台的强内存模型,在 x86 上也不会应用实际的内存屏障(即MFENCE
指令),而是内存总线上的锁,以确保操作的原子性。另一方面,IA64 需要内存屏障,因为该平台的内存模型较弱。ARM 也是如此。