runtime/internal/atomic: add arm/arm64 operators for And/Or

For #61395
This commit is contained in:
Mauri de Souza Meneguzzo 2023-09-15 23:22:23 -03:00
parent 6458c8e45f
commit 8267665a03
4 changed files with 157 additions and 1 deletions

View file

@ -1,4 +1,4 @@
//go:build 386 || amd64 || ppc64 || ppc64le || riscv64 || wasm
//go:build 386 || amd64 || arm || arm64 || ppc64 || ppc64le || riscv64 || wasm
//
// Copyright 2023 The Go Authors. All rights reserved.

View file

@ -208,6 +208,66 @@ func And(addr *uint32, v uint32) {
}
}
//go:nosplit
func Or32(addr *uint32, v uint32) uint32 {
for {
old := *addr
if Cas(addr, old, old|v) {
return old
}
}
}
//go:nosplit
func And32(addr *uint32, v uint32) uint32 {
for {
old := *addr
if Cas(addr, old, old&v) {
return old
}
}
}
//go:nosplit
func Or64(addr *uint64, v uint64) uint64 {
for {
old := *addr
if Cas64(addr, old, old|v) {
return old
}
}
}
//go:nosplit
func And64(addr *uint64, v uint64) uint64 {
for {
old := *addr
if Cas64(addr, old, old&v) {
return old
}
}
}
//go:nosplit
func Oruintptr(addr *uintptr, v uintptr) uintptr {
for {
old := *addr
if Casuintptr(addr, old, old|v) {
return old
}
}
}
//go:nosplit
func Anduintptr(addr *uintptr, v uintptr) uintptr {
for {
old := *addr
if Casuintptr(addr, old, old&v) {
return old
}
}
}
//go:nosplit
func armcas(ptr *uint32, old, new uint32) bool

View file

@ -66,6 +66,24 @@ func And(ptr *uint32, val uint32)
//go:noescape
func Or(ptr *uint32, val uint32)
//go:noescape
func And32(ptr *uint32, val uint32) uint32
//go:noescape
func Or32(ptr *uint32, val uint32) uint32
//go:noescape
func And64(ptr *uint64, val uint64) uint64
//go:noescape
func Or64(ptr *uint64, val uint64) uint64
//go:noescape
func Anduintptr(ptr *uintptr, val uintptr) uintptr
//go:noescape
func Oruintptr(ptr *uintptr, val uintptr) uintptr
//go:noescape
func Cas64(ptr *uint64, old, new uint64) bool

View file

@ -331,3 +331,81 @@ load_store_loop:
STLXRW R2, (R0), R3
CBNZ R3, load_store_loop
RET
// func Or32(addr *uint32, v uint32) old uint32
TEXT ·Or32(SB), NOSPLIT, $0-20
MOVD ptr+0(FP), R0
MOVW val+8(FP), R1
MOVBU internalcpu·ARM64+const_offsetARM64HasATOMICS(SB), R4
CBZ R4, load_store_loop
LDORALW R1, (R0), R2
MOVD R2, ret+16(FP)
RET
load_store_loop:
LDAXRW (R0), R2
ORR R1, R2, R3
STLXRW R3, (R0), R4
CBNZ R4, load_store_loop
MOVD R2, ret+16(FP)
RET
// func And32(addr *uint32, v uint32) old uint32
TEXT ·And32(SB), NOSPLIT, $0-20
MOVD ptr+0(FP), R0
MOVW val+8(FP), R1
MOVBU internalcpu·ARM64+const_offsetARM64HasATOMICS(SB), R4
CBZ R4, load_store_loop
MVN R1, R2
LDCLRALW R2, (R0), R3
MOVD R3, ret+16(FP)
RET
load_store_loop:
LDAXRW (R0), R2
AND R1, R2, R3
STLXRW R3, (R0), R4
CBNZ R4, load_store_loop
MOVD R2, ret+16(FP)
RET
// func Or64(addr *uint64, v uint64) old uint64
TEXT ·Or64(SB), NOSPLIT, $0-24
MOVD ptr+0(FP), R0
MOVD val+8(FP), R1
MOVBU internalcpu·ARM64+const_offsetARM64HasATOMICS(SB), R4
CBZ R4, load_store_loop
LDORALD R1, (R0), R2
MOVD R2, ret+16(FP)
RET
load_store_loop:
LDAXR (R0), R2
ORR R1, R2, R3
STLXR R3, (R0), R4
CBNZ R4, load_store_loop
MOVD R2, ret+16(FP)
RET
// func And64(addr *uint64, v uint64) old uint64
TEXT ·And64(SB), NOSPLIT, $0-24
MOVD ptr+0(FP), R0
MOVD val+8(FP), R1
MOVBU internalcpu·ARM64+const_offsetARM64HasATOMICS(SB), R4
CBZ R4, load_store_loop
MVN R1, R2
LDCLRALD R2, (R0), R3
MOVD R3, ret+16(FP)
RET
load_store_loop:
LDAXR (R0), R2
AND R1, R2, R3
STLXR R3, (R0), R4
CBNZ R4, load_store_loop
MOVD R2, ret+16(FP)
RET
// func Anduintptr(addr *uintptr, v uintptr) old uintptr
TEXT ·Anduintptr(SB), NOSPLIT, $0-24
B ·And64(SB)
// func Oruintptr(addr *uintptr, v uintptr) old uintptr
TEXT ·Oruintptr(SB), NOSPLIT, $0-24
B ·Or64(SB)