multithreading - 锁定指令是否在弱顺序访问之间提供了障碍?

标签 multithreading x86 intel memory-model memory-fences

在 x86 上,lock - 前缀指令,例如 lock cmpxchg除了原子操作之外,还提供屏障语义:对于回写内存区域的正常内存访问,读取和写入不会跨 lock 重新排序。 - 前缀说明,根据英特尔 SDM 第 3 卷第 8.2.2 节:

Reads or writes cannot be reordered with I/O instructions, locked instructions, or serializing instructions.



本节仅适用于回写存储器类型。在同一个列表中,您会发现一个异常(exception),它指出弱排序的商店没有被排序:

  • Reads are not reordered with other reads.
  • Writes are not reordered with older reads.
  • Writes to memory are not reordered with other writes, with the following exceptions: —

    streaming stores (writes) executed with the non-temporal move instructions (MOVNTI, MOVNTQ, MOVNTDQ, MOVNTPS, and MOVNTPD); and —

    string operations (see Section 8.2.4.1).



  • 请注意,列表中任何其他项目中的非临时指令没有异常(exception),例如,在引用锁定前缀指令的项目中。

    在指南的其他各个部分中,提到了 mfence和/或 sfence当使用弱排序(非时间)指令时,指令可用于对内存进行排序。这些部分一般不提lock - 前缀指令作为替代。

    所有让我不确定的事情:做 lock - 前缀指令提供与 mfence 相同的完整屏障在 WB 内存上提供弱排序(非时间)指令?同样的问题再次适用,但适用于对 WC 内存的任何类型的访问。

最佳答案

在所有 64 位 AMD 处理器上,MFENCE是一个完全序列化的指令,而锁定前缀的指令则不是。但是,两者都根据 AMD 手册 V2 7.4.2 序列化所有内存访问:

All previous loads and stores complete to memory or I/O space before a memory access for an I/O, locked or serializing instruction is issued.

All loads and stores associated with the I/O and locked instructions complete to memory (no buffered stores) before a load or store from a subsequent instruction is issued.



没有与这些指令的序列化属性相关的异常(exception)或错误。

从英特尔手册和文档中可以清楚地看出,它们都将所有存储序列化,没有异常(exception)或相关错误。 MFENCE还序列化了所有负载,其中记录了大多数基于 Skylake、Kaby Lake 和 Coffee Lake 微体系结构的处理器的勘误表,其中指出 MOVNTDQA来自 WC 内存可能更早通过 MFENCE指示。此外,许多基于 Nehalem、Sandy Bridge、Ivy Bridge、Haswell、Broadwell、Skylake、Kaby Lake、Coffee Lake 和 Silvermont 微架构的处理器都有一个勘误表,上面写着 MOVNTDQA来自 WC 内存的数据可能会传递更早的锁定指令。基于 Core、Westmere、Sunny Cove 和 Goldmont 微体系结构的处理器没有此勘误表。

引用 Necrolis 的回答说,锁定前缀可能不会序列化引用 Pentium 4 处理器上弱排序内存类型的加载操作。我的理解是,这看起来像是奔腾 4 处理器中的一个错误,它不适用于任何其他处理器。虽然值得注意的是,它没有记录在奔腾 4 处理器的规范更新文档中。

@PeterCordes 的 experiments表明,在 Skylake 上,锁定指令似乎并没有阻止 ALU 指令在 mfence 时乱序执行。确实序列化 ALU 指令(可能与 lfence 的行为相同 + 像锁定指令一样的存储缓冲区刷新)。但是,我认为这是一个实现细节。

关于multithreading - 锁定指令是否在弱顺序访问之间提供了障碍?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50280857/

相关文章:

c++ - MFC C++ 在回调函数中编辑 Windows 控件

c# - 为什么 Thread.Sleep(0) 时间片处理优先级较低的线程?

assembly - 程序在奇怪的情况下崩溃

iphone - 如何在 iPhone 上访问 safari、facebook 等应用程序的远程连接请求

java - 在Thread内创建一个service或者在Service内创建一个service

assembly - #define 汇编中的替代方案?

assembly - 在 ds 中移动 0x18 后,QEMU 寄存器和 eip 被破坏

linux - 并行程序给出错误 "Undefined reference to _Kmpc_ok_to_fork"

linux - 调用 clCreateContext 时报错 CL_DEVICE_NOT_AVAILABLE (Intel Core2Duo, Intel OCL SDK 3.0 beta)

android - 启用英特尔虚拟化技术