1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package atomic_test
6
7import (
8	"fmt"
9	"reflect"
10	"runtime"
11	"runtime/debug"
12	"strings"
13	. "sync/atomic"
14	"testing"
15	"unsafe"
16)
17
18// Tests of correct behavior, without contention.
19// (Does the function work as advertised?)
20//
21// Test that the Add functions add correctly.
22// Test that the CompareAndSwap functions actually
23// do the comparison and the swap correctly.
24//
25// The loop over power-of-two values is meant to
26// ensure that the operations apply to the full word size.
27// The struct fields x.before and x.after check that the
28// operations do not extend past the full word size.
29
30const (
31	magic32 = 0xdedbeef
32	magic64 = 0xdeddeadbeefbeef
33)
34
35func TestSwapInt32(t *testing.T) {
36	var x struct {
37		before int32
38		i      int32
39		after  int32
40	}
41	x.before = magic32
42	x.after = magic32
43	var j int32
44	for delta := int32(1); delta+delta > delta; delta += delta {
45		k := SwapInt32(&x.i, delta)
46		if x.i != delta || k != j {
47			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
48		}
49		j = delta
50	}
51	if x.before != magic32 || x.after != magic32 {
52		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
53	}
54}
55
56func TestSwapInt32Method(t *testing.T) {
57	var x struct {
58		before int32
59		i      Int32
60		after  int32
61	}
62	x.before = magic32
63	x.after = magic32
64	var j int32
65	for delta := int32(1); delta+delta > delta; delta += delta {
66		k := x.i.Swap(delta)
67		if x.i.Load() != delta || k != j {
68			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
69		}
70		j = delta
71	}
72	if x.before != magic32 || x.after != magic32 {
73		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
74	}
75}
76
77func TestSwapUint32(t *testing.T) {
78	var x struct {
79		before uint32
80		i      uint32
81		after  uint32
82	}
83	x.before = magic32
84	x.after = magic32
85	var j uint32
86	for delta := uint32(1); delta+delta > delta; delta += delta {
87		k := SwapUint32(&x.i, delta)
88		if x.i != delta || k != j {
89			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
90		}
91		j = delta
92	}
93	if x.before != magic32 || x.after != magic32 {
94		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
95	}
96}
97
98func TestSwapUint32Method(t *testing.T) {
99	var x struct {
100		before uint32
101		i      Uint32
102		after  uint32
103	}
104	x.before = magic32
105	x.after = magic32
106	var j uint32
107	for delta := uint32(1); delta+delta > delta; delta += delta {
108		k := x.i.Swap(delta)
109		if x.i.Load() != delta || k != j {
110			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
111		}
112		j = delta
113	}
114	if x.before != magic32 || x.after != magic32 {
115		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
116	}
117}
118
119func TestSwapInt64(t *testing.T) {
120	var x struct {
121		before int64
122		i      int64
123		after  int64
124	}
125	magic64 := int64(magic64)
126	x.before = magic64
127	x.after = magic64
128	var j int64
129	for delta := int64(1); delta+delta > delta; delta += delta {
130		k := SwapInt64(&x.i, delta)
131		if x.i != delta || k != j {
132			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
133		}
134		j = delta
135	}
136	if x.before != magic64 || x.after != magic64 {
137		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
138	}
139}
140
141func TestSwapInt64Method(t *testing.T) {
142	var x struct {
143		before int64
144		i      Int64
145		after  int64
146	}
147	magic64 := int64(magic64)
148	x.before = magic64
149	x.after = magic64
150	var j int64
151	for delta := int64(1); delta+delta > delta; delta += delta {
152		k := x.i.Swap(delta)
153		if x.i.Load() != delta || k != j {
154			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
155		}
156		j = delta
157	}
158	if x.before != magic64 || x.after != magic64 {
159		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
160	}
161}
162
163func TestSwapUint64(t *testing.T) {
164	var x struct {
165		before uint64
166		i      uint64
167		after  uint64
168	}
169	magic64 := uint64(magic64)
170	x.before = magic64
171	x.after = magic64
172	var j uint64
173	for delta := uint64(1); delta+delta > delta; delta += delta {
174		k := SwapUint64(&x.i, delta)
175		if x.i != delta || k != j {
176			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
177		}
178		j = delta
179	}
180	if x.before != magic64 || x.after != magic64 {
181		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
182	}
183}
184
185func TestSwapUint64Method(t *testing.T) {
186	var x struct {
187		before uint64
188		i      Uint64
189		after  uint64
190	}
191	magic64 := uint64(magic64)
192	x.before = magic64
193	x.after = magic64
194	var j uint64
195	for delta := uint64(1); delta+delta > delta; delta += delta {
196		k := x.i.Swap(delta)
197		if x.i.Load() != delta || k != j {
198			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
199		}
200		j = delta
201	}
202	if x.before != magic64 || x.after != magic64 {
203		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
204	}
205}
206
207func TestSwapUintptr(t *testing.T) {
208	var x struct {
209		before uintptr
210		i      uintptr
211		after  uintptr
212	}
213	var m uint64 = magic64
214	magicptr := uintptr(m)
215	x.before = magicptr
216	x.after = magicptr
217	var j uintptr
218	for delta := uintptr(1); delta+delta > delta; delta += delta {
219		k := SwapUintptr(&x.i, delta)
220		if x.i != delta || k != j {
221			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
222		}
223		j = delta
224	}
225	if x.before != magicptr || x.after != magicptr {
226		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
227	}
228}
229
230func TestSwapUintptrMethod(t *testing.T) {
231	var x struct {
232		before uintptr
233		i      Uintptr
234		after  uintptr
235	}
236	var m uint64 = magic64
237	magicptr := uintptr(m)
238	x.before = magicptr
239	x.after = magicptr
240	var j uintptr
241	for delta := uintptr(1); delta+delta > delta; delta += delta {
242		k := x.i.Swap(delta)
243		if x.i.Load() != delta || k != j {
244			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
245		}
246		j = delta
247	}
248	if x.before != magicptr || x.after != magicptr {
249		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
250	}
251}
252
253var global [1024]byte
254
255func testPointers() []unsafe.Pointer {
256	var pointers []unsafe.Pointer
257	// globals
258	for i := 0; i < 10; i++ {
259		pointers = append(pointers, unsafe.Pointer(&global[1<<i-1]))
260	}
261	// heap
262	pointers = append(pointers, unsafe.Pointer(new(byte)))
263	// nil
264	pointers = append(pointers, nil)
265	return pointers
266}
267
268func TestSwapPointer(t *testing.T) {
269	var x struct {
270		before uintptr
271		i      unsafe.Pointer
272		after  uintptr
273	}
274	var m uint64 = magic64
275	magicptr := uintptr(m)
276	x.before = magicptr
277	x.after = magicptr
278	var j unsafe.Pointer
279
280	for _, p := range testPointers() {
281		k := SwapPointer(&x.i, p)
282		if x.i != p || k != j {
283			t.Fatalf("p=%p i=%p j=%p k=%p", p, x.i, j, k)
284		}
285		j = p
286	}
287	if x.before != magicptr || x.after != magicptr {
288		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
289	}
290}
291
292func TestSwapPointerMethod(t *testing.T) {
293	var x struct {
294		before uintptr
295		i      Pointer[byte]
296		after  uintptr
297	}
298	var m uint64 = magic64
299	magicptr := uintptr(m)
300	x.before = magicptr
301	x.after = magicptr
302	var j *byte
303	for _, p := range testPointers() {
304		p := (*byte)(p)
305		k := x.i.Swap(p)
306		if x.i.Load() != p || k != j {
307			t.Fatalf("p=%p i=%p j=%p k=%p", p, x.i.Load(), j, k)
308		}
309		j = p
310	}
311	if x.before != magicptr || x.after != magicptr {
312		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
313	}
314}
315
316func TestAddInt32(t *testing.T) {
317	var x struct {
318		before int32
319		i      int32
320		after  int32
321	}
322	x.before = magic32
323	x.after = magic32
324	var j int32
325	for delta := int32(1); delta+delta > delta; delta += delta {
326		k := AddInt32(&x.i, delta)
327		j += delta
328		if x.i != j || k != j {
329			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
330		}
331	}
332	if x.before != magic32 || x.after != magic32 {
333		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
334	}
335}
336
337func TestAddInt32Method(t *testing.T) {
338	var x struct {
339		before int32
340		i      Int32
341		after  int32
342	}
343	x.before = magic32
344	x.after = magic32
345	var j int32
346	for delta := int32(1); delta+delta > delta; delta += delta {
347		k := x.i.Add(delta)
348		j += delta
349		if x.i.Load() != j || k != j {
350			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
351		}
352	}
353	if x.before != magic32 || x.after != magic32 {
354		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
355	}
356}
357
358func TestAddUint32(t *testing.T) {
359	var x struct {
360		before uint32
361		i      uint32
362		after  uint32
363	}
364	x.before = magic32
365	x.after = magic32
366	var j uint32
367	for delta := uint32(1); delta+delta > delta; delta += delta {
368		k := AddUint32(&x.i, delta)
369		j += delta
370		if x.i != j || k != j {
371			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
372		}
373	}
374	if x.before != magic32 || x.after != magic32 {
375		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
376	}
377}
378
379func TestAddUint32Method(t *testing.T) {
380	var x struct {
381		before uint32
382		i      Uint32
383		after  uint32
384	}
385	x.before = magic32
386	x.after = magic32
387	var j uint32
388	for delta := uint32(1); delta+delta > delta; delta += delta {
389		k := x.i.Add(delta)
390		j += delta
391		if x.i.Load() != j || k != j {
392			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
393		}
394	}
395	if x.before != magic32 || x.after != magic32 {
396		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
397	}
398}
399
400func TestAddInt64(t *testing.T) {
401	var x struct {
402		before int64
403		i      int64
404		after  int64
405	}
406	magic64 := int64(magic64)
407	x.before = magic64
408	x.after = magic64
409	var j int64
410	for delta := int64(1); delta+delta > delta; delta += delta {
411		k := AddInt64(&x.i, delta)
412		j += delta
413		if x.i != j || k != j {
414			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
415		}
416	}
417	if x.before != magic64 || x.after != magic64 {
418		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
419	}
420}
421
422func TestAddInt64Method(t *testing.T) {
423	var x struct {
424		before int64
425		i      Int64
426		after  int64
427	}
428	magic64 := int64(magic64)
429	x.before = magic64
430	x.after = magic64
431	var j int64
432	for delta := int64(1); delta+delta > delta; delta += delta {
433		k := x.i.Add(delta)
434		j += delta
435		if x.i.Load() != j || k != j {
436			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
437		}
438	}
439	if x.before != magic64 || x.after != magic64 {
440		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
441	}
442}
443
444func TestAddUint64(t *testing.T) {
445	var x struct {
446		before uint64
447		i      uint64
448		after  uint64
449	}
450	magic64 := uint64(magic64)
451	x.before = magic64
452	x.after = magic64
453	var j uint64
454	for delta := uint64(1); delta+delta > delta; delta += delta {
455		k := AddUint64(&x.i, delta)
456		j += delta
457		if x.i != j || k != j {
458			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
459		}
460	}
461	if x.before != magic64 || x.after != magic64 {
462		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
463	}
464}
465
466func TestAddUint64Method(t *testing.T) {
467	var x struct {
468		before uint64
469		i      Uint64
470		after  uint64
471	}
472	magic64 := uint64(magic64)
473	x.before = magic64
474	x.after = magic64
475	var j uint64
476	for delta := uint64(1); delta+delta > delta; delta += delta {
477		k := x.i.Add(delta)
478		j += delta
479		if x.i.Load() != j || k != j {
480			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
481		}
482	}
483	if x.before != magic64 || x.after != magic64 {
484		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
485	}
486}
487
488func TestAddUintptr(t *testing.T) {
489	var x struct {
490		before uintptr
491		i      uintptr
492		after  uintptr
493	}
494	var m uint64 = magic64
495	magicptr := uintptr(m)
496	x.before = magicptr
497	x.after = magicptr
498	var j uintptr
499	for delta := uintptr(1); delta+delta > delta; delta += delta {
500		k := AddUintptr(&x.i, delta)
501		j += delta
502		if x.i != j || k != j {
503			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
504		}
505	}
506	if x.before != magicptr || x.after != magicptr {
507		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
508	}
509}
510
511func TestAddUintptrMethod(t *testing.T) {
512	var x struct {
513		before uintptr
514		i      Uintptr
515		after  uintptr
516	}
517	var m uint64 = magic64
518	magicptr := uintptr(m)
519	x.before = magicptr
520	x.after = magicptr
521	var j uintptr
522	for delta := uintptr(1); delta+delta > delta; delta += delta {
523		k := x.i.Add(delta)
524		j += delta
525		if x.i.Load() != j || k != j {
526			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k)
527		}
528	}
529	if x.before != magicptr || x.after != magicptr {
530		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
531	}
532}
533
534func TestAndInt32(t *testing.T) {
535	var x struct {
536		before int32
537		i      int32
538		after  int32
539	}
540	x.before = magic32
541	x.after = magic32
542	x.i = -1
543	j := x.i
544	for mask := int32(1); mask != 0; mask <<= 1 {
545		old := x.i
546		k := AndInt32(&x.i, ^mask)
547		j &= ^mask
548		if x.i != j || k != old {
549			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old)
550		}
551	}
552	if x.before != magic32 || x.after != magic32 {
553		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
554	}
555}
556
557func TestAndInt32Method(t *testing.T) {
558	var x struct {
559		before int32
560		i      Int32
561		after  int32
562	}
563	x.before = magic32
564	x.after = magic32
565	x.i.Store(-1)
566	j := x.i.Load()
567	for mask := int32(1); mask != 0; mask <<= 1 {
568		old := x.i.Load()
569		k := x.i.And(^mask)
570		j &= ^mask
571		if x.i.Load() != j || k != old {
572			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old)
573		}
574	}
575	if x.before != magic32 || x.after != magic32 {
576		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
577	}
578}
579
580func TestAndUint32(t *testing.T) {
581	var x struct {
582		before uint32
583		i      uint32
584		after  uint32
585	}
586	x.before = magic32
587	x.after = magic32
588	x.i = 0xffffffff
589	j := x.i
590	for mask := uint32(1); mask != 0; mask <<= 1 {
591		old := x.i
592		k := AndUint32(&x.i, ^mask)
593		j &= ^mask
594		if x.i != j || k != old {
595			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old)
596		}
597	}
598	if x.before != magic32 || x.after != magic32 {
599		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
600	}
601}
602
603func TestAndUint32Method(t *testing.T) {
604	var x struct {
605		before uint32
606		i      Uint32
607		after  uint32
608	}
609	x.before = magic32
610	x.after = magic32
611	x.i.Store(0xffffffff)
612	j := x.i.Load()
613	for mask := uint32(1); mask != 0; mask <<= 1 {
614		old := x.i.Load()
615		k := x.i.And(^mask)
616		j &= ^mask
617		if x.i.Load() != j || k != old {
618			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old)
619		}
620	}
621	if x.before != magic32 || x.after != magic32 {
622		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
623	}
624}
625
626func TestAndInt64(t *testing.T) {
627	var x struct {
628		before int64
629		i      int64
630		after  int64
631	}
632	magic64 := int64(magic64)
633	x.before = magic64
634	x.after = magic64
635	x.i = -1
636	j := x.i
637	for mask := int64(1); mask != 0; mask <<= 1 {
638		old := x.i
639		k := AndInt64(&x.i, ^mask)
640		j &= ^mask
641		if x.i != j || k != old {
642			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old)
643		}
644	}
645	if x.before != magic64 || x.after != magic64 {
646		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
647	}
648}
649
650func TestAndInt64Method(t *testing.T) {
651	var x struct {
652		before int64
653		i      Int64
654		after  int64
655	}
656	magic64 := int64(magic64)
657	x.before = magic64
658	x.after = magic64
659	x.i.Store(-1)
660	j := x.i.Load()
661	for mask := int64(1); mask != 0; mask <<= 1 {
662		old := x.i.Load()
663		k := x.i.And(^mask)
664		j &= ^mask
665		if x.i.Load() != j || k != old {
666			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old)
667		}
668	}
669	if x.before != magic64 || x.after != magic64 {
670		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
671	}
672}
673
674func TestAndUint64(t *testing.T) {
675	var x struct {
676		before uint64
677		i      uint64
678		after  uint64
679	}
680	magic64 := uint64(magic64)
681	x.before = magic64
682	x.after = magic64
683	x.i = 0xfffffffffffffff
684	j := x.i
685	for mask := uint64(1); mask != 0; mask <<= 1 {
686		old := x.i
687		k := AndUint64(&x.i, ^mask)
688		j &= ^mask
689		if x.i != j || k != old {
690			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old)
691		}
692	}
693	if x.before != magic64 || x.after != magic64 {
694		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
695	}
696}
697
698func TestAndUint64Method(t *testing.T) {
699	var x struct {
700		before uint64
701		i      Uint64
702		after  uint64
703	}
704	magic64 := uint64(magic64)
705	x.before = magic64
706	x.after = magic64
707	x.i.Store(0xfffffffffffffff)
708	j := x.i.Load()
709	for mask := uint64(1); mask != 0; mask <<= 1 {
710		old := x.i.Load()
711		k := x.i.And(^mask)
712		j &= ^mask
713		if x.i.Load() != j || k != old {
714			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old)
715		}
716	}
717	if x.before != magic64 || x.after != magic64 {
718		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
719	}
720}
721
722func TestAndUintptr(t *testing.T) {
723	var x struct {
724		before uintptr
725		i      uintptr
726		after  uintptr
727	}
728	var m uint64 = magic64
729	magicptr := uintptr(m)
730	x.before = magicptr
731	x.after = magicptr
732	x.i = ^uintptr(0)
733	j := x.i
734	for mask := uintptr(1); mask != 0; mask <<= 1 {
735		old := x.i
736		k := AndUintptr(&x.i, ^mask)
737		j &= ^mask
738		if x.i != j || k != old {
739			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old)
740		}
741	}
742	if x.before != magicptr || x.after != magicptr {
743		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
744	}
745}
746
747func TestAndUintptrMethod(t *testing.T) {
748	var x struct {
749		before uintptr
750		i      Uintptr
751		after  uintptr
752	}
753	var m uint64 = magic64
754	magicptr := uintptr(m)
755	x.before = magicptr
756	x.after = magicptr
757	x.i.Store(^uintptr(0))
758	j := x.i.Load()
759	for mask := uintptr(1); mask != 0; mask <<= 1 {
760		old := x.i.Load()
761		k := x.i.And(^mask)
762		j &= ^mask
763		if x.i.Load() != j || k != old {
764			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old)
765		}
766	}
767	if x.before != magicptr || x.after != magicptr {
768		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
769	}
770}
771
772func TestOrInt32(t *testing.T) {
773	var x struct {
774		before int32
775		i      int32
776		after  int32
777	}
778	x.before = magic32
779	x.after = magic32
780	var j int32
781	for mask := int32(1); mask != 0; mask <<= 1 {
782		old := x.i
783		k := OrInt32(&x.i, mask)
784		j |= mask
785		if x.i != j || k != old {
786			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old)
787		}
788	}
789	if x.before != magic32 || x.after != magic32 {
790		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
791	}
792}
793
794func TestOrInt32Method(t *testing.T) {
795	var x struct {
796		before int32
797		i      Int32
798		after  int32
799	}
800	x.before = magic32
801	x.after = magic32
802	var j int32
803	for mask := int32(1); mask != 0; mask <<= 1 {
804		old := x.i.Load()
805		k := x.i.Or(mask)
806		j |= mask
807		if x.i.Load() != j || k != old {
808			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old)
809		}
810	}
811	if x.before != magic32 || x.after != magic32 {
812		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
813	}
814}
815
816func TestOrUint32(t *testing.T) {
817	var x struct {
818		before uint32
819		i      uint32
820		after  uint32
821	}
822	x.before = magic32
823	x.after = magic32
824	var j uint32
825	for mask := uint32(1); mask != 0; mask <<= 1 {
826		old := x.i
827		k := OrUint32(&x.i, mask)
828		j |= mask
829		if x.i != j || k != old {
830			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old)
831		}
832	}
833	if x.before != magic32 || x.after != magic32 {
834		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
835	}
836}
837
838func TestOrUint32Method(t *testing.T) {
839	var x struct {
840		before uint32
841		i      Uint32
842		after  uint32
843	}
844	x.before = magic32
845	x.after = magic32
846	var j uint32
847	for mask := uint32(1); mask != 0; mask <<= 1 {
848		old := x.i.Load()
849		k := x.i.Or(mask)
850		j |= mask
851		if x.i.Load() != j || k != old {
852			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old)
853		}
854	}
855	if x.before != magic32 || x.after != magic32 {
856		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
857	}
858}
859
860func TestOrInt64(t *testing.T) {
861	var x struct {
862		before int64
863		i      int64
864		after  int64
865	}
866	magic64 := int64(magic64)
867	x.before = magic64
868	x.after = magic64
869	var j int64
870	for mask := int64(1); mask != 0; mask <<= 1 {
871		old := x.i
872		k := OrInt64(&x.i, mask)
873		j |= mask
874		if x.i != j || k != old {
875			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old)
876		}
877	}
878	if x.before != magic64 || x.after != magic64 {
879		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
880	}
881}
882
883func TestOrInt64Method(t *testing.T) {
884	var x struct {
885		before int64
886		i      Int64
887		after  int64
888	}
889	magic64 := int64(magic64)
890	x.before = magic64
891	x.after = magic64
892	var j int64
893	for mask := int64(1); mask != 0; mask <<= 1 {
894		old := x.i.Load()
895		k := x.i.Or(mask)
896		j |= mask
897		if x.i.Load() != j || k != old {
898			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old)
899		}
900	}
901	if x.before != magic64 || x.after != magic64 {
902		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
903	}
904}
905
906func TestOrUint64(t *testing.T) {
907	var x struct {
908		before uint64
909		i      uint64
910		after  uint64
911	}
912	magic64 := uint64(magic64)
913	x.before = magic64
914	x.after = magic64
915	var j uint64
916	for mask := uint64(1); mask != 0; mask <<= 1 {
917		old := x.i
918		k := OrUint64(&x.i, mask)
919		j |= mask
920		if x.i != j || k != old {
921			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old)
922		}
923	}
924	if x.before != magic64 || x.after != magic64 {
925		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
926	}
927}
928
929func TestOrUint64Method(t *testing.T) {
930	var x struct {
931		before uint64
932		i      Uint64
933		after  uint64
934	}
935	magic64 := uint64(magic64)
936	x.before = magic64
937	x.after = magic64
938	var j uint64
939	for mask := uint64(1); mask != 0; mask <<= 1 {
940		old := x.i.Load()
941		k := x.i.Or(mask)
942		j |= mask
943		if x.i.Load() != j || k != old {
944			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old)
945		}
946	}
947	if x.before != magic64 || x.after != magic64 {
948		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
949	}
950}
951
952func TestOrUintptr(t *testing.T) {
953	var x struct {
954		before uintptr
955		i      uintptr
956		after  uintptr
957	}
958	var m uint64 = magic64
959	magicptr := uintptr(m)
960	x.before = magicptr
961	x.after = magicptr
962	var j uintptr
963	for mask := uintptr(1); mask != 0; mask <<= 1 {
964		old := x.i
965		k := OrUintptr(&x.i, mask)
966		j |= mask
967		if x.i != j || k != old {
968			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old)
969		}
970	}
971	if x.before != magicptr || x.after != magicptr {
972		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
973	}
974}
975
976func TestOrUintptrMethod(t *testing.T) {
977	var x struct {
978		before uintptr
979		i      Uintptr
980		after  uintptr
981	}
982	var m uint64 = magic64
983	magicptr := uintptr(m)
984	x.before = magicptr
985	x.after = magicptr
986	var j uintptr
987	for mask := uintptr(1); mask != 0; mask <<= 1 {
988		old := x.i.Load()
989		k := x.i.Or(mask)
990		j |= mask
991		if x.i.Load() != j || k != old {
992			t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old)
993		}
994	}
995	if x.before != magicptr || x.after != magicptr {
996		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
997	}
998}
999
1000func TestCompareAndSwapInt32(t *testing.T) {
1001	var x struct {
1002		before int32
1003		i      int32
1004		after  int32
1005	}
1006	x.before = magic32
1007	x.after = magic32
1008	for val := int32(1); val+val > val; val += val {
1009		x.i = val
1010		if !CompareAndSwapInt32(&x.i, val, val+1) {
1011			t.Fatalf("should have swapped %#x %#x", val, val+1)
1012		}
1013		if x.i != val+1 {
1014			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
1015		}
1016		x.i = val + 1
1017		if CompareAndSwapInt32(&x.i, val, val+2) {
1018			t.Fatalf("should not have swapped %#x %#x", val, val+2)
1019		}
1020		if x.i != val+1 {
1021			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
1022		}
1023	}
1024	if x.before != magic32 || x.after != magic32 {
1025		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
1026	}
1027}
1028
1029func TestCompareAndSwapInt32Method(t *testing.T) {
1030	var x struct {
1031		before int32
1032		i      Int32
1033		after  int32
1034	}
1035	x.before = magic32
1036	x.after = magic32
1037	for val := int32(1); val+val > val; val += val {
1038		x.i.Store(val)
1039		if !x.i.CompareAndSwap(val, val+1) {
1040			t.Fatalf("should have swapped %#x %#x", val, val+1)
1041		}
1042		if x.i.Load() != val+1 {
1043			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
1044		}
1045		x.i.Store(val + 1)
1046		if x.i.CompareAndSwap(val, val+2) {
1047			t.Fatalf("should not have swapped %#x %#x", val, val+2)
1048		}
1049		if x.i.Load() != val+1 {
1050			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
1051		}
1052	}
1053	if x.before != magic32 || x.after != magic32 {
1054		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
1055	}
1056}
1057
1058func TestCompareAndSwapUint32(t *testing.T) {
1059	var x struct {
1060		before uint32
1061		i      uint32
1062		after  uint32
1063	}
1064	x.before = magic32
1065	x.after = magic32
1066	for val := uint32(1); val+val > val; val += val {
1067		x.i = val
1068		if !CompareAndSwapUint32(&x.i, val, val+1) {
1069			t.Fatalf("should have swapped %#x %#x", val, val+1)
1070		}
1071		if x.i != val+1 {
1072			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
1073		}
1074		x.i = val + 1
1075		if CompareAndSwapUint32(&x.i, val, val+2) {
1076			t.Fatalf("should not have swapped %#x %#x", val, val+2)
1077		}
1078		if x.i != val+1 {
1079			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
1080		}
1081	}
1082	if x.before != magic32 || x.after != magic32 {
1083		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
1084	}
1085}
1086
1087func TestCompareAndSwapUint32Method(t *testing.T) {
1088	var x struct {
1089		before uint32
1090		i      Uint32
1091		after  uint32
1092	}
1093	x.before = magic32
1094	x.after = magic32
1095	for val := uint32(1); val+val > val; val += val {
1096		x.i.Store(val)
1097		if !x.i.CompareAndSwap(val, val+1) {
1098			t.Fatalf("should have swapped %#x %#x", val, val+1)
1099		}
1100		if x.i.Load() != val+1 {
1101			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
1102		}
1103		x.i.Store(val + 1)
1104		if x.i.CompareAndSwap(val, val+2) {
1105			t.Fatalf("should not have swapped %#x %#x", val, val+2)
1106		}
1107		if x.i.Load() != val+1 {
1108			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
1109		}
1110	}
1111	if x.before != magic32 || x.after != magic32 {
1112		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
1113	}
1114}
1115
1116func TestCompareAndSwapInt64(t *testing.T) {
1117	var x struct {
1118		before int64
1119		i      int64
1120		after  int64
1121	}
1122	magic64 := int64(magic64)
1123	x.before = magic64
1124	x.after = magic64
1125	for val := int64(1); val+val > val; val += val {
1126		x.i = val
1127		if !CompareAndSwapInt64(&x.i, val, val+1) {
1128			t.Fatalf("should have swapped %#x %#x", val, val+1)
1129		}
1130		if x.i != val+1 {
1131			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
1132		}
1133		x.i = val + 1
1134		if CompareAndSwapInt64(&x.i, val, val+2) {
1135			t.Fatalf("should not have swapped %#x %#x", val, val+2)
1136		}
1137		if x.i != val+1 {
1138			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
1139		}
1140	}
1141	if x.before != magic64 || x.after != magic64 {
1142		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1143	}
1144}
1145
1146func TestCompareAndSwapInt64Method(t *testing.T) {
1147	var x struct {
1148		before int64
1149		i      Int64
1150		after  int64
1151	}
1152	magic64 := int64(magic64)
1153	x.before = magic64
1154	x.after = magic64
1155	for val := int64(1); val+val > val; val += val {
1156		x.i.Store(val)
1157		if !x.i.CompareAndSwap(val, val+1) {
1158			t.Fatalf("should have swapped %#x %#x", val, val+1)
1159		}
1160		if x.i.Load() != val+1 {
1161			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
1162		}
1163		x.i.Store(val + 1)
1164		if x.i.CompareAndSwap(val, val+2) {
1165			t.Fatalf("should not have swapped %#x %#x", val, val+2)
1166		}
1167		if x.i.Load() != val+1 {
1168			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
1169		}
1170	}
1171	if x.before != magic64 || x.after != magic64 {
1172		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1173	}
1174}
1175
1176func testCompareAndSwapUint64(t *testing.T, cas func(*uint64, uint64, uint64) bool) {
1177	var x struct {
1178		before uint64
1179		i      uint64
1180		after  uint64
1181	}
1182	magic64 := uint64(magic64)
1183	x.before = magic64
1184	x.after = magic64
1185	for val := uint64(1); val+val > val; val += val {
1186		x.i = val
1187		if !cas(&x.i, val, val+1) {
1188			t.Fatalf("should have swapped %#x %#x", val, val+1)
1189		}
1190		if x.i != val+1 {
1191			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
1192		}
1193		x.i = val + 1
1194		if cas(&x.i, val, val+2) {
1195			t.Fatalf("should not have swapped %#x %#x", val, val+2)
1196		}
1197		if x.i != val+1 {
1198			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
1199		}
1200	}
1201	if x.before != magic64 || x.after != magic64 {
1202		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1203	}
1204}
1205
1206func TestCompareAndSwapUint64(t *testing.T) {
1207	testCompareAndSwapUint64(t, CompareAndSwapUint64)
1208}
1209
1210func TestCompareAndSwapUint64Method(t *testing.T) {
1211	var x struct {
1212		before uint64
1213		i      Uint64
1214		after  uint64
1215	}
1216	magic64 := uint64(magic64)
1217	x.before = magic64
1218	x.after = magic64
1219	for val := uint64(1); val+val > val; val += val {
1220		x.i.Store(val)
1221		if !x.i.CompareAndSwap(val, val+1) {
1222			t.Fatalf("should have swapped %#x %#x", val, val+1)
1223		}
1224		if x.i.Load() != val+1 {
1225			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
1226		}
1227		x.i.Store(val + 1)
1228		if x.i.CompareAndSwap(val, val+2) {
1229			t.Fatalf("should not have swapped %#x %#x", val, val+2)
1230		}
1231		if x.i.Load() != val+1 {
1232			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
1233		}
1234	}
1235	if x.before != magic64 || x.after != magic64 {
1236		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1237	}
1238}
1239
1240func TestCompareAndSwapUintptr(t *testing.T) {
1241	var x struct {
1242		before uintptr
1243		i      uintptr
1244		after  uintptr
1245	}
1246	var m uint64 = magic64
1247	magicptr := uintptr(m)
1248	x.before = magicptr
1249	x.after = magicptr
1250	for val := uintptr(1); val+val > val; val += val {
1251		x.i = val
1252		if !CompareAndSwapUintptr(&x.i, val, val+1) {
1253			t.Fatalf("should have swapped %#x %#x", val, val+1)
1254		}
1255		if x.i != val+1 {
1256			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
1257		}
1258		x.i = val + 1
1259		if CompareAndSwapUintptr(&x.i, val, val+2) {
1260			t.Fatalf("should not have swapped %#x %#x", val, val+2)
1261		}
1262		if x.i != val+1 {
1263			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
1264		}
1265	}
1266	if x.before != magicptr || x.after != magicptr {
1267		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
1268	}
1269}
1270
1271func TestCompareAndSwapUintptrMethod(t *testing.T) {
1272	var x struct {
1273		before uintptr
1274		i      Uintptr
1275		after  uintptr
1276	}
1277	var m uint64 = magic64
1278	magicptr := uintptr(m)
1279	x.before = magicptr
1280	x.after = magicptr
1281	for val := uintptr(1); val+val > val; val += val {
1282		x.i.Store(val)
1283		if !x.i.CompareAndSwap(val, val+1) {
1284			t.Fatalf("should have swapped %#x %#x", val, val+1)
1285		}
1286		if x.i.Load() != val+1 {
1287			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
1288		}
1289		x.i.Store(val + 1)
1290		if x.i.CompareAndSwap(val, val+2) {
1291			t.Fatalf("should not have swapped %#x %#x", val, val+2)
1292		}
1293		if x.i.Load() != val+1 {
1294			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
1295		}
1296	}
1297	if x.before != magicptr || x.after != magicptr {
1298		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uintptr(magicptr), uintptr(magicptr))
1299	}
1300}
1301
1302func TestCompareAndSwapPointer(t *testing.T) {
1303	var x struct {
1304		before uintptr
1305		i      unsafe.Pointer
1306		after  uintptr
1307	}
1308	var m uint64 = magic64
1309	magicptr := uintptr(m)
1310	x.before = magicptr
1311	x.after = magicptr
1312	q := unsafe.Pointer(new(byte))
1313	for _, p := range testPointers() {
1314		x.i = p
1315		if !CompareAndSwapPointer(&x.i, p, q) {
1316			t.Fatalf("should have swapped %p %p", p, q)
1317		}
1318		if x.i != q {
1319			t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i, q)
1320		}
1321		if CompareAndSwapPointer(&x.i, p, nil) {
1322			t.Fatalf("should not have swapped %p nil", p)
1323		}
1324		if x.i != q {
1325			t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i, q)
1326		}
1327	}
1328	if x.before != magicptr || x.after != magicptr {
1329		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
1330	}
1331}
1332
1333func TestCompareAndSwapPointerMethod(t *testing.T) {
1334	var x struct {
1335		before uintptr
1336		i      Pointer[byte]
1337		after  uintptr
1338	}
1339	var m uint64 = magic64
1340	magicptr := uintptr(m)
1341	x.before = magicptr
1342	x.after = magicptr
1343	q := new(byte)
1344	for _, p := range testPointers() {
1345		p := (*byte)(p)
1346		x.i.Store(p)
1347		if !x.i.CompareAndSwap(p, q) {
1348			t.Fatalf("should have swapped %p %p", p, q)
1349		}
1350		if x.i.Load() != q {
1351			t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i.Load(), q)
1352		}
1353		if x.i.CompareAndSwap(p, nil) {
1354			t.Fatalf("should not have swapped %p nil", p)
1355		}
1356		if x.i.Load() != q {
1357			t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i.Load(), q)
1358		}
1359	}
1360	if x.before != magicptr || x.after != magicptr {
1361		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
1362	}
1363}
1364
1365func TestLoadInt32(t *testing.T) {
1366	var x struct {
1367		before int32
1368		i      int32
1369		after  int32
1370	}
1371	x.before = magic32
1372	x.after = magic32
1373	for delta := int32(1); delta+delta > delta; delta += delta {
1374		k := LoadInt32(&x.i)
1375		if k != x.i {
1376			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
1377		}
1378		x.i += delta
1379	}
1380	if x.before != magic32 || x.after != magic32 {
1381		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
1382	}
1383}
1384
1385func TestLoadInt32Method(t *testing.T) {
1386	var x struct {
1387		before int32
1388		i      Int32
1389		after  int32
1390	}
1391	x.before = magic32
1392	x.after = magic32
1393	want := int32(0)
1394	for delta := int32(1); delta+delta > delta; delta += delta {
1395		k := x.i.Load()
1396		if k != want {
1397			t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want)
1398		}
1399		x.i.Store(k + delta)
1400		want = k + delta
1401	}
1402	if x.before != magic32 || x.after != magic32 {
1403		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
1404	}
1405}
1406
1407func TestLoadUint32(t *testing.T) {
1408	var x struct {
1409		before uint32
1410		i      uint32
1411		after  uint32
1412	}
1413	x.before = magic32
1414	x.after = magic32
1415	for delta := uint32(1); delta+delta > delta; delta += delta {
1416		k := LoadUint32(&x.i)
1417		if k != x.i {
1418			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
1419		}
1420		x.i += delta
1421	}
1422	if x.before != magic32 || x.after != magic32 {
1423		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
1424	}
1425}
1426
1427func TestLoadUint32Method(t *testing.T) {
1428	var x struct {
1429		before uint32
1430		i      Uint32
1431		after  uint32
1432	}
1433	x.before = magic32
1434	x.after = magic32
1435	want := uint32(0)
1436	for delta := uint32(1); delta+delta > delta; delta += delta {
1437		k := x.i.Load()
1438		if k != want {
1439			t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want)
1440		}
1441		x.i.Store(k + delta)
1442		want = k + delta
1443	}
1444	if x.before != magic32 || x.after != magic32 {
1445		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
1446	}
1447}
1448
1449func TestLoadInt64(t *testing.T) {
1450	var x struct {
1451		before int64
1452		i      int64
1453		after  int64
1454	}
1455	magic64 := int64(magic64)
1456	x.before = magic64
1457	x.after = magic64
1458	for delta := int64(1); delta+delta > delta; delta += delta {
1459		k := LoadInt64(&x.i)
1460		if k != x.i {
1461			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
1462		}
1463		x.i += delta
1464	}
1465	if x.before != magic64 || x.after != magic64 {
1466		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1467	}
1468}
1469
1470func TestLoadInt64Method(t *testing.T) {
1471	var x struct {
1472		before int64
1473		i      Int64
1474		after  int64
1475	}
1476	magic64 := int64(magic64)
1477	x.before = magic64
1478	x.after = magic64
1479	want := int64(0)
1480	for delta := int64(1); delta+delta > delta; delta += delta {
1481		k := x.i.Load()
1482		if k != want {
1483			t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want)
1484		}
1485		x.i.Store(k + delta)
1486		want = k + delta
1487	}
1488	if x.before != magic64 || x.after != magic64 {
1489		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1490	}
1491}
1492
1493func TestLoadUint64(t *testing.T) {
1494	var x struct {
1495		before uint64
1496		i      uint64
1497		after  uint64
1498	}
1499	magic64 := uint64(magic64)
1500	x.before = magic64
1501	x.after = magic64
1502	for delta := uint64(1); delta+delta > delta; delta += delta {
1503		k := LoadUint64(&x.i)
1504		if k != x.i {
1505			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
1506		}
1507		x.i += delta
1508	}
1509	if x.before != magic64 || x.after != magic64 {
1510		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1511	}
1512}
1513
1514func TestLoadUint64Method(t *testing.T) {
1515	var x struct {
1516		before uint64
1517		i      Uint64
1518		after  uint64
1519	}
1520	magic64 := uint64(magic64)
1521	x.before = magic64
1522	x.after = magic64
1523	want := uint64(0)
1524	for delta := uint64(1); delta+delta > delta; delta += delta {
1525		k := x.i.Load()
1526		if k != want {
1527			t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want)
1528		}
1529		x.i.Store(k + delta)
1530		want = k + delta
1531	}
1532	if x.before != magic64 || x.after != magic64 {
1533		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1534	}
1535}
1536
1537func TestLoadUintptr(t *testing.T) {
1538	var x struct {
1539		before uintptr
1540		i      uintptr
1541		after  uintptr
1542	}
1543	var m uint64 = magic64
1544	magicptr := uintptr(m)
1545	x.before = magicptr
1546	x.after = magicptr
1547	for delta := uintptr(1); delta+delta > delta; delta += delta {
1548		k := LoadUintptr(&x.i)
1549		if k != x.i {
1550			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
1551		}
1552		x.i += delta
1553	}
1554	if x.before != magicptr || x.after != magicptr {
1555		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
1556	}
1557}
1558
1559func TestLoadUintptrMethod(t *testing.T) {
1560	var x struct {
1561		before uintptr
1562		i      Uintptr
1563		after  uintptr
1564	}
1565	var m uint64 = magic64
1566	magicptr := uintptr(m)
1567	x.before = magicptr
1568	x.after = magicptr
1569	want := uintptr(0)
1570	for delta := uintptr(1); delta+delta > delta; delta += delta {
1571		k := x.i.Load()
1572		if k != want {
1573			t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want)
1574		}
1575		x.i.Store(k + delta)
1576		want = k + delta
1577	}
1578	if x.before != magicptr || x.after != magicptr {
1579		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
1580	}
1581}
1582
1583func TestLoadPointer(t *testing.T) {
1584	var x struct {
1585		before uintptr
1586		i      unsafe.Pointer
1587		after  uintptr
1588	}
1589	var m uint64 = magic64
1590	magicptr := uintptr(m)
1591	x.before = magicptr
1592	x.after = magicptr
1593	for _, p := range testPointers() {
1594		x.i = p
1595		k := LoadPointer(&x.i)
1596		if k != p {
1597			t.Fatalf("p=%x k=%x", p, k)
1598		}
1599	}
1600	if x.before != magicptr || x.after != magicptr {
1601		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
1602	}
1603}
1604
1605func TestLoadPointerMethod(t *testing.T) {
1606	var x struct {
1607		before uintptr
1608		i      Pointer[byte]
1609		after  uintptr
1610	}
1611	var m uint64 = magic64
1612	magicptr := uintptr(m)
1613	x.before = magicptr
1614	x.after = magicptr
1615	for _, p := range testPointers() {
1616		p := (*byte)(p)
1617		x.i.Store(p)
1618		k := x.i.Load()
1619		if k != p {
1620			t.Fatalf("p=%x k=%x", p, k)
1621		}
1622	}
1623	if x.before != magicptr || x.after != magicptr {
1624		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
1625	}
1626}
1627
1628func TestStoreInt32(t *testing.T) {
1629	var x struct {
1630		before int32
1631		i      int32
1632		after  int32
1633	}
1634	x.before = magic32
1635	x.after = magic32
1636	v := int32(0)
1637	for delta := int32(1); delta+delta > delta; delta += delta {
1638		StoreInt32(&x.i, v)
1639		if x.i != v {
1640			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
1641		}
1642		v += delta
1643	}
1644	if x.before != magic32 || x.after != magic32 {
1645		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
1646	}
1647}
1648
1649func TestStoreInt32Method(t *testing.T) {
1650	var x struct {
1651		before int32
1652		i      Int32
1653		after  int32
1654	}
1655	x.before = magic32
1656	x.after = magic32
1657	v := int32(0)
1658	for delta := int32(1); delta+delta > delta; delta += delta {
1659		x.i.Store(v)
1660		if x.i.Load() != v {
1661			t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v)
1662		}
1663		v += delta
1664	}
1665	if x.before != magic32 || x.after != magic32 {
1666		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
1667	}
1668}
1669
1670func TestStoreUint32(t *testing.T) {
1671	var x struct {
1672		before uint32
1673		i      uint32
1674		after  uint32
1675	}
1676	x.before = magic32
1677	x.after = magic32
1678	v := uint32(0)
1679	for delta := uint32(1); delta+delta > delta; delta += delta {
1680		StoreUint32(&x.i, v)
1681		if x.i != v {
1682			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
1683		}
1684		v += delta
1685	}
1686	if x.before != magic32 || x.after != magic32 {
1687		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
1688	}
1689}
1690
1691func TestStoreUint32Method(t *testing.T) {
1692	var x struct {
1693		before uint32
1694		i      Uint32
1695		after  uint32
1696	}
1697	x.before = magic32
1698	x.after = magic32
1699	v := uint32(0)
1700	for delta := uint32(1); delta+delta > delta; delta += delta {
1701		x.i.Store(v)
1702		if x.i.Load() != v {
1703			t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v)
1704		}
1705		v += delta
1706	}
1707	if x.before != magic32 || x.after != magic32 {
1708		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
1709	}
1710}
1711
1712func TestStoreInt64(t *testing.T) {
1713	var x struct {
1714		before int64
1715		i      int64
1716		after  int64
1717	}
1718	magic64 := int64(magic64)
1719	x.before = magic64
1720	x.after = magic64
1721	v := int64(0)
1722	for delta := int64(1); delta+delta > delta; delta += delta {
1723		StoreInt64(&x.i, v)
1724		if x.i != v {
1725			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
1726		}
1727		v += delta
1728	}
1729	if x.before != magic64 || x.after != magic64 {
1730		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1731	}
1732}
1733
1734func TestStoreInt64Method(t *testing.T) {
1735	var x struct {
1736		before int64
1737		i      Int64
1738		after  int64
1739	}
1740	magic64 := int64(magic64)
1741	x.before = magic64
1742	x.after = magic64
1743	v := int64(0)
1744	for delta := int64(1); delta+delta > delta; delta += delta {
1745		x.i.Store(v)
1746		if x.i.Load() != v {
1747			t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v)
1748		}
1749		v += delta
1750	}
1751	if x.before != magic64 || x.after != magic64 {
1752		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1753	}
1754}
1755
1756func TestStoreUint64(t *testing.T) {
1757	var x struct {
1758		before uint64
1759		i      uint64
1760		after  uint64
1761	}
1762	magic64 := uint64(magic64)
1763	x.before = magic64
1764	x.after = magic64
1765	v := uint64(0)
1766	for delta := uint64(1); delta+delta > delta; delta += delta {
1767		StoreUint64(&x.i, v)
1768		if x.i != v {
1769			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
1770		}
1771		v += delta
1772	}
1773	if x.before != magic64 || x.after != magic64 {
1774		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1775	}
1776}
1777
1778func TestStoreUint64Method(t *testing.T) {
1779	var x struct {
1780		before uint64
1781		i      Uint64
1782		after  uint64
1783	}
1784	magic64 := uint64(magic64)
1785	x.before = magic64
1786	x.after = magic64
1787	v := uint64(0)
1788	for delta := uint64(1); delta+delta > delta; delta += delta {
1789		x.i.Store(v)
1790		if x.i.Load() != v {
1791			t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v)
1792		}
1793		v += delta
1794	}
1795	if x.before != magic64 || x.after != magic64 {
1796		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1797	}
1798}
1799
1800func TestStoreUintptr(t *testing.T) {
1801	var x struct {
1802		before uintptr
1803		i      uintptr
1804		after  uintptr
1805	}
1806	var m uint64 = magic64
1807	magicptr := uintptr(m)
1808	x.before = magicptr
1809	x.after = magicptr
1810	v := uintptr(0)
1811	for delta := uintptr(1); delta+delta > delta; delta += delta {
1812		StoreUintptr(&x.i, v)
1813		if x.i != v {
1814			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
1815		}
1816		v += delta
1817	}
1818	if x.before != magicptr || x.after != magicptr {
1819		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
1820	}
1821}
1822
1823func TestStoreUintptrMethod(t *testing.T) {
1824	var x struct {
1825		before uintptr
1826		i      Uintptr
1827		after  uintptr
1828	}
1829	var m uint64 = magic64
1830	magicptr := uintptr(m)
1831	x.before = magicptr
1832	x.after = magicptr
1833	v := uintptr(0)
1834	for delta := uintptr(1); delta+delta > delta; delta += delta {
1835		x.i.Store(v)
1836		if x.i.Load() != v {
1837			t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v)
1838		}
1839		v += delta
1840	}
1841	if x.before != magicptr || x.after != magicptr {
1842		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
1843	}
1844}
1845
1846func TestStorePointer(t *testing.T) {
1847	var x struct {
1848		before uintptr
1849		i      unsafe.Pointer
1850		after  uintptr
1851	}
1852	var m uint64 = magic64
1853	magicptr := uintptr(m)
1854	x.before = magicptr
1855	x.after = magicptr
1856	for _, p := range testPointers() {
1857		StorePointer(&x.i, p)
1858		if x.i != p {
1859			t.Fatalf("x.i=%p p=%p", x.i, p)
1860		}
1861	}
1862	if x.before != magicptr || x.after != magicptr {
1863		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
1864	}
1865}
1866
1867func TestStorePointerMethod(t *testing.T) {
1868	var x struct {
1869		before uintptr
1870		i      Pointer[byte]
1871		after  uintptr
1872	}
1873	var m uint64 = magic64
1874	magicptr := uintptr(m)
1875	x.before = magicptr
1876	x.after = magicptr
1877	for _, p := range testPointers() {
1878		p := (*byte)(p)
1879		x.i.Store(p)
1880		if x.i.Load() != p {
1881			t.Fatalf("x.i=%p p=%p", x.i.Load(), p)
1882		}
1883	}
1884	if x.before != magicptr || x.after != magicptr {
1885		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
1886	}
1887}
1888
1889// Tests of correct behavior, with contention.
1890// (Is the function atomic?)
1891//
1892// For each function, we write a "hammer" function that repeatedly
1893// uses the atomic operation to add 1 to a value. After running
1894// multiple hammers in parallel, check that we end with the correct
1895// total.
1896// Swap can't add 1, so it uses a different scheme.
1897// The functions repeatedly generate a pseudo-random number such that
1898// low bits are equal to high bits, swap, check that the old value
1899// has low and high bits equal.
1900
1901var hammer32 = map[string]func(*uint32, int){
1902	"SwapInt32":             hammerSwapInt32,
1903	"SwapUint32":            hammerSwapUint32,
1904	"SwapUintptr":           hammerSwapUintptr32,
1905	"AddInt32":              hammerAddInt32,
1906	"AddUint32":             hammerAddUint32,
1907	"AddUintptr":            hammerAddUintptr32,
1908	"CompareAndSwapInt32":   hammerCompareAndSwapInt32,
1909	"CompareAndSwapUint32":  hammerCompareAndSwapUint32,
1910	"CompareAndSwapUintptr": hammerCompareAndSwapUintptr32,
1911
1912	"SwapInt32Method":             hammerSwapInt32Method,
1913	"SwapUint32Method":            hammerSwapUint32Method,
1914	"SwapUintptrMethod":           hammerSwapUintptr32Method,
1915	"AddInt32Method":              hammerAddInt32Method,
1916	"AddUint32Method":             hammerAddUint32Method,
1917	"AddUintptrMethod":            hammerAddUintptr32Method,
1918	"CompareAndSwapInt32Method":   hammerCompareAndSwapInt32Method,
1919	"CompareAndSwapUint32Method":  hammerCompareAndSwapUint32Method,
1920	"CompareAndSwapUintptrMethod": hammerCompareAndSwapUintptr32Method,
1921}
1922
1923func init() {
1924	var v uint64 = 1 << 50
1925	if uintptr(v) != 0 {
1926		// 64-bit system; clear uintptr tests
1927		delete(hammer32, "SwapUintptr")
1928		delete(hammer32, "AddUintptr")
1929		delete(hammer32, "CompareAndSwapUintptr")
1930		delete(hammer32, "SwapUintptrMethod")
1931		delete(hammer32, "AddUintptrMethod")
1932		delete(hammer32, "CompareAndSwapUintptrMethod")
1933	}
1934}
1935
1936func hammerSwapInt32(uaddr *uint32, count int) {
1937	addr := (*int32)(unsafe.Pointer(uaddr))
1938	seed := int(uintptr(unsafe.Pointer(&count)))
1939	for i := 0; i < count; i++ {
1940		new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
1941		old := uint32(SwapInt32(addr, int32(new)))
1942		if old>>16 != old<<16>>16 {
1943			panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old))
1944		}
1945	}
1946}
1947
1948func hammerSwapInt32Method(uaddr *uint32, count int) {
1949	addr := (*Int32)(unsafe.Pointer(uaddr))
1950	seed := int(uintptr(unsafe.Pointer(&count)))
1951	for i := 0; i < count; i++ {
1952		new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
1953		old := uint32(addr.Swap(int32(new)))
1954		if old>>16 != old<<16>>16 {
1955			panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old))
1956		}
1957	}
1958}
1959
1960func hammerSwapUint32(addr *uint32, count int) {
1961	seed := int(uintptr(unsafe.Pointer(&count)))
1962	for i := 0; i < count; i++ {
1963		new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
1964		old := SwapUint32(addr, new)
1965		if old>>16 != old<<16>>16 {
1966			panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old))
1967		}
1968	}
1969}
1970
1971func hammerSwapUint32Method(uaddr *uint32, count int) {
1972	addr := (*Uint32)(unsafe.Pointer(uaddr))
1973	seed := int(uintptr(unsafe.Pointer(&count)))
1974	for i := 0; i < count; i++ {
1975		new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
1976		old := addr.Swap(new)
1977		if old>>16 != old<<16>>16 {
1978			panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old))
1979		}
1980	}
1981}
1982
1983func hammerSwapUintptr32(uaddr *uint32, count int) {
1984	// only safe when uintptr is 32-bit.
1985	// not called on 64-bit systems.
1986	addr := (*uintptr)(unsafe.Pointer(uaddr))
1987	seed := int(uintptr(unsafe.Pointer(&count)))
1988	for i := 0; i < count; i++ {
1989		new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16
1990		old := SwapUintptr(addr, new)
1991		if old>>16 != old<<16>>16 {
1992			panic(fmt.Sprintf("SwapUintptr is not atomic: %#08x", old))
1993		}
1994	}
1995}
1996
1997func hammerSwapUintptr32Method(uaddr *uint32, count int) {
1998	// only safe when uintptr is 32-bit.
1999	// not called on 64-bit systems.
2000	addr := (*Uintptr)(unsafe.Pointer(uaddr))
2001	seed := int(uintptr(unsafe.Pointer(&count)))
2002	for i := 0; i < count; i++ {
2003		new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16
2004		old := addr.Swap(new)
2005		if old>>16 != old<<16>>16 {
2006			panic(fmt.Sprintf("Uintptr.Swap is not atomic: %#08x", old))
2007		}
2008	}
2009}
2010
2011func hammerAddInt32(uaddr *uint32, count int) {
2012	addr := (*int32)(unsafe.Pointer(uaddr))
2013	for i := 0; i < count; i++ {
2014		AddInt32(addr, 1)
2015	}
2016}
2017
2018func hammerAddInt32Method(uaddr *uint32, count int) {
2019	addr := (*Int32)(unsafe.Pointer(uaddr))
2020	for i := 0; i < count; i++ {
2021		addr.Add(1)
2022	}
2023}
2024
2025func hammerAddUint32(addr *uint32, count int) {
2026	for i := 0; i < count; i++ {
2027		AddUint32(addr, 1)
2028	}
2029}
2030
2031func hammerAddUint32Method(uaddr *uint32, count int) {
2032	addr := (*Uint32)(unsafe.Pointer(uaddr))
2033	for i := 0; i < count; i++ {
2034		addr.Add(1)
2035	}
2036}
2037
2038func hammerAddUintptr32(uaddr *uint32, count int) {
2039	// only safe when uintptr is 32-bit.
2040	// not called on 64-bit systems.
2041	addr := (*uintptr)(unsafe.Pointer(uaddr))
2042	for i := 0; i < count; i++ {
2043		AddUintptr(addr, 1)
2044	}
2045}
2046
2047func hammerAddUintptr32Method(uaddr *uint32, count int) {
2048	// only safe when uintptr is 32-bit.
2049	// not called on 64-bit systems.
2050	addr := (*Uintptr)(unsafe.Pointer(uaddr))
2051	for i := 0; i < count; i++ {
2052		addr.Add(1)
2053	}
2054}
2055
2056func hammerCompareAndSwapInt32(uaddr *uint32, count int) {
2057	addr := (*int32)(unsafe.Pointer(uaddr))
2058	for i := 0; i < count; i++ {
2059		for {
2060			v := LoadInt32(addr)
2061			if CompareAndSwapInt32(addr, v, v+1) {
2062				break
2063			}
2064		}
2065	}
2066}
2067
2068func hammerCompareAndSwapInt32Method(uaddr *uint32, count int) {
2069	addr := (*Int32)(unsafe.Pointer(uaddr))
2070	for i := 0; i < count; i++ {
2071		for {
2072			v := addr.Load()
2073			if addr.CompareAndSwap(v, v+1) {
2074				break
2075			}
2076		}
2077	}
2078}
2079
2080func hammerCompareAndSwapUint32(addr *uint32, count int) {
2081	for i := 0; i < count; i++ {
2082		for {
2083			v := LoadUint32(addr)
2084			if CompareAndSwapUint32(addr, v, v+1) {
2085				break
2086			}
2087		}
2088	}
2089}
2090
2091func hammerCompareAndSwapUint32Method(uaddr *uint32, count int) {
2092	addr := (*Uint32)(unsafe.Pointer(uaddr))
2093	for i := 0; i < count; i++ {
2094		for {
2095			v := addr.Load()
2096			if addr.CompareAndSwap(v, v+1) {
2097				break
2098			}
2099		}
2100	}
2101}
2102
2103func hammerCompareAndSwapUintptr32(uaddr *uint32, count int) {
2104	// only safe when uintptr is 32-bit.
2105	// not called on 64-bit systems.
2106	addr := (*uintptr)(unsafe.Pointer(uaddr))
2107	for i := 0; i < count; i++ {
2108		for {
2109			v := LoadUintptr(addr)
2110			if CompareAndSwapUintptr(addr, v, v+1) {
2111				break
2112			}
2113		}
2114	}
2115}
2116
2117func hammerCompareAndSwapUintptr32Method(uaddr *uint32, count int) {
2118	// only safe when uintptr is 32-bit.
2119	// not called on 64-bit systems.
2120	addr := (*Uintptr)(unsafe.Pointer(uaddr))
2121	for i := 0; i < count; i++ {
2122		for {
2123			v := addr.Load()
2124			if addr.CompareAndSwap(v, v+1) {
2125				break
2126			}
2127		}
2128	}
2129}
2130
2131func TestHammer32(t *testing.T) {
2132	const p = 4
2133	n := 100000
2134	if testing.Short() {
2135		n = 1000
2136	}
2137	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
2138
2139	for name, testf := range hammer32 {
2140		c := make(chan int)
2141		var val uint32
2142		for i := 0; i < p; i++ {
2143			go func() {
2144				defer func() {
2145					if err := recover(); err != nil {
2146						t.Error(err.(string))
2147					}
2148					c <- 1
2149				}()
2150				testf(&val, n)
2151			}()
2152		}
2153		for i := 0; i < p; i++ {
2154			<-c
2155		}
2156		if !strings.HasPrefix(name, "Swap") && val != uint32(n)*p {
2157			t.Fatalf("%s: val=%d want %d", name, val, n*p)
2158		}
2159	}
2160}
2161
2162var hammer64 = map[string]func(*uint64, int){
2163	"SwapInt64":             hammerSwapInt64,
2164	"SwapUint64":            hammerSwapUint64,
2165	"SwapUintptr":           hammerSwapUintptr64,
2166	"AddInt64":              hammerAddInt64,
2167	"AddUint64":             hammerAddUint64,
2168	"AddUintptr":            hammerAddUintptr64,
2169	"CompareAndSwapInt64":   hammerCompareAndSwapInt64,
2170	"CompareAndSwapUint64":  hammerCompareAndSwapUint64,
2171	"CompareAndSwapUintptr": hammerCompareAndSwapUintptr64,
2172
2173	"SwapInt64Method":             hammerSwapInt64Method,
2174	"SwapUint64Method":            hammerSwapUint64Method,
2175	"SwapUintptrMethod":           hammerSwapUintptr64Method,
2176	"AddInt64Method":              hammerAddInt64Method,
2177	"AddUint64Method":             hammerAddUint64Method,
2178	"AddUintptrMethod":            hammerAddUintptr64Method,
2179	"CompareAndSwapInt64Method":   hammerCompareAndSwapInt64Method,
2180	"CompareAndSwapUint64Method":  hammerCompareAndSwapUint64Method,
2181	"CompareAndSwapUintptrMethod": hammerCompareAndSwapUintptr64Method,
2182}
2183
2184func init() {
2185	var v uint64 = 1 << 50
2186	if uintptr(v) == 0 {
2187		// 32-bit system; clear uintptr tests
2188		delete(hammer64, "SwapUintptr")
2189		delete(hammer64, "SwapUintptrMethod")
2190		delete(hammer64, "AddUintptr")
2191		delete(hammer64, "AddUintptrMethod")
2192		delete(hammer64, "CompareAndSwapUintptr")
2193		delete(hammer64, "CompareAndSwapUintptrMethod")
2194	}
2195}
2196
2197func hammerSwapInt64(uaddr *uint64, count int) {
2198	addr := (*int64)(unsafe.Pointer(uaddr))
2199	seed := int(uintptr(unsafe.Pointer(&count)))
2200	for i := 0; i < count; i++ {
2201		new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
2202		old := uint64(SwapInt64(addr, int64(new)))
2203		if old>>32 != old<<32>>32 {
2204			panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old))
2205		}
2206	}
2207}
2208
2209func hammerSwapInt64Method(uaddr *uint64, count int) {
2210	addr := (*Int64)(unsafe.Pointer(uaddr))
2211	seed := int(uintptr(unsafe.Pointer(&count)))
2212	for i := 0; i < count; i++ {
2213		new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
2214		old := uint64(addr.Swap(int64(new)))
2215		if old>>32 != old<<32>>32 {
2216			panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old))
2217		}
2218	}
2219}
2220
2221func hammerSwapUint64(addr *uint64, count int) {
2222	seed := int(uintptr(unsafe.Pointer(&count)))
2223	for i := 0; i < count; i++ {
2224		new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
2225		old := SwapUint64(addr, new)
2226		if old>>32 != old<<32>>32 {
2227			panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old))
2228		}
2229	}
2230}
2231
2232func hammerSwapUint64Method(uaddr *uint64, count int) {
2233	addr := (*Uint64)(unsafe.Pointer(uaddr))
2234	seed := int(uintptr(unsafe.Pointer(&count)))
2235	for i := 0; i < count; i++ {
2236		new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
2237		old := addr.Swap(new)
2238		if old>>32 != old<<32>>32 {
2239			panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old))
2240		}
2241	}
2242}
2243
2244const arch32 = unsafe.Sizeof(uintptr(0)) == 4
2245
2246func hammerSwapUintptr64(uaddr *uint64, count int) {
2247	// only safe when uintptr is 64-bit.
2248	// not called on 32-bit systems.
2249	if !arch32 {
2250		addr := (*uintptr)(unsafe.Pointer(uaddr))
2251		seed := int(uintptr(unsafe.Pointer(&count)))
2252		for i := 0; i < count; i++ {
2253			new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32
2254			old := SwapUintptr(addr, new)
2255			if old>>32 != old<<32>>32 {
2256				panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old))
2257			}
2258		}
2259	}
2260}
2261
2262func hammerSwapUintptr64Method(uaddr *uint64, count int) {
2263	// only safe when uintptr is 64-bit.
2264	// not called on 32-bit systems.
2265	if !arch32 {
2266		addr := (*Uintptr)(unsafe.Pointer(uaddr))
2267		seed := int(uintptr(unsafe.Pointer(&count)))
2268		for i := 0; i < count; i++ {
2269			new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32
2270			old := addr.Swap(new)
2271			if old>>32 != old<<32>>32 {
2272				panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old))
2273			}
2274		}
2275	}
2276}
2277
2278func hammerAddInt64(uaddr *uint64, count int) {
2279	addr := (*int64)(unsafe.Pointer(uaddr))
2280	for i := 0; i < count; i++ {
2281		AddInt64(addr, 1)
2282	}
2283}
2284
2285func hammerAddInt64Method(uaddr *uint64, count int) {
2286	addr := (*Int64)(unsafe.Pointer(uaddr))
2287	for i := 0; i < count; i++ {
2288		addr.Add(1)
2289	}
2290}
2291
2292func hammerAddUint64(addr *uint64, count int) {
2293	for i := 0; i < count; i++ {
2294		AddUint64(addr, 1)
2295	}
2296}
2297
2298func hammerAddUint64Method(uaddr *uint64, count int) {
2299	addr := (*Uint64)(unsafe.Pointer(uaddr))
2300	for i := 0; i < count; i++ {
2301		addr.Add(1)
2302	}
2303}
2304
2305func hammerAddUintptr64(uaddr *uint64, count int) {
2306	// only safe when uintptr is 64-bit.
2307	// not called on 32-bit systems.
2308	addr := (*uintptr)(unsafe.Pointer(uaddr))
2309	for i := 0; i < count; i++ {
2310		AddUintptr(addr, 1)
2311	}
2312}
2313
2314func hammerAddUintptr64Method(uaddr *uint64, count int) {
2315	// only safe when uintptr is 64-bit.
2316	// not called on 32-bit systems.
2317	addr := (*Uintptr)(unsafe.Pointer(uaddr))
2318	for i := 0; i < count; i++ {
2319		addr.Add(1)
2320	}
2321}
2322
2323func hammerCompareAndSwapInt64(uaddr *uint64, count int) {
2324	addr := (*int64)(unsafe.Pointer(uaddr))
2325	for i := 0; i < count; i++ {
2326		for {
2327			v := LoadInt64(addr)
2328			if CompareAndSwapInt64(addr, v, v+1) {
2329				break
2330			}
2331		}
2332	}
2333}
2334
2335func hammerCompareAndSwapInt64Method(uaddr *uint64, count int) {
2336	addr := (*Int64)(unsafe.Pointer(uaddr))
2337	for i := 0; i < count; i++ {
2338		for {
2339			v := addr.Load()
2340			if addr.CompareAndSwap(v, v+1) {
2341				break
2342			}
2343		}
2344	}
2345}
2346
2347func hammerCompareAndSwapUint64(addr *uint64, count int) {
2348	for i := 0; i < count; i++ {
2349		for {
2350			v := LoadUint64(addr)
2351			if CompareAndSwapUint64(addr, v, v+1) {
2352				break
2353			}
2354		}
2355	}
2356}
2357
2358func hammerCompareAndSwapUint64Method(uaddr *uint64, count int) {
2359	addr := (*Uint64)(unsafe.Pointer(uaddr))
2360	for i := 0; i < count; i++ {
2361		for {
2362			v := addr.Load()
2363			if addr.CompareAndSwap(v, v+1) {
2364				break
2365			}
2366		}
2367	}
2368}
2369
2370func hammerCompareAndSwapUintptr64(uaddr *uint64, count int) {
2371	// only safe when uintptr is 64-bit.
2372	// not called on 32-bit systems.
2373	addr := (*uintptr)(unsafe.Pointer(uaddr))
2374	for i := 0; i < count; i++ {
2375		for {
2376			v := LoadUintptr(addr)
2377			if CompareAndSwapUintptr(addr, v, v+1) {
2378				break
2379			}
2380		}
2381	}
2382}
2383
2384func hammerCompareAndSwapUintptr64Method(uaddr *uint64, count int) {
2385	// only safe when uintptr is 64-bit.
2386	// not called on 32-bit systems.
2387	addr := (*Uintptr)(unsafe.Pointer(uaddr))
2388	for i := 0; i < count; i++ {
2389		for {
2390			v := addr.Load()
2391			if addr.CompareAndSwap(v, v+1) {
2392				break
2393			}
2394		}
2395	}
2396}
2397
2398func TestHammer64(t *testing.T) {
2399	const p = 4
2400	n := 100000
2401	if testing.Short() {
2402		n = 1000
2403	}
2404	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
2405
2406	for name, testf := range hammer64 {
2407		c := make(chan int)
2408		var val uint64
2409		for i := 0; i < p; i++ {
2410			go func() {
2411				defer func() {
2412					if err := recover(); err != nil {
2413						t.Error(err.(string))
2414					}
2415					c <- 1
2416				}()
2417				testf(&val, n)
2418			}()
2419		}
2420		for i := 0; i < p; i++ {
2421			<-c
2422		}
2423		if !strings.HasPrefix(name, "Swap") && val != uint64(n)*p {
2424			t.Fatalf("%s: val=%d want %d", name, val, n*p)
2425		}
2426	}
2427}
2428
2429func hammerStoreLoadInt32(t *testing.T, paddr unsafe.Pointer) {
2430	addr := (*int32)(paddr)
2431	v := LoadInt32(addr)
2432	vlo := v & ((1 << 16) - 1)
2433	vhi := v >> 16
2434	if vlo != vhi {
2435		t.Fatalf("Int32: %#x != %#x", vlo, vhi)
2436	}
2437	new := v + 1 + 1<<16
2438	if vlo == 1e4 {
2439		new = 0
2440	}
2441	StoreInt32(addr, new)
2442}
2443
2444func hammerStoreLoadInt32Method(t *testing.T, paddr unsafe.Pointer) {
2445	addr := (*int32)(paddr)
2446	v := LoadInt32(addr)
2447	vlo := v & ((1 << 16) - 1)
2448	vhi := v >> 16
2449	if vlo != vhi {
2450		t.Fatalf("Int32: %#x != %#x", vlo, vhi)
2451	}
2452	new := v + 1 + 1<<16
2453	if vlo == 1e4 {
2454		new = 0
2455	}
2456	StoreInt32(addr, new)
2457}
2458
2459func hammerStoreLoadUint32(t *testing.T, paddr unsafe.Pointer) {
2460	addr := (*uint32)(paddr)
2461	v := LoadUint32(addr)
2462	vlo := v & ((1 << 16) - 1)
2463	vhi := v >> 16
2464	if vlo != vhi {
2465		t.Fatalf("Uint32: %#x != %#x", vlo, vhi)
2466	}
2467	new := v + 1 + 1<<16
2468	if vlo == 1e4 {
2469		new = 0
2470	}
2471	StoreUint32(addr, new)
2472}
2473
2474func hammerStoreLoadUint32Method(t *testing.T, paddr unsafe.Pointer) {
2475	addr := (*Uint32)(paddr)
2476	v := addr.Load()
2477	vlo := v & ((1 << 16) - 1)
2478	vhi := v >> 16
2479	if vlo != vhi {
2480		t.Fatalf("Uint32: %#x != %#x", vlo, vhi)
2481	}
2482	new := v + 1 + 1<<16
2483	if vlo == 1e4 {
2484		new = 0
2485	}
2486	addr.Store(new)
2487}
2488
2489func hammerStoreLoadInt64(t *testing.T, paddr unsafe.Pointer) {
2490	addr := (*int64)(paddr)
2491	v := LoadInt64(addr)
2492	vlo := v & ((1 << 32) - 1)
2493	vhi := v >> 32
2494	if vlo != vhi {
2495		t.Fatalf("Int64: %#x != %#x", vlo, vhi)
2496	}
2497	new := v + 1 + 1<<32
2498	StoreInt64(addr, new)
2499}
2500
2501func hammerStoreLoadInt64Method(t *testing.T, paddr unsafe.Pointer) {
2502	addr := (*Int64)(paddr)
2503	v := addr.Load()
2504	vlo := v & ((1 << 32) - 1)
2505	vhi := v >> 32
2506	if vlo != vhi {
2507		t.Fatalf("Int64: %#x != %#x", vlo, vhi)
2508	}
2509	new := v + 1 + 1<<32
2510	addr.Store(new)
2511}
2512
2513func hammerStoreLoadUint64(t *testing.T, paddr unsafe.Pointer) {
2514	addr := (*uint64)(paddr)
2515	v := LoadUint64(addr)
2516	vlo := v & ((1 << 32) - 1)
2517	vhi := v >> 32
2518	if vlo != vhi {
2519		t.Fatalf("Uint64: %#x != %#x", vlo, vhi)
2520	}
2521	new := v + 1 + 1<<32
2522	StoreUint64(addr, new)
2523}
2524
2525func hammerStoreLoadUint64Method(t *testing.T, paddr unsafe.Pointer) {
2526	addr := (*Uint64)(paddr)
2527	v := addr.Load()
2528	vlo := v & ((1 << 32) - 1)
2529	vhi := v >> 32
2530	if vlo != vhi {
2531		t.Fatalf("Uint64: %#x != %#x", vlo, vhi)
2532	}
2533	new := v + 1 + 1<<32
2534	addr.Store(new)
2535}
2536
2537func hammerStoreLoadUintptr(t *testing.T, paddr unsafe.Pointer) {
2538	addr := (*uintptr)(paddr)
2539	v := LoadUintptr(addr)
2540	new := v
2541	if arch32 {
2542		vlo := v & ((1 << 16) - 1)
2543		vhi := v >> 16
2544		if vlo != vhi {
2545			t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
2546		}
2547		new = v + 1 + 1<<16
2548		if vlo == 1e4 {
2549			new = 0
2550		}
2551	} else {
2552		vlo := v & ((1 << 32) - 1)
2553		vhi := v >> 32
2554		if vlo != vhi {
2555			t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
2556		}
2557		inc := uint64(1 + 1<<32)
2558		new = v + uintptr(inc)
2559	}
2560	StoreUintptr(addr, new)
2561}
2562
2563//go:nocheckptr
2564func hammerStoreLoadUintptrMethod(t *testing.T, paddr unsafe.Pointer) {
2565	addr := (*Uintptr)(paddr)
2566	v := addr.Load()
2567	new := v
2568	if arch32 {
2569		vlo := v & ((1 << 16) - 1)
2570		vhi := v >> 16
2571		if vlo != vhi {
2572			t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
2573		}
2574		new = v + 1 + 1<<16
2575		if vlo == 1e4 {
2576			new = 0
2577		}
2578	} else {
2579		vlo := v & ((1 << 32) - 1)
2580		vhi := v >> 32
2581		if vlo != vhi {
2582			t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
2583		}
2584		inc := uint64(1 + 1<<32)
2585		new = v + uintptr(inc)
2586	}
2587	addr.Store(new)
2588}
2589
2590// This code is just testing that LoadPointer/StorePointer operate
2591// atomically; it's not actually calculating pointers.
2592//
2593//go:nocheckptr
2594func hammerStoreLoadPointer(t *testing.T, paddr unsafe.Pointer) {
2595	addr := (*unsafe.Pointer)(paddr)
2596	v := uintptr(LoadPointer(addr))
2597	new := v
2598	if arch32 {
2599		vlo := v & ((1 << 16) - 1)
2600		vhi := v >> 16
2601		if vlo != vhi {
2602			t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
2603		}
2604		new = v + 1 + 1<<16
2605		if vlo == 1e4 {
2606			new = 0
2607		}
2608	} else {
2609		vlo := v & ((1 << 32) - 1)
2610		vhi := v >> 32
2611		if vlo != vhi {
2612			t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
2613		}
2614		inc := uint64(1 + 1<<32)
2615		new = v + uintptr(inc)
2616	}
2617	StorePointer(addr, unsafe.Pointer(new))
2618}
2619
2620// This code is just testing that LoadPointer/StorePointer operate
2621// atomically; it's not actually calculating pointers.
2622//
2623//go:nocheckptr
2624func hammerStoreLoadPointerMethod(t *testing.T, paddr unsafe.Pointer) {
2625	addr := (*Pointer[byte])(paddr)
2626	v := uintptr(unsafe.Pointer(addr.Load()))
2627	new := v
2628	if arch32 {
2629		vlo := v & ((1 << 16) - 1)
2630		vhi := v >> 16
2631		if vlo != vhi {
2632			t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
2633		}
2634		new = v + 1 + 1<<16
2635		if vlo == 1e4 {
2636			new = 0
2637		}
2638	} else {
2639		vlo := v & ((1 << 32) - 1)
2640		vhi := v >> 32
2641		if vlo != vhi {
2642			t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
2643		}
2644		inc := uint64(1 + 1<<32)
2645		new = v + uintptr(inc)
2646	}
2647	addr.Store((*byte)(unsafe.Pointer(new)))
2648}
2649
2650func TestHammerStoreLoad(t *testing.T) {
2651	tests := []func(*testing.T, unsafe.Pointer){
2652		hammerStoreLoadInt32, hammerStoreLoadUint32,
2653		hammerStoreLoadUintptr, hammerStoreLoadPointer,
2654		hammerStoreLoadInt32Method, hammerStoreLoadUint32Method,
2655		hammerStoreLoadUintptrMethod, hammerStoreLoadPointerMethod,
2656		hammerStoreLoadInt64, hammerStoreLoadUint64,
2657		hammerStoreLoadInt64Method, hammerStoreLoadUint64Method,
2658	}
2659	n := int(1e6)
2660	if testing.Short() {
2661		n = int(1e4)
2662	}
2663	const procs = 8
2664	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(procs))
2665	// Disable the GC because hammerStoreLoadPointer invokes
2666	// write barriers on values that aren't real pointers.
2667	defer debug.SetGCPercent(debug.SetGCPercent(-1))
2668	// Ensure any in-progress GC is finished.
2669	runtime.GC()
2670	for _, tt := range tests {
2671		c := make(chan int)
2672		var val uint64
2673		for p := 0; p < procs; p++ {
2674			go func() {
2675				for i := 0; i < n; i++ {
2676					tt(t, unsafe.Pointer(&val))
2677				}
2678				c <- 1
2679			}()
2680		}
2681		for p := 0; p < procs; p++ {
2682			<-c
2683		}
2684	}
2685}
2686
2687func TestStoreLoadSeqCst32(t *testing.T) {
2688	if runtime.NumCPU() == 1 {
2689		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
2690	}
2691	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
2692	N := int32(1e3)
2693	if testing.Short() {
2694		N = int32(1e2)
2695	}
2696	c := make(chan bool, 2)
2697	X := [2]int32{}
2698	ack := [2][3]int32{{-1, -1, -1}, {-1, -1, -1}}
2699	for p := 0; p < 2; p++ {
2700		go func(me int) {
2701			he := 1 - me
2702			for i := int32(1); i < N; i++ {
2703				StoreInt32(&X[me], i)
2704				my := LoadInt32(&X[he])
2705				StoreInt32(&ack[me][i%3], my)
2706				for w := 1; LoadInt32(&ack[he][i%3]) == -1; w++ {
2707					if w%1000 == 0 {
2708						runtime.Gosched()
2709					}
2710				}
2711				his := LoadInt32(&ack[he][i%3])
2712				if (my != i && my != i-1) || (his != i && his != i-1) {
2713					t.Errorf("invalid values: %d/%d (%d)", my, his, i)
2714					break
2715				}
2716				if my != i && his != i {
2717					t.Errorf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
2718					break
2719				}
2720				StoreInt32(&ack[me][(i-1)%3], -1)
2721			}
2722			c <- true
2723		}(p)
2724	}
2725	<-c
2726	<-c
2727}
2728
2729func TestStoreLoadSeqCst64(t *testing.T) {
2730	if runtime.NumCPU() == 1 {
2731		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
2732	}
2733	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
2734	N := int64(1e3)
2735	if testing.Short() {
2736		N = int64(1e2)
2737	}
2738	c := make(chan bool, 2)
2739	X := [2]int64{}
2740	ack := [2][3]int64{{-1, -1, -1}, {-1, -1, -1}}
2741	for p := 0; p < 2; p++ {
2742		go func(me int) {
2743			he := 1 - me
2744			for i := int64(1); i < N; i++ {
2745				StoreInt64(&X[me], i)
2746				my := LoadInt64(&X[he])
2747				StoreInt64(&ack[me][i%3], my)
2748				for w := 1; LoadInt64(&ack[he][i%3]) == -1; w++ {
2749					if w%1000 == 0 {
2750						runtime.Gosched()
2751					}
2752				}
2753				his := LoadInt64(&ack[he][i%3])
2754				if (my != i && my != i-1) || (his != i && his != i-1) {
2755					t.Errorf("invalid values: %d/%d (%d)", my, his, i)
2756					break
2757				}
2758				if my != i && his != i {
2759					t.Errorf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
2760					break
2761				}
2762				StoreInt64(&ack[me][(i-1)%3], -1)
2763			}
2764			c <- true
2765		}(p)
2766	}
2767	<-c
2768	<-c
2769}
2770
2771func TestStoreLoadRelAcq32(t *testing.T) {
2772	if runtime.NumCPU() == 1 {
2773		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
2774	}
2775	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
2776	N := int32(1e3)
2777	if testing.Short() {
2778		N = int32(1e2)
2779	}
2780	c := make(chan bool, 2)
2781	type Data struct {
2782		signal int32
2783		pad1   [128]int8
2784		data1  int32
2785		pad2   [128]int8
2786		data2  float32
2787	}
2788	var X Data
2789	for p := int32(0); p < 2; p++ {
2790		go func(p int32) {
2791			for i := int32(1); i < N; i++ {
2792				if (i+p)%2 == 0 {
2793					X.data1 = i
2794					X.data2 = float32(i)
2795					StoreInt32(&X.signal, i)
2796				} else {
2797					for w := 1; LoadInt32(&X.signal) != i; w++ {
2798						if w%1000 == 0 {
2799							runtime.Gosched()
2800						}
2801					}
2802					d1 := X.data1
2803					d2 := X.data2
2804					if d1 != i || d2 != float32(i) {
2805						t.Errorf("incorrect data: %d/%g (%d)", d1, d2, i)
2806						break
2807					}
2808				}
2809			}
2810			c <- true
2811		}(p)
2812	}
2813	<-c
2814	<-c
2815}
2816
2817func TestStoreLoadRelAcq64(t *testing.T) {
2818	if runtime.NumCPU() == 1 {
2819		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
2820	}
2821	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
2822	N := int64(1e3)
2823	if testing.Short() {
2824		N = int64(1e2)
2825	}
2826	c := make(chan bool, 2)
2827	type Data struct {
2828		signal int64
2829		pad1   [128]int8
2830		data1  int64
2831		pad2   [128]int8
2832		data2  float64
2833	}
2834	var X Data
2835	for p := int64(0); p < 2; p++ {
2836		go func(p int64) {
2837			for i := int64(1); i < N; i++ {
2838				if (i+p)%2 == 0 {
2839					X.data1 = i
2840					X.data2 = float64(i)
2841					StoreInt64(&X.signal, i)
2842				} else {
2843					for w := 1; LoadInt64(&X.signal) != i; w++ {
2844						if w%1000 == 0 {
2845							runtime.Gosched()
2846						}
2847					}
2848					d1 := X.data1
2849					d2 := X.data2
2850					if d1 != i || d2 != float64(i) {
2851						t.Errorf("incorrect data: %d/%g (%d)", d1, d2, i)
2852						break
2853					}
2854				}
2855			}
2856			c <- true
2857		}(p)
2858	}
2859	<-c
2860	<-c
2861}
2862
2863func shouldPanic(t *testing.T, name string, f func()) {
2864	defer func() {
2865		// Check that all GC maps are sane.
2866		runtime.GC()
2867
2868		err := recover()
2869		want := "unaligned 64-bit atomic operation"
2870		if err == nil {
2871			t.Errorf("%s did not panic", name)
2872		} else if s, _ := err.(string); s != want {
2873			t.Errorf("%s: wanted panic %q, got %q", name, want, err)
2874		}
2875	}()
2876	f()
2877}
2878
2879func TestUnaligned64(t *testing.T) {
2880	// Unaligned 64-bit atomics on 32-bit systems are
2881	// a continual source of pain. Test that on 32-bit systems they crash
2882	// instead of failing silently.
2883	if !arch32 {
2884		t.Skip("test only runs on 32-bit systems")
2885	}
2886
2887	x := make([]uint32, 4)
2888	p := (*uint64)(unsafe.Pointer(&x[1])) // misaligned
2889
2890	shouldPanic(t, "LoadUint64", func() { LoadUint64(p) })
2891	shouldPanic(t, "LoadUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).Load() })
2892	shouldPanic(t, "StoreUint64", func() { StoreUint64(p, 1) })
2893	shouldPanic(t, "StoreUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).Store(1) })
2894	shouldPanic(t, "CompareAndSwapUint64", func() { CompareAndSwapUint64(p, 1, 2) })
2895	shouldPanic(t, "CompareAndSwapUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).CompareAndSwap(1, 2) })
2896	shouldPanic(t, "AddUint64", func() { AddUint64(p, 3) })
2897	shouldPanic(t, "AddUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).Add(3) })
2898}
2899
2900func TestAutoAligned64(t *testing.T) {
2901	var signed struct {
2902		_ uint32
2903		i Int64
2904	}
2905	if o := reflect.TypeOf(&signed).Elem().Field(1).Offset; o != 8 {
2906		t.Fatalf("Int64 offset = %d, want 8", o)
2907	}
2908	if p := reflect.ValueOf(&signed).Elem().Field(1).Addr().Pointer(); p&7 != 0 {
2909		t.Fatalf("Int64 pointer = %#x, want 8-aligned", p)
2910	}
2911
2912	var unsigned struct {
2913		_ uint32
2914		i Uint64
2915	}
2916	if o := reflect.TypeOf(&unsigned).Elem().Field(1).Offset; o != 8 {
2917		t.Fatalf("Uint64 offset = %d, want 8", o)
2918	}
2919	if p := reflect.ValueOf(&unsigned).Elem().Field(1).Addr().Pointer(); p&7 != 0 {
2920		t.Fatalf("Int64 pointer = %#x, want 8-aligned", p)
2921	}
2922}
2923
2924func TestNilDeref(t *testing.T) {
2925	funcs := [...]func(){
2926		func() { CompareAndSwapInt32(nil, 0, 0) },
2927		func() { (*Int32)(nil).CompareAndSwap(0, 0) },
2928		func() { CompareAndSwapInt64(nil, 0, 0) },
2929		func() { (*Int64)(nil).CompareAndSwap(0, 0) },
2930		func() { CompareAndSwapUint32(nil, 0, 0) },
2931		func() { (*Uint32)(nil).CompareAndSwap(0, 0) },
2932		func() { CompareAndSwapUint64(nil, 0, 0) },
2933		func() { (*Uint64)(nil).CompareAndSwap(0, 0) },
2934		func() { CompareAndSwapUintptr(nil, 0, 0) },
2935		func() { (*Uintptr)(nil).CompareAndSwap(0, 0) },
2936		func() { CompareAndSwapPointer(nil, nil, nil) },
2937		func() { (*Pointer[byte])(nil).CompareAndSwap(nil, nil) },
2938		func() { SwapInt32(nil, 0) },
2939		func() { (*Int32)(nil).Swap(0) },
2940		func() { SwapUint32(nil, 0) },
2941		func() { (*Uint32)(nil).Swap(0) },
2942		func() { SwapInt64(nil, 0) },
2943		func() { (*Int64)(nil).Swap(0) },
2944		func() { SwapUint64(nil, 0) },
2945		func() { (*Uint64)(nil).Swap(0) },
2946		func() { SwapUintptr(nil, 0) },
2947		func() { (*Uintptr)(nil).Swap(0) },
2948		func() { SwapPointer(nil, nil) },
2949		func() { (*Pointer[byte])(nil).Swap(nil) },
2950		func() { AddInt32(nil, 0) },
2951		func() { (*Int32)(nil).Add(0) },
2952		func() { AddUint32(nil, 0) },
2953		func() { (*Uint32)(nil).Add(0) },
2954		func() { AddInt64(nil, 0) },
2955		func() { (*Int64)(nil).Add(0) },
2956		func() { AddUint64(nil, 0) },
2957		func() { (*Uint64)(nil).Add(0) },
2958		func() { AddUintptr(nil, 0) },
2959		func() { (*Uintptr)(nil).Add(0) },
2960		func() { LoadInt32(nil) },
2961		func() { (*Int32)(nil).Load() },
2962		func() { LoadInt64(nil) },
2963		func() { (*Int64)(nil).Load() },
2964		func() { LoadUint32(nil) },
2965		func() { (*Uint32)(nil).Load() },
2966		func() { LoadUint64(nil) },
2967		func() { (*Uint64)(nil).Load() },
2968		func() { LoadUintptr(nil) },
2969		func() { (*Uintptr)(nil).Load() },
2970		func() { LoadPointer(nil) },
2971		func() { (*Pointer[byte])(nil).Load() },
2972		func() { StoreInt32(nil, 0) },
2973		func() { (*Int32)(nil).Store(0) },
2974		func() { StoreInt64(nil, 0) },
2975		func() { (*Int64)(nil).Store(0) },
2976		func() { StoreUint32(nil, 0) },
2977		func() { (*Uint32)(nil).Store(0) },
2978		func() { StoreUint64(nil, 0) },
2979		func() { (*Uint64)(nil).Store(0) },
2980		func() { StoreUintptr(nil, 0) },
2981		func() { (*Uintptr)(nil).Store(0) },
2982		func() { StorePointer(nil, nil) },
2983		func() { (*Pointer[byte])(nil).Store(nil) },
2984	}
2985	for _, f := range funcs {
2986		func() {
2987			defer func() {
2988				runtime.GC()
2989				recover()
2990			}()
2991			f()
2992		}()
2993	}
2994}
2995
2996// Test that this compiles.
2997// When atomic.Pointer used _ [0]T, it did not.
2998type List struct {
2999	Next Pointer[List]
3000}
3001