【问题标题】:How does "XORL AX, AX" work as a memory fence? [duplicate]“XORL AX, AX”如何作为记忆栅栏工作? [复制]
【发布时间】:2019-10-07 13:40:17
【问题描述】:

最近我一直在浏览 Go 的源代码,尤其是 runtime/internal/atomic/asm_386.s。 下面是一个internal.atomic.Store64 函数的实现。

// void runtime∕internal∕atomic·Store64(uint64 volatile* addr, uint64 v);
TEXT runtime∕internal∕atomic·Store64(SB), NOSPLIT, $0-12
    MOVL    ptr+0(FP), AX
    TESTL   $7, AX
    JZ  2(PC)
    MOVL    0, AX // crash with nil ptr deref
    // MOVQ and EMMS were introduced on the Pentium MMX.
    MOVQ    val+4(FP), M0
    MOVQ    M0, (AX)
    EMMS
    // This is essentially a no-op, but it provides required memory fencing.
    // It can be replaced with MFENCE, but MFENCE was introduced only on the Pentium4 (SSE2).
    XORL    AX, AX
    LOCK
    XADDL   AX, (SP)
    RET

问题与函数中的第二条评论有关。有人能解释一下XORL AX, AX 是如何作为记忆栅栏工作的吗?

我想这与紧随其后的LOCK 有关,但它是如何工作的?

谢谢。

【问题讨论】:

  • 这很愚蠢,普通人使用lock addl $0, (SP) 作为 MFENCE 的(有时更快)等价物。另一个效率低下是使用testl 而不是testb 来检查EAX 的低位:没有test r32, imm8 编码所以它浪费了几个字节的代码大小。
  • 另外,如果我需要避免 SSE2,我会使用 fild / fistp 而不是需要 MMX EMMS。或 SSE1 movlps 加载/存储到 xmm0,尽管与 SSE2 movqmovsd 加载到 xmm0 相比,它具有错误的依赖性。而且我会在 ret 之后放置崩溃时未对齐负载,因此在正常情况下不会采用分支。

标签: multithreading go assembly parallel-processing x86


【解决方案1】:

不是 XOR 充当了记忆栅栏。执行此操作的是锁定的 XADD 指令。 XOR 指令清除 EAX 以便 XADD 指令实际上不会改变内存的内容。

锁定指令的内存排序行为在此问题的答案中有所描述:How many memory barriers instructions does an x86 CPU have?

【讨论】:

    猜你喜欢
    • 2011-11-08
    • 2020-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多