Recently I've been browsing through Go's source code and in particular runtime/internal/atomic/asm_386.s.
Below is an implementation of an internal.atomic.Store64
function.
// 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
The question is related to the second comment in the function. Could someone explain how does XORL AX, AX
work as a memory fence?
I guess it has something to do with the LOCK
that goes right after, but how does it work?
Thank you.