x86 - 为什么 “movnti” 后跟一个 “sfence” 保证持久排序?

标签 x86 cpu-architecture memory-barriers persistent-memory

SFENCE prevents NT stores from committing from the store buffer ahead of SFENCE itself.

NT store data enters an LFB directly from the store buffer.

因此SFENCE只能保证进入LFB的数据的顺序。

例如,

movnti;
sfence;
movnti to another address;

这里的SFENCE只能保证第一个NT store会比下一个先commit到LFB。但是,由于 LFB 是 volatile 的,因此数据尚未持久化。进入LFB的数据会按照进入顺序持久化吗?

最佳答案

sfence 确保程序顺序中所有较早的存储在程序顺序中的任何较晚存储变得全局可观察之前变得全局可观察。这里的存储包括数据存储 uops、clflushclflushoptclwbmovdirimovdir64b.

GO 的点数取决于以下所有内容:

  • 操作类型,
  • 非时间暗示的存在,
  • 目标内存位置的内存类型,
  • 映射到目标内存地址的设备,以及
  • 微架构。

例如,在现代 Intel 服务器处理器上,当从内存中获取目标缓存行(如果尚未存在于L1D 处于合适的一致性状态并且存储被提交到缓存。这就是为什么在 Intel CSX 等异步 DRAM 刷新 (ADR) 平台上,sfence 本身并不能保证持久性。

关于您询问的具体示例,movnti 是带有 NT 提示的数据存储指令。假设目标地址映射到 ADR 平台上的主内存,则该指令的全局可观察点与持久域的第一个点相同。因此,在具有 NVDIMM 的任何 Intel 或 AMD 平台上,无论内存类型如何,数据都保证在任何后续存储变为持久化之前位于持久化域中。这比你说的(sfence 防止后面的存储在前面的存储之前提交)更有保障,因为提交并不意味着持久化,但持久化只能发生在提交之后。虽然在这里使用术语“退出”而不是“提交”可能更好,因为“退出”在架构上是有意义的并且表示更改线程的状态,但“提交”是微架构操作并且取决于设计。

关于x86 - 为什么 “movnti” 后跟一个 “sfence” 保证持久排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65826035/

相关文章:

caching - L1、L2 和 L3 缓存如何与多个并发运行的进程配合使用?

c - 以编程方式查找缓存级别的数量

c++ - 在 C++ 中,加载是否可以在获取操作下方滑动/存储可以在释放上方 float 吗?

c++ - 在C++11中如何表达普通的存储(导出)和加载(导入)屏障(fence)?

assembly - 从MIPS切换到x86组装时我应该知道什么?

assembly - 最初的 16 位 x86 中是否有 8 位内存寻址?

c++ - 如何在 VS C++ 中使用 IA32 指令 'fabs'?

c++ - 对返回前仅对 EAX 的低字节进行异或运算的虚方法进行逆向工程

c - linux 内核的 ext2 函数 ext2_statfs() 中的内存屏障

c - 是否可以只在存储端使用内存屏障