]> Cypherpunks repositories - gostls13.git/commitdiff
internal/runtime/atomic: add Xchg8 for s390x and wasm
authorRhys Hiltner <rhys.hiltner@gmail.com>
Fri, 14 Mar 2025 16:36:06 +0000 (09:36 -0700)
committerGopher Robot <gobot@golang.org>
Fri, 14 Mar 2025 22:42:34 +0000 (15:42 -0700)
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>

src/internal/runtime/atomic/atomic_arm.go
src/internal/runtime/atomic/atomic_s390x.go
src/internal/runtime/atomic/atomic_wasm.go
src/internal/runtime/atomic/xchg8.go [new file with mode: 0644]
src/internal/runtime/atomic/xchg8_test.go

index 8d8ffcf7dcbf64f20aa6844ab8e5b13193bff7f9..e858fb7cd1a99a812c26ed44219a2f67d2f9d179 100644 (file)
@@ -77,24 +77,6 @@ func Xchg(addr *uint32, v uint32) uint32 {
 //go:noescape
 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
 func Xchguintptr(addr *uintptr, v uintptr) uintptr {
        return uintptr(Xchg((*uint32)(unsafe.Pointer(addr)), uint32(v)))
index 68b4e160f9a865ecd4a30ebcd27abfdbbdb125af..bd5d867bec4e62e4557006ec1a5ff1d9a263347a 100644 (file)
@@ -128,6 +128,11 @@ func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
 //go:noescape
 func Xchg(ptr *uint32, new uint32) uint32
 
+//go:nosplit
+func Xchg8(addr *uint8, v uint8) uint8 {
+       return goXchg8(addr, v)
+}
+
 //go:noescape
 func Xchg64(ptr *uint64, new uint64) uint64
 
index d1dcfec7adde9f75fcf068c19de7fc013ccc8b47..3f14da138c79cc9cfd06b0c67a17e13447879154 100644 (file)
@@ -114,6 +114,11 @@ func Xchg(ptr *uint32, new uint32) uint32 {
        return old
 }
 
+//go:nosplit
+func Xchg8(addr *uint8, v uint8) uint8 {
+       return goXchg8(addr, v)
+}
+
 //go:nosplit
 //go:noinline
 func Xchg64(ptr *uint64, new uint64) uint64 {
diff --git a/src/internal/runtime/atomic/xchg8.go b/src/internal/runtime/atomic/xchg8.go
new file mode 100644 (file)
index 0000000..4fdea9a
--- /dev/null
@@ -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)
+               }
+       }
+}
index 952dfe4aad5645bc98b3abd171167b64d0fcf225..1214c9cedcefbb34323db8d8e8bdfccb0bd775bb 100644 (file)
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // 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
 
 import (