似乎接受和释放语义的公认定义是这样的:(引自http://msdn.microsoft.com/en-us/library/windows/hardware/ff540496(v=vs.85).aspx

如果其他处理器在任何后续操作的效果之前始终看到其效果,则操作已获取语义。 如果其他处理器在操作本身的影响之前将看到每个先前操作的效果,则操作具有释放语义。

我已经简要地阅读了半存储障碍的存在,并且据说它们具有获取障碍和释放障碍的风格,遵循上述相同的语义。

查看硬件指令的真实示例我遇到了SFENCE。 此博客( http://peeterjoot.wordpress.com/2009/12/04/intel-memory-ordering-fence-instructions-and-atomic-operations/ )表示它是一种释放栅栏/屏障:

英特尔提供双向围栏指令MFENCE,获取围栏LFENCE和释放围栏SFENCE。

但是,阅读SFENCE的定义,它似乎没有提供发布语义,因为它根本不与负载同步? 而我所理解的释放语义定义了关于所有内存操作(加载和存储)的排序。

===============>>#1 票数:20 已采纳

LFENCE没有获得语义; SFENCE没有发布语义。 这有一个很好的理由:拥有一个带有获取语义或释放语义的独立fence指令,结果几乎完全没用。 为了获得/释放任何好处,它必须与内存操作相关联。

例如,考虑在两个线程之间发送数据的常用习惯用法:

  1. 处理器A写入缓冲区。
  2. 处理器A将“true”写入标志。
  3. 处理器B等待,直到标志为真。
  4. 处理器B读取缓冲区。

请注意,处理器A必须确保写入缓冲区才能看到对该标志的写入。 现在假设我们有一个“RFENCE”指令,它是一个释放围栏。 如果我们在步骤(1)之后立即执行该指令,则没有任何好处,因为允许步骤2中的写入在RFENCE上向上迁移并在步骤1中向上迁移。

类似的论点表明,执行获取的“AFENCE”指令同样无用于确保步骤3中的标志读取似乎不会在步骤4中向下迁移。

Itanium通过提供write-with-release和load-with-acquire指令将范围与内存操作联系起来,从而优雅地解决了这个问题。

回到IA-32和Intel64: 如果程序不使用“非时间”指令,则其余指令的行为就好像每个负载都执行“获取”并且每个存储都执行“释放”。 请参阅英特尔®64和IA-32架构开发人员手册:Vol。第8.2.3节(和小节) 3A 如果涉及“非临时”商店,您可以通过多种方式强制执行范围:

  • 使用SFENCE
  • 使用MFENCE - 有点矫枉过正
  • 使用LOCK前缀指令(例如“LOCK INC”)写入标志。 LOCK前缀指令隐式具有MFENCE。
  • 使用XCHG(就像它具有隐式LOCK前缀一样)来写入标志。

例如,如果在较早的习语中,缓冲区是使用非临时存储编写的,则处理器A在步骤1和2之间发出SFENCE或MFENCE。或者使用XCHG写入标志。

以上所有评论均适用于硬件。 使用高级语言时,请确保编译器不会损坏事件的关键顺序。 存在C ++ 11原子操作库,以便您可以告诉编译器硬件您想要什么。

  ask by ryaner translate from so

未解决问题?本站智能推荐: