1 //go:build 386 || amd64 || ppc64 || ppc64le || riscv64 || wasm
4 // Copyright 2023 The Go Authors. All rights reserved.
5 // Use of this source code is governed by a BSD-style
6 // license that can be found in the LICENSE file.
8 // TODO(61395): move these tests to atomic_test.go once And/Or have
9 // implementations for all architectures.
13 "runtime/internal/atomic"
17 func TestAnd32(t *testing.T) {
18 // Basic sanity check.
19 x := uint32(0xffffffff)
20 for i := uint32(0); i < 32; i++ {
22 v := atomic.And32(&x, ^(1 << i))
23 if r := uint32(0xffffffff) << (i + 1); x != r || v != old {
24 t.Fatalf("clearing bit %#x: want %#x, got new %#x and old %#v", uint32(1<<i), r, x, v)
28 // Set every bit in array to 1.
29 a := make([]uint32, 1<<12)
34 // Clear array bit-by-bit in different goroutines.
35 done := make(chan bool)
36 for i := 0; i < 32; i++ {
45 for i := 0; i < 32; i++ {
49 // Check that the array has been totally cleared.
52 t.Fatalf("a[%v] not cleared: want %#x, got %#x", i, uint32(0), v)
57 func TestAnd64(t *testing.T) {
58 // Basic sanity check.
59 x := uint64(0xffffffffffffffff)
60 for i := uint64(0); i < 64; i++ {
62 v := atomic.And64(&x, ^(1 << i))
63 if r := uint64(0xffffffffffffffff) << (i + 1); x != r || v != old {
64 t.Fatalf("clearing bit %#x: want %#x, got new %#x and old %#v", uint64(1<<i), r, x, v)
68 // Set every bit in array to 1.
69 a := make([]uint64, 1<<12)
71 a[i] = 0xffffffffffffffff
74 // Clear array bit-by-bit in different goroutines.
75 done := make(chan bool)
76 for i := 0; i < 64; i++ {
80 atomic.And64(&a[i], m)
85 for i := 0; i < 64; i++ {
89 // Check that the array has been totally cleared.
92 t.Fatalf("a[%v] not cleared: want %#x, got %#x", i, uint64(0), v)
97 func TestOr32(t *testing.T) {
98 // Basic sanity check.
100 for i := uint32(0); i < 32; i++ {
102 v := atomic.Or32(&x, 1<<i)
103 if r := (uint32(1) << (i + 1)) - 1; x != r || v != old {
104 t.Fatalf("setting bit %#x: want %#x, got new %#x and old %#v", uint32(1<<i), r, x, v)
108 // Start with every bit in array set to 0.
109 a := make([]uint32, 1<<12)
111 // Set every bit in array bit-by-bit in different goroutines.
112 done := make(chan bool)
113 for i := 0; i < 32; i++ {
117 atomic.Or32(&a[i], m)
122 for i := 0; i < 32; i++ {
126 // Check that the array has been totally set.
127 for i, v := range a {
129 t.Fatalf("a[%v] not fully set: want %#x, got %#x", i, uint32(0xffffffff), v)
134 func TestOr64(t *testing.T) {
135 // Basic sanity check.
137 for i := uint64(0); i < 64; i++ {
139 v := atomic.Or64(&x, 1<<i)
140 if r := (uint64(1) << (i + 1)) - 1; x != r || v != old {
141 t.Fatalf("setting bit %#x: want %#x, got new %#x and old %#v", uint64(1<<i), r, x, v)
145 // Start with every bit in array set to 0.
146 a := make([]uint64, 1<<12)
148 // Set every bit in array bit-by-bit in different goroutines.
149 done := make(chan bool)
150 for i := 0; i < 64; i++ {
154 atomic.Or64(&a[i], m)
159 for i := 0; i < 64; i++ {
163 // Check that the array has been totally set.
164 for i, v := range a {
165 if v != 0xffffffffffffffff {
166 t.Fatalf("a[%v] not fully set: want %#x, got %#x", i, uint64(0xffffffffffffffff), v)
171 func BenchmarkAnd32(b *testing.B) {
172 var x [128]uint32 // give x its own cache line
174 for i := 0; i < b.N; i++ {
175 atomic.And32(&x[63], uint32(i))
179 func BenchmarkAnd32Parallel(b *testing.B) {
180 var x [128]uint32 // give x its own cache line
182 b.RunParallel(func(pb *testing.PB) {
185 atomic.And32(&x[63], i)
191 func BenchmarkAnd64(b *testing.B) {
192 var x [128]uint64 // give x its own cache line
194 for i := 0; i < b.N; i++ {
195 atomic.And64(&x[63], uint64(i))
199 func BenchmarkAnd64Parallel(b *testing.B) {
200 var x [128]uint64 // give x its own cache line
202 b.RunParallel(func(pb *testing.PB) {
205 atomic.And64(&x[63], i)
211 func BenchmarkOr32(b *testing.B) {
212 var x [128]uint32 // give x its own cache line
214 for i := 0; i < b.N; i++ {
215 atomic.Or32(&x[63], uint32(i))
219 func BenchmarkOr32Parallel(b *testing.B) {
220 var x [128]uint32 // give x its own cache line
222 b.RunParallel(func(pb *testing.PB) {
225 atomic.Or32(&x[63], i)
231 func BenchmarkOr64(b *testing.B) {
232 var x [128]uint64 // give x its own cache line
234 for i := 0; i < b.N; i++ {
235 atomic.Or64(&x[63], uint64(i))
239 func BenchmarkOr64Parallel(b *testing.B) {
240 var x [128]uint64 // give x its own cache line
242 b.RunParallel(func(pb *testing.PB) {
245 atomic.Or64(&x[63], i)