//go:noescape
func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
+//go:noescape
+func Xchg8(ptr *uint8, new uint8) uint8
+
//go:noescape
func Xchg(ptr *uint32, new uint32) uint32
TEXT ·Xadduintptr(SB), NOSPLIT, $0-24
JMP ·Xadd64(SB)
+// uint8 Xchg(ptr *uint8, new uint8)
+// Atomically:
+// old := *ptr;
+// *ptr = new;
+// return old;
+TEXT ·Xchg8(SB), NOSPLIT, $0-17
+ MOVQ ptr+0(FP), BX
+ MOVB new+8(FP), AX
+ XCHGB AX, 0(BX)
+ MOVB AX, ret+16(FP)
+ RET
+
// uint32 Xchg(ptr *uint32, new uint32)
// Atomically:
// old := *ptr;
--- /dev/null
+// Copyright 2024 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.
+
+//go:build amd64
+
+package atomic_test
+
+import (
+ "internal/runtime/atomic"
+ "testing"
+)
+
+func TestXchg8(t *testing.T) {
+ var a [16]uint8
+ for i := range a {
+ next := uint8(i + 50)
+ a[i] = next
+ }
+ b := a
+
+ // Compare behavior against non-atomic implementation. Expect the operation
+ // to work at any byte offset and to not clobber neighboring values.
+ for i := range a {
+ next := uint8(i + 100)
+ pa := atomic.Xchg8(&a[i], next)
+ pb := b[i]
+ b[i] = next
+ if pa != pb {
+ t.Errorf("atomic.Xchg8(a[%d]); %d != %d", i, pa, pb)
+ }
+ if a != b {
+ t.Errorf("after atomic.Xchg8(a[%d]); %d != %d", i, a, b)
+ }
+ if t.Failed() {
+ break
+ }
+ }
+}