golang 原子操作

发布时间 2023-11-22 21:26:38作者: _小孟同学

在 golang 中,有原子包,能够实现原子操作,在我分析和猜想下,感觉解开了谜团
具体用法不说了,网上一大堆什么 cas,add,load,store 等,主要是底层实现

arm 架构

在 amd 架构下,通过汇编指令加锁来实现

代码在src/runtime/internal/atomic/atomic_amd64.s

// uint64 Xadd64(uint64 volatile *val, int64 delta)
// Atomically:
//	*val += delta;
//	return *val;
TEXT ·Xadd64(SB), NOSPLIT, $0-24
	MOVQ	ptr+0(FP), BX
	MOVQ	delta+8(FP), AX
	MOVQ	AX, CX
	LOCK
	XADDQ	AX, 0(BX)
	ADDQ	CX, AX
	MOVQ	AX, ret+16(FP)
	RET

可以看到在执行 XADDQ 命令之前,先进行 LOCK 加锁把内存地址锁住,然后执行下面的操作

amd 架构

在 arm 架构下,似乎没看到 LOCK 指令

src/runtime/internal/atomic/atomic_arm64.s

// uint64 Xadd64(uint64 volatile *ptr, int64 delta)
// Atomically:
//      *val += delta;
//      return *val;
TEXT ·Xadd64(SB), NOSPLIT, $0-24
	MOVD	ptr+0(FP), R0
	MOVD	delta+8(FP), R1
	MOVBU	internal∕cpu·ARM64+const_offsetARM64HasATOMICS(SB), R4
	CBZ 	R4, load_store_loop
	LDADDALD	R1, (R0), R2
	ADD 	R1, R2
	MOVD	R2, ret+16(FP)
	RET
load_store_loop:
	LDAXR	(R0), R2
	ADD	R2, R1, R2
	STLXR	R2, (R0), R3
	CBNZ	R3, load_store_loop
	MOVD	R2, ret+16(FP)
	RET

在 arm 架构下没有了 LOCK 指令,但是用到了 MOVBU internal∕cpu·ARM64+const_offsetARM64HasATOMICS(SB), R4 这个命令,虽然没查到怎么用,但是看变量命令,可以理解是将原子位置一个值再操作

参考

原子操作与 x86 上的 lock 指令前缀