为什么 MESI 协议不能保证没有 LOCK 前缀的 x86 上 CMPXCHG 的原子性?

Why can the MESI protocol not guarantee atomicity of CMPXCHG on x86 without the LOCK prefix?

我了解 MESI 协议成功地保证了不同内核的内存(缓存)视图相同。我的问题来自这样一个事实,即在编写过程中,MESI 保证缓存由 CPU 独占,然后原子 CMPXCHG 只是原子地比较和交换值。那么,当我们已经从 MESI 协议获得保证时,为什么我们需要使用 LOCK 指令并因此锁定缓存行?

atomic CMPXCHG just compares and exchanges values atomically

不,缓存访问硬件不会将 CMPXCHG 实现为单周期固有原子操作。它是由加载和单独存储的多个 uops 合成的。

如果 这就是常规 CMPXCHG 的工作方式,那么您的推理就是正确的。但是常规 CMPXCHG 是 不是 原子的(对于其他内核上的观察者)。


lock cmpxchg 解码为多个 uops,使缓存行 "locked" 从加载到存储,将其变成系统中任何其他观察者可以看到的单个原子事务. (即延迟响应 MESI 无效或共享该行的请求,直到商店提交之后)。这也使它成为一个完整的内存屏障。


没有lock,CMPXCHG 解码为加载的多个微指令,检查是否相等,然后根据比较结果存储或不存储新值。 就原子性而言,它与 add [mem], edx 相同,后者使用 ALU 在加载和存储微指令之间进行加法运算。即它是 不是 原子的,除了关于中断在同一个内核上(因为中断只能发生在指令边界)。

加载和存储各自单独原子,但它们不是单个原子 RMW 事务。如果另一个核心使我们的无效缓存行的副本并在我们的负载和我们的商店之间存储一个新值,我们的商店将踩到另一个商店。并且其他存储将出现在我们加载和存储之间的缓存行上的全局操作顺序中,这违反了 "atomic" = indivisible.

的定义
  • 为什么 add [mem], edx 不是原子的,以及 lock 如何使它成为原子的。
  • cmpxchg 没有 lock 的用例:单处理器机器。