我的代码很简单,如下所示。我找到了用于读写的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" ) )。