我的代码很简单,如下所示。我找到了用于读写的rmb和wmb ,但没有找到通用的。lwsync在 PowerPC 上可用,但是 x86 的替代品是什么?提前谢谢。
#define barrier() __asm__ volatile ("lwsync")
...
lock()
if(!pInst);
{
T* temp=new T;
barrier();
pInst=temp;
}
unlock();
我的代码很简单,如下所示。我找到了用于读写的rmb和wmb ,但没有找到通用的。lwsync在 PowerPC 上可用,但是 x86 的替代品是什么?提前谢谢。
#define barrier() __asm__ volatile ("lwsync")
...
lock()
if(!pInst);
{
T* temp=new T;
barrier();
pInst=temp;
}
unlock();
rmb()
和 wmb() 是 Linux 内核函数。还有mb()
.
x86 指令是lfence
、、sfence
和mfence
、IIRC。
Cilk 运行时中有一个您可能会感兴趣的特定文件,即 cilk-sysdep.h,其中包含系统特定的映射 wrt 内存屏障。我在 x86 即 i386 上提取了一小部分关于你的问题
文件:-- cilk-sysdep.h(LHS 上的数字实际上是行号) 252 * 我们使用 xchg 指令序列化内存访问,可以 253 * 根据英特尔架构软件开发人员的规定完成 254 * 手册,第 3 卷:系统编程指南 255 * (http://www.intel.com/design/pro/manuals/243192.htm),第 7-6 页, 256 * "对于 P6 系列处理器,锁定操作序列化所有 257 * 未完成的加载和存储操作(即等待它们 258 * 完成)。” xchg 指令是一个锁定操作 259 * 默认值。请注意,推荐的内存屏障是 cpuid 260 * 指令,这真的很慢(约 70 个周期)。相比之下, 261 * xchg 大约只有 23 个周期(每个写缓冲区加上几个 262 *条目?)。仍然很慢,但我能找到最好的。-KHR 263 * 264 * Bradley 也为“mfence”计时,并且在 Pentium IV xchgl 上仍然相当快 265 * mfence 在 2.5GHZ P4 上似乎需要大约 125 ns 266 * xchgl 在 2.5GHZ P4 上大约需要 90 ns 267 * 然而,在 opteron 上,mfence 和 xchgl 的性能都*好得多*。 268 * mfence 在 1.5GHZ AMD64 上需要 8ns(也许这是 801) 269 * sfence 需要 5ns 270 * lfence 需要 3ns 271 * xchgl 需要 14ns 第272章 *见mfence-benchmark.c 273 */ 第274章 275 __asm__ 易失性(“xchgl %0,%1”:“=r”(x):“m”(y),“0”(x):“内存”); 第276章
我喜欢这一点的事实是 xchgl 似乎更快:) 尽管您应该真正实现它们并检查一下。
您没有确切说明此代码中的锁定和解锁是什么。我假设它们是互斥操作。在 powerpc 上,互斥获取函数将使用 isync(没有它,硬件可能会在 lock() 之前评估您的 if (!pInst)),并且会在 unlock() .
因此,假设您对 pInst 的所有访问(读取和写入)都受到您的锁定和解锁方法的保护,那么您使用屏障是多余的。解锁将具有足够的屏障以确保在解锁操作完成之前 pInst 存储是可见的(以便在任何后续锁获取后它都是可见的,假设使用相同的锁)。
在 x86 和 x64 上,您的 lock() 将使用某种形式的 LOCK 前缀指令,该指令自动具有双向屏蔽行为。
你在 x86 和 x64 上的解锁只需要一个存储指令(除非你在你的 CS 中使用一些特殊的字符串指令,在这种情况下你需要一个 SFENCE)。
手册:
有关于所有栅栏的良好信息以及 LOCK 前缀的效果(以及何时暗示)。
附言。在你的解锁代码中,你还必须有一些强制编译器排序的东西(所以如果它只是一个存储零,你还需要像 GCC 风格asm _ volatile _ ( "" ::: "memory" ) )。