【问题标题】:Understanding cmpxchg8b/cmpxchg16b operation了解 cmpxchg8b/cmpxchg16b 操作
【发布时间】:2020-07-29 23:13:59
【问题描述】:

该指令的 SDM 文本具有以下块:

该指令可以与 LOCK 前缀一起使用,以允许指令以原子方式执行。为了简化界面 处理器的总线,目标操作数接收一个写周期 不考虑比较结果。目的地 如果比较失败,则写回操作数;否则,源 操作数被写入目的地。

我很难理解最后一句话(但也可能是整个段落)

  • The destination operand is written back ... 回什么?
  • ...;otherwise, the source operand is written into the destination 源操作数是什么?是ECX:EBX 吗?据我了解,这条 CAS 指令只需要一个操作数(内存目标)。

如果有人可以改写和/或解释有关无条件写入的这一点,将不胜感激。

【问题讨论】:

  • "如果比较失败,则将目标操作数的先验值写回到目标;否则,将源操作数写入目的地。”
  • 引用指令的列出方式可能很有用,以便清楚源操作数和目标操作数的含义。它可能在页面上的其他地方进行了解释。例如,Felix Cloutier's version 包含语句“将 EDX:EAX 中的 64 位值(或 RDX:RAX 中的 128 位值,如果操作数大小为 128 位)与操作数(目标操作数 )。”因此,赋予指令的显式操作数被认为是目标操作数。

标签: assembly x86-64 intel instructions compare-and-swap


【解决方案1】:

与常规cmpxchg r/m32, r32 的措辞(具有显式而不是隐式来源)相比,它应该更有意义,尤其是比较手动输入顶部表格中的简短描述。我已经用 dst、src 和隐式进行了注释。请注意,Intel 语法一般为op dst, src

  • cmpxchg r/m64, r64:比较 RAX (implicit) 和 r/m64 (dst)。如果相等,则设置 ZF 并将 r64 (src) 加载到 r/m64 (dst) 中。否则,清除 ZF 并将 r/m64 (dst) 加载到 RAX (implicit)

  • cmpxchg16b m128 比较 RDX:RAX 和 m128 (dst)。如果相等,则设置 ZF 并将 RCX:RBX 加载到 m128 (dst) 中。否则,清除 ZF 并将 m128 加载到 RDX:RAX。

是的,没错,英特尔的手册使用“加载”来描述存储到内存。 (对于cmpxchg,目标可以是一个寄存器,这有点合理,对于cmpxchg16b,根本不是。)

但无论如何,记住这些实现会有所帮助:

m64.compare_exchange_strong(expected=RAX, desired=r64);
m128.compare_exchange_strong(expected=RDX:RAX, desired=RCX:RBX);

(就 C++ std::atomic 而言。要真正成为原子,它们需要 lock 前缀,否则它是非原子 RMW。C++ 只会编译为 lock cmpxchg / lock cmpxchg16b,永远不会是 un-与主流编译器锁定cmpxchg。)

目标操作数被写回...回什么?

目标的旧值(刚刚加载)被写回。这意味着cmpxchg16b总是是一个写操作,例如始终将页面的脏标志标记为脏。 (Does cmpxchg write destination cache line on failure? If not, is it better than xchg for spinlock? 询问它是否真的在 CAS 故障时在微架构上弄脏了缓存行。我假设是这样,但尚未检查。)

这对于旧 CPU 上的 lock 前缀在历史上很重要,其中有一个外部 LOCK# 引脚,lock cmpxchg 实际上为整个加载+存储对断言。现代 CPU 只是在持续时间内保持受影响缓存行上的缓存锁,用于可缓存内存上的对齐锁 CAS。这就是为什么手册说“为了简化与处理器总线的接口,目标操作数接收一个写周期而不考虑比较结果。


如果比较失败,则写回目标操作数;否则,源操作数被写入目标。 (处理器不会在不产生锁定写入的情况下产生锁定读取。)

整个段落是在英特尔编写cmpxchg16b 条目时从cmpxchg 手动条目中复制粘贴的;在 CX16 上下文中不太清楚,因为它有 2 个隐式操作数,而不是显式源和读写 RAX。它没有定义术语“源操作数”。

在描述的前面,它确实为该指令定义了“目标操作数”术语

比较 EDX:EAX 中的 64 位值(或 RDX:RAX 中的 128 位值,如果操作数大小为 128 位)与操作数(目标操作数)

“操作数”表示显式操作数。这显然是什么意思,因为它是唯一可以作为记忆的东西,所以它必须是被比较的东西之一。还有其他线索/原因来自英语的运作方式等等。

所以“目标操作数”确实得到了明确定义,但是在一条总共有 3 个操作数的指令中,不定义它就说“源操作数”是很糟糕的。就像我说的那样,显然是英特尔文档作者复制/粘贴的结果。

这不是一个严重的问题;我们知道指令的基本点,操作部分可以 100% 清楚实际发生的情况。

【讨论】:

    猜你喜欢
    • 2019-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-17
    • 2011-06-15
    • 2011-12-23
    • 2014-08-28
    • 1970-01-01
    相关资源
    最近更新 更多