mirror of https://github.com/golang/go.git
internal/runtime/atomic: add Xchg8 for s390x and wasm
This makes the single-byte atomic.Xchg8 operation available on all GOARCHes, including those without direct / single-instruction support. Fixes #69735 Change-Id: Icb6aff8f907257db81ea440dc4d29f96b3cff6c4 Reviewed-on: https://go-review.googlesource.com/c/go/+/657936 Reviewed-by: Mauri de Souza Meneguzzo <mauri870@gmail.com> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: David Chase <drchase@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@google.com> Auto-Submit: Rhys Hiltner <rhys.hiltner@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
580b6ee646
commit
3c3b8dd4f0
|
|
@ -77,24 +77,6 @@ func Xchg(addr *uint32, v uint32) uint32 {
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func Xchg8(addr *uint8, v uint8) uint8
|
func Xchg8(addr *uint8, v uint8) uint8
|
||||||
|
|
||||||
//go:nosplit
|
|
||||||
func goXchg8(addr *uint8, v uint8) uint8 {
|
|
||||||
// Align down to 4 bytes and use 32-bit CAS.
|
|
||||||
addr32 := (*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(addr)) &^ 3))
|
|
||||||
shift := (uintptr(unsafe.Pointer(addr)) & 3) * 8 // little endian
|
|
||||||
word := uint32(v) << shift
|
|
||||||
mask := uint32(0xFF) << shift
|
|
||||||
|
|
||||||
for {
|
|
||||||
old := *addr32 // Read the old 32-bit value
|
|
||||||
// Clear the old 8 bits then insert the new value
|
|
||||||
if Cas(addr32, old, (old&^mask)|word) {
|
|
||||||
// Return the old 8-bit value
|
|
||||||
return uint8((old & mask) >> shift)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func Xchguintptr(addr *uintptr, v uintptr) uintptr {
|
func Xchguintptr(addr *uintptr, v uintptr) uintptr {
|
||||||
return uintptr(Xchg((*uint32)(unsafe.Pointer(addr)), uint32(v)))
|
return uintptr(Xchg((*uint32)(unsafe.Pointer(addr)), uint32(v)))
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,11 @@ func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func Xchg(ptr *uint32, new uint32) uint32
|
func Xchg(ptr *uint32, new uint32) uint32
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
func Xchg8(addr *uint8, v uint8) uint8 {
|
||||||
|
return goXchg8(addr, v)
|
||||||
|
}
|
||||||
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func Xchg64(ptr *uint64, new uint64) uint64
|
func Xchg64(ptr *uint64, new uint64) uint64
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,11 @@ func Xchg(ptr *uint32, new uint32) uint32 {
|
||||||
return old
|
return old
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
func Xchg8(addr *uint8, v uint8) uint8 {
|
||||||
|
return goXchg8(addr, v)
|
||||||
|
}
|
||||||
|
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
//go:noinline
|
//go:noinline
|
||||||
func Xchg64(ptr *uint64, new uint64) uint64 {
|
func Xchg64(ptr *uint64, new uint64) uint64 {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright 2025 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package atomic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"internal/goarch"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
func goXchg8(addr *uint8, v uint8) uint8 {
|
||||||
|
// Align down to 4 bytes and use 32-bit CAS.
|
||||||
|
addr32 := (*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(addr)) &^ 3))
|
||||||
|
shift := (uintptr(unsafe.Pointer(addr)) & 3)
|
||||||
|
if goarch.BigEndian {
|
||||||
|
shift = shift ^ 3
|
||||||
|
}
|
||||||
|
shift = shift * 8
|
||||||
|
word := uint32(v) << shift
|
||||||
|
mask := uint32(0xFF) << shift
|
||||||
|
|
||||||
|
for {
|
||||||
|
old := *addr32 // Read the old 32-bit value
|
||||||
|
// Clear the old 8 bits then insert the new value
|
||||||
|
if Cas(addr32, old, (old&^mask)|word) {
|
||||||
|
// Return the old 8-bit value
|
||||||
|
return uint8((old & mask) >> shift)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,8 +2,6 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build 386 || amd64 || arm || arm64 || loong64 || mips || mipsle || mips64 || mips64le || ppc64 || ppc64le || riscv64
|
|
||||||
|
|
||||||
package atomic_test
|
package atomic_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue