0

根据 clwb 订购信息(链接),

" CLWB 指令仅按存储屏蔽操作排序。例如,软件可以使用 SFENCE、MFENCE、XCHG 或 LOCK 前缀指令来确保回写中包含以前的存储。CLWB 指令不需要按以下顺序排序_

如果 Intel X86-64 上的操作集如下所示,如果写入 (A) 和写入 (B) 是高速缓存行对齐的,我是否可以删除“ sfence ”并仍然确保正确性。

我问这个是因为在英特尔Write(A) 和 write(B)上是有序的 (TSO) 和write(A)->clwb(A)write(B)->clwb(B)是按照上面引用的描述排序的clwb _

write(A)
clwb(A)
sfence()
write(B)
clwb(B)

我正在做以下假设

  1. 编译器不会重新排序这些操作
  2. clwb() 指令将脏行写回到持久域,因此write(A)->clwb(A)对确保 A 的修改值在持久域中

请告诉删除sfence是否会破坏正确性?如果是,在什么情况下谢谢

4

1 回答 1

3

对于在同一缓存行中的 WB 内存的正常存储:是的持久性顺序匹配 x86-TSO 全局可观察性顺序,请参阅系统崩溃时 clflush 或 clflushopt 是否原子?</a>。否则不能保证。

似乎您的意思是 A 完全包含在一个缓存行中,而 B 完全包含在一个单独的缓存行中。

如果没有 SFENCE,崩溃后可能会看到 B 的效果,但不会看到 A。clwb没有排序,因此后者可以先使其存储持久化。这就是手册所指出的,因为 clwb 没有订购 wrt。正常的商店。

所以根据 TSO write(B) 发生意味着 write(A) 发生(可能是在存储缓冲区中)。

不,x86-TSO 排序是关于从存储缓冲区到 L1d(全局可观察性指针)的提交顺序。这当然与最终回写(通过驱逐或 clwb)到 DRAM 完全不同。存储微指令可以以任何顺序执行(将其地址+数据写入存储缓冲区),但直到退休后才能提交(即当它们是非推测性的时)。此外,该提交被限制在程序顺序中发生,即在发布/重命名/分配期间分配的顺序存储缓冲区条目。

意思是 write(A)->write(B) 是有序的并且 write(B)->clwb(B) 是有序的,那么 clwb(B) 如何绕过 write(B) [从而违反手册的顺序约束] 并发生在 clwb(A) 之前,从而导致 clwb(B) 在崩溃后可见而不是 clwb(A) 的效果?

不,“与旧存储隐式排序...到相同地址”规则仅保证存储 + clwb 到相同地址将写回包含该存储数据的行的版本。否则,它可能会在最新的存储仍在存储缓冲区中或什至未执行时写回该行的副本。这并不意味着整个回写必须在任何以后的存储之前完成!

崩溃后产生 B 但不可见 A 的操作顺序如下:

  • A 和 B 按某种顺序执行
  • 一旦这个核心拥有各自线路的 MESI 独占所有权,A 和 B 就会提交到 L1d 缓存,从而对其他核心全局可见。
  • clwb 指令在某个时间点执行,请求在存储提交后的某个时间点将高速缓存行写回 DRAM。
  • A 行的回写在它提交到 L1d 后的某个时间点开始,对于 B 行也是如此。它们可以以任一顺序开始,因为 clwb 的顺序不能保证 wrt。其他 clwb 操作到其他行,尽管在实践中它们可能program oder 开始。
  • clwb-B 完成持久化
  • 机器在飞行中的 clwb-A 进入持久域之前断电。您没有要求按 wrt 订购 clwb 操作。彼此,所以这是允许的。

在 asm 指令重新排序方面,允许以下重新排序:

 store A
 store B
 clwb  B
 clwb  A     ; not ordered wrt. store B or clwb B

当然,执行顺序与到达存储缓冲区的末尾与实际持久提交至少在理论上都是独立的事情,但是如果您想将其简化为在另一条指令的任何影响之前发生的指令的所有步骤,这重新排序仍然与所有规则兼容。

我认为您缺少的关键是 clwb A 是与商店 A 分开的操作,它不会一直坚持下去。该 clwb允许在其他以后的商店之后“发生”。store B 指向不同的地址,因此它不订购 clwb A。

SFENCE 可以防止这种情况。

于 2021-05-18T05:39:00.003 回答