4

我对 x86 上的顺序一致的加载操作很感兴趣。

据我从汇编程序列表中看到的,由编译器生成它是作为 x86 上的普通加载实现的,但是据我所知,普通加载保证具有获取语义,而普通存储保证具有释放。

顺序一致的存储实现为锁定的 xchg,而加载为普通加载。这听起来很奇怪,你能详细解释一下吗?

添加

刚刚在互联网上发现,只要使用锁定的 xchg 完成存储,就可以像简单的 mov 一样完成顺序一致的原子加载,但是没有证据,也没有文档链接。

4

3 回答 3

10

x86 上的 plainMOV对于原子顺序一致的加载就足够了,只要 SC 存储使用LOCKed 指令完成,值正确对齐,并且使用“正常”WB缓存模式。

有关完整映射,请参阅我在http://www.justsoftwaresolutions.co.uk/threading/intel-memory-ordering-and-c++-memory-model.html上的博客文章,以及在http://developer上的英特尔处理器文档.intel.com/products/processor/manuals/index.htm了解允许订购的详细信息。

如果您使用“WC”缓存模式或“非临时”指令,MOVNTI那么所有的赌注都将被取消,因为处理器不一定会及时将数据写回主存。

于 2011-06-27T16:04:33.640 回答
2

x86 上的读取本质上是原子的,只要它们对齐,MOVintel assembly manuals vol 2A 中的说明下的部分应该提到这一点,与LOCK前缀相同。其他卷也可能提到这一点

但是,如果你想要一个atomic read,你可以使用_InterlockedExchangeAdd((LONG*)&var,0)aka LOCK XADD,这将产生旧值,但不会改变它的值,同样可以用InterlockCompareExchange((LONG*)&var,var,var)aka完成LOCK CMPXCHG,但是 IMO,不需要这个

于 2011-02-17T07:30:06.400 回答
1

寄存器到内存的传输(反之亦然)在多处理器环境中不一定是原子的。

阅读

XOR EAX, EAX
LOCK XADD [address], EAX

第一条指令将 EAX 寄存器归零,第二条指令将两个 EAX 的内容与 [address] 交换,并将两者的总和再次存储在 [address] 中。由于之前 EAX 寄存器为零,因此没有任何变化。

写作

XCHG [address], EAX

EAX 寄存器将获取值存储到指定地址。

编辑: LOCK ADD EAX, [address] 将导致“无效操作码异常”,因为目标操作数不是内存地址。

当 LOCK 前缀与任何其他指令一起使用或未对内存进行写操作时,将生成无效操作码异常 (#UD)。8.1.2.2 软件控制的总线锁定

编辑 2:总结评论中的信息。

尽管

“[...] 处理器的锁定协议在交换操作期间自动实现,无论是否存在 LOCK 前缀或 IOPL 的值。”

对此有限制

“对跨总线宽度、缓存行和页面边界的可缓存内存的访问不能保证是原子的”

于 2011-02-16T14:53:26.920 回答