Source file
src/sync/atomic/atomic_test.go
1
2
3
4
5 package atomic_test
6
7 import (
8 "fmt"
9 "reflect"
10 "runtime"
11 "runtime/debug"
12 "strings"
13 . "sync/atomic"
14 "testing"
15 "unsafe"
16 )
17
18
19
20
21
22
23
24
25
26
27
28
29
30 const (
31 magic32 = 0xdedbeef
32 magic64 = 0xdeddeadbeefbeef
33 )
34
35 func 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
56 func 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
77 func 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
98 func 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
119 func 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
141 func 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
163 func 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
185 func 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
207 func 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
230 func 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
253 var global [1024]byte
254
255 func testPointers() []unsafe.Pointer {
256 var pointers []unsafe.Pointer
257
258 for i := 0; i < 10; i++ {
259 pointers = append(pointers, unsafe.Pointer(&global[1<<i-1]))
260 }
261
262 pointers = append(pointers, unsafe.Pointer(new(byte)))
263
264 pointers = append(pointers, nil)
265 return pointers
266 }
267
268 func 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
292 func 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
316 func 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
337 func 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
358 func 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
379 func 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
400 func 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
422 func 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
444 func 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
466 func 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
488 func 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
511 func 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
534 func 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
557 func 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
580 func 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
603 func 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
626 func 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
650 func 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
674 func 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
698 func 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
722 func 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
747 func 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
772 func 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
794 func 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
816 func 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
838 func 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
860 func 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
883 func 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
906 func 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
929 func 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
952 func 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
976 func 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
1000 func 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
1029 func 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
1058 func 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
1087 func 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
1116 func 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
1146 func 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
1176 func 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
1206 func TestCompareAndSwapUint64(t *testing.T) {
1207 testCompareAndSwapUint64(t, CompareAndSwapUint64)
1208 }
1209
1210 func 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
1240 func 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
1271 func 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
1302 func 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
1333 func 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
1365 func 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
1385 func 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
1407 func 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
1427 func 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
1449 func 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
1470 func 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
1493 func 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
1514 func 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
1537 func 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
1559 func 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
1583 func 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
1605 func 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
1628 func 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
1649 func 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
1670 func 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
1691 func 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
1712 func 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
1734 func 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
1756 func 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
1778 func 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
1800 func 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
1823 func 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
1846 func 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
1867 func 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
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901 var 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
1923 func init() {
1924 var v uint64 = 1 << 50
1925 if uintptr(v) != 0 {
1926
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
1936 func 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
1948 func 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
1960 func 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
1971 func 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
1983 func hammerSwapUintptr32(uaddr *uint32, count int) {
1984
1985
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
1997 func hammerSwapUintptr32Method(uaddr *uint32, count int) {
1998
1999
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
2011 func 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
2018 func 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
2025 func hammerAddUint32(addr *uint32, count int) {
2026 for i := 0; i < count; i++ {
2027 AddUint32(addr, 1)
2028 }
2029 }
2030
2031 func 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
2038 func hammerAddUintptr32(uaddr *uint32, count int) {
2039
2040
2041 addr := (*uintptr)(unsafe.Pointer(uaddr))
2042 for i := 0; i < count; i++ {
2043 AddUintptr(addr, 1)
2044 }
2045 }
2046
2047 func hammerAddUintptr32Method(uaddr *uint32, count int) {
2048
2049
2050 addr := (*Uintptr)(unsafe.Pointer(uaddr))
2051 for i := 0; i < count; i++ {
2052 addr.Add(1)
2053 }
2054 }
2055
2056 func 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
2068 func 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
2080 func 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
2091 func 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
2103 func hammerCompareAndSwapUintptr32(uaddr *uint32, count int) {
2104
2105
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
2117 func hammerCompareAndSwapUintptr32Method(uaddr *uint32, count int) {
2118
2119
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
2131 func 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
2162 var 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
2184 func init() {
2185 var v uint64 = 1 << 50
2186 if uintptr(v) == 0 {
2187
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
2197 func 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
2209 func 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
2221 func 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
2232 func 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
2244 const arch32 = unsafe.Sizeof(uintptr(0)) == 4
2245
2246 func hammerSwapUintptr64(uaddr *uint64, count int) {
2247
2248
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
2262 func hammerSwapUintptr64Method(uaddr *uint64, count int) {
2263
2264
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
2278 func 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
2285 func 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
2292 func hammerAddUint64(addr *uint64, count int) {
2293 for i := 0; i < count; i++ {
2294 AddUint64(addr, 1)
2295 }
2296 }
2297
2298 func 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
2305 func hammerAddUintptr64(uaddr *uint64, count int) {
2306
2307
2308 addr := (*uintptr)(unsafe.Pointer(uaddr))
2309 for i := 0; i < count; i++ {
2310 AddUintptr(addr, 1)
2311 }
2312 }
2313
2314 func hammerAddUintptr64Method(uaddr *uint64, count int) {
2315
2316
2317 addr := (*Uintptr)(unsafe.Pointer(uaddr))
2318 for i := 0; i < count; i++ {
2319 addr.Add(1)
2320 }
2321 }
2322
2323 func 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
2335 func 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
2347 func 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
2358 func 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
2370 func hammerCompareAndSwapUintptr64(uaddr *uint64, count int) {
2371
2372
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
2384 func hammerCompareAndSwapUintptr64Method(uaddr *uint64, count int) {
2385
2386
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
2398 func 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
2429 func 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
2444 func 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
2459 func 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
2474 func 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
2489 func 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
2501 func 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
2513 func 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
2525 func 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
2537 func 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
2564 func 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
2591
2592
2593
2594 func 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
2621
2622
2623
2624 func 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
2650 func 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
2666
2667 defer debug.SetGCPercent(debug.SetGCPercent(-1))
2668
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
2687 func 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
2729 func 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
2771 func 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
2817 func 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
2863 func shouldPanic(t *testing.T, name string, f func()) {
2864 defer func() {
2865
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
2879 func TestUnaligned64(t *testing.T) {
2880
2881
2882
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]))
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
2900 func 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
2924 func 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
2997
2998 type List struct {
2999 Next Pointer[List]
3000 }
3001
View as plain text