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 TestCompareAndSwapInt32(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 for val := int32(1); val+val > val; val += val {
543 x.i = val
544 if !CompareAndSwapInt32(&x.i, val, val+1) {
545 t.Fatalf("should have swapped %#x %#x", val, val+1)
546 }
547 if x.i != val+1 {
548 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
549 }
550 x.i = val + 1
551 if CompareAndSwapInt32(&x.i, val, val+2) {
552 t.Fatalf("should not have swapped %#x %#x", val, val+2)
553 }
554 if x.i != val+1 {
555 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
556 }
557 }
558 if x.before != magic32 || x.after != magic32 {
559 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
560 }
561 }
562
563 func TestCompareAndSwapInt32Method(t *testing.T) {
564 var x struct {
565 before int32
566 i Int32
567 after int32
568 }
569 x.before = magic32
570 x.after = magic32
571 for val := int32(1); val+val > val; val += val {
572 x.i.Store(val)
573 if !x.i.CompareAndSwap(val, val+1) {
574 t.Fatalf("should have swapped %#x %#x", val, val+1)
575 }
576 if x.i.Load() != val+1 {
577 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
578 }
579 x.i.Store(val + 1)
580 if x.i.CompareAndSwap(val, val+2) {
581 t.Fatalf("should not have swapped %#x %#x", val, val+2)
582 }
583 if x.i.Load() != val+1 {
584 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
585 }
586 }
587 if x.before != magic32 || x.after != magic32 {
588 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
589 }
590 }
591
592 func TestCompareAndSwapUint32(t *testing.T) {
593 var x struct {
594 before uint32
595 i uint32
596 after uint32
597 }
598 x.before = magic32
599 x.after = magic32
600 for val := uint32(1); val+val > val; val += val {
601 x.i = val
602 if !CompareAndSwapUint32(&x.i, val, val+1) {
603 t.Fatalf("should have swapped %#x %#x", val, val+1)
604 }
605 if x.i != val+1 {
606 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
607 }
608 x.i = val + 1
609 if CompareAndSwapUint32(&x.i, val, val+2) {
610 t.Fatalf("should not have swapped %#x %#x", val, val+2)
611 }
612 if x.i != val+1 {
613 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
614 }
615 }
616 if x.before != magic32 || x.after != magic32 {
617 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
618 }
619 }
620
621 func TestCompareAndSwapUint32Method(t *testing.T) {
622 var x struct {
623 before uint32
624 i Uint32
625 after uint32
626 }
627 x.before = magic32
628 x.after = magic32
629 for val := uint32(1); val+val > val; val += val {
630 x.i.Store(val)
631 if !x.i.CompareAndSwap(val, val+1) {
632 t.Fatalf("should have swapped %#x %#x", val, val+1)
633 }
634 if x.i.Load() != val+1 {
635 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
636 }
637 x.i.Store(val + 1)
638 if x.i.CompareAndSwap(val, val+2) {
639 t.Fatalf("should not have swapped %#x %#x", val, val+2)
640 }
641 if x.i.Load() != val+1 {
642 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
643 }
644 }
645 if x.before != magic32 || x.after != magic32 {
646 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
647 }
648 }
649
650 func TestCompareAndSwapInt64(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 for val := int64(1); val+val > val; val += val {
660 x.i = val
661 if !CompareAndSwapInt64(&x.i, val, val+1) {
662 t.Fatalf("should have swapped %#x %#x", val, val+1)
663 }
664 if x.i != val+1 {
665 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
666 }
667 x.i = val + 1
668 if CompareAndSwapInt64(&x.i, val, val+2) {
669 t.Fatalf("should not have swapped %#x %#x", val, val+2)
670 }
671 if x.i != val+1 {
672 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
673 }
674 }
675 if x.before != magic64 || x.after != magic64 {
676 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
677 }
678 }
679
680 func TestCompareAndSwapInt64Method(t *testing.T) {
681 var x struct {
682 before int64
683 i Int64
684 after int64
685 }
686 magic64 := int64(magic64)
687 x.before = magic64
688 x.after = magic64
689 for val := int64(1); val+val > val; val += val {
690 x.i.Store(val)
691 if !x.i.CompareAndSwap(val, val+1) {
692 t.Fatalf("should have swapped %#x %#x", val, val+1)
693 }
694 if x.i.Load() != val+1 {
695 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
696 }
697 x.i.Store(val + 1)
698 if x.i.CompareAndSwap(val, val+2) {
699 t.Fatalf("should not have swapped %#x %#x", val, val+2)
700 }
701 if x.i.Load() != val+1 {
702 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
703 }
704 }
705 if x.before != magic64 || x.after != magic64 {
706 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
707 }
708 }
709
710 func testCompareAndSwapUint64(t *testing.T, cas func(*uint64, uint64, uint64) bool) {
711 var x struct {
712 before uint64
713 i uint64
714 after uint64
715 }
716 magic64 := uint64(magic64)
717 x.before = magic64
718 x.after = magic64
719 for val := uint64(1); val+val > val; val += val {
720 x.i = val
721 if !cas(&x.i, val, val+1) {
722 t.Fatalf("should have swapped %#x %#x", val, val+1)
723 }
724 if x.i != val+1 {
725 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
726 }
727 x.i = val + 1
728 if cas(&x.i, val, val+2) {
729 t.Fatalf("should not have swapped %#x %#x", val, val+2)
730 }
731 if x.i != val+1 {
732 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
733 }
734 }
735 if x.before != magic64 || x.after != magic64 {
736 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
737 }
738 }
739
740 func TestCompareAndSwapUint64(t *testing.T) {
741 testCompareAndSwapUint64(t, CompareAndSwapUint64)
742 }
743
744 func TestCompareAndSwapUint64Method(t *testing.T) {
745 var x struct {
746 before uint64
747 i Uint64
748 after uint64
749 }
750 magic64 := uint64(magic64)
751 x.before = magic64
752 x.after = magic64
753 for val := uint64(1); val+val > val; val += val {
754 x.i.Store(val)
755 if !x.i.CompareAndSwap(val, val+1) {
756 t.Fatalf("should have swapped %#x %#x", val, val+1)
757 }
758 if x.i.Load() != val+1 {
759 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
760 }
761 x.i.Store(val + 1)
762 if x.i.CompareAndSwap(val, val+2) {
763 t.Fatalf("should not have swapped %#x %#x", val, val+2)
764 }
765 if x.i.Load() != val+1 {
766 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
767 }
768 }
769 if x.before != magic64 || x.after != magic64 {
770 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
771 }
772 }
773
774 func TestCompareAndSwapUintptr(t *testing.T) {
775 var x struct {
776 before uintptr
777 i uintptr
778 after uintptr
779 }
780 var m uint64 = magic64
781 magicptr := uintptr(m)
782 x.before = magicptr
783 x.after = magicptr
784 for val := uintptr(1); val+val > val; val += val {
785 x.i = val
786 if !CompareAndSwapUintptr(&x.i, val, val+1) {
787 t.Fatalf("should have swapped %#x %#x", val, val+1)
788 }
789 if x.i != val+1 {
790 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
791 }
792 x.i = val + 1
793 if CompareAndSwapUintptr(&x.i, val, val+2) {
794 t.Fatalf("should not have swapped %#x %#x", val, val+2)
795 }
796 if x.i != val+1 {
797 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
798 }
799 }
800 if x.before != magicptr || x.after != magicptr {
801 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
802 }
803 }
804
805 func TestCompareAndSwapUintptrMethod(t *testing.T) {
806 var x struct {
807 before uintptr
808 i Uintptr
809 after uintptr
810 }
811 var m uint64 = magic64
812 magicptr := uintptr(m)
813 x.before = magicptr
814 x.after = magicptr
815 for val := uintptr(1); val+val > val; val += val {
816 x.i.Store(val)
817 if !x.i.CompareAndSwap(val, val+1) {
818 t.Fatalf("should have swapped %#x %#x", val, val+1)
819 }
820 if x.i.Load() != val+1 {
821 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
822 }
823 x.i.Store(val + 1)
824 if x.i.CompareAndSwap(val, val+2) {
825 t.Fatalf("should not have swapped %#x %#x", val, val+2)
826 }
827 if x.i.Load() != val+1 {
828 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1)
829 }
830 }
831 if x.before != magicptr || x.after != magicptr {
832 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uintptr(magicptr), uintptr(magicptr))
833 }
834 }
835
836 func TestCompareAndSwapPointer(t *testing.T) {
837 var x struct {
838 before uintptr
839 i unsafe.Pointer
840 after uintptr
841 }
842 var m uint64 = magic64
843 magicptr := uintptr(m)
844 x.before = magicptr
845 x.after = magicptr
846 q := unsafe.Pointer(new(byte))
847 for _, p := range testPointers() {
848 x.i = p
849 if !CompareAndSwapPointer(&x.i, p, q) {
850 t.Fatalf("should have swapped %p %p", p, q)
851 }
852 if x.i != q {
853 t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i, q)
854 }
855 if CompareAndSwapPointer(&x.i, p, nil) {
856 t.Fatalf("should not have swapped %p nil", p)
857 }
858 if x.i != q {
859 t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i, q)
860 }
861 }
862 if x.before != magicptr || x.after != magicptr {
863 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
864 }
865 }
866
867 func TestCompareAndSwapPointerMethod(t *testing.T) {
868 var x struct {
869 before uintptr
870 i Pointer[byte]
871 after uintptr
872 }
873 var m uint64 = magic64
874 magicptr := uintptr(m)
875 x.before = magicptr
876 x.after = magicptr
877 q := new(byte)
878 for _, p := range testPointers() {
879 p := (*byte)(p)
880 x.i.Store(p)
881 if !x.i.CompareAndSwap(p, q) {
882 t.Fatalf("should have swapped %p %p", p, q)
883 }
884 if x.i.Load() != q {
885 t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i.Load(), q)
886 }
887 if x.i.CompareAndSwap(p, nil) {
888 t.Fatalf("should not have swapped %p nil", p)
889 }
890 if x.i.Load() != q {
891 t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i.Load(), q)
892 }
893 }
894 if x.before != magicptr || x.after != magicptr {
895 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
896 }
897 }
898
899 func TestLoadInt32(t *testing.T) {
900 var x struct {
901 before int32
902 i int32
903 after int32
904 }
905 x.before = magic32
906 x.after = magic32
907 for delta := int32(1); delta+delta > delta; delta += delta {
908 k := LoadInt32(&x.i)
909 if k != x.i {
910 t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
911 }
912 x.i += delta
913 }
914 if x.before != magic32 || x.after != magic32 {
915 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
916 }
917 }
918
919 func TestLoadInt32Method(t *testing.T) {
920 var x struct {
921 before int32
922 i Int32
923 after int32
924 }
925 x.before = magic32
926 x.after = magic32
927 want := int32(0)
928 for delta := int32(1); delta+delta > delta; delta += delta {
929 k := x.i.Load()
930 if k != want {
931 t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want)
932 }
933 x.i.Store(k + delta)
934 want = k + delta
935 }
936 if x.before != magic32 || x.after != magic32 {
937 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
938 }
939 }
940
941 func TestLoadUint32(t *testing.T) {
942 var x struct {
943 before uint32
944 i uint32
945 after uint32
946 }
947 x.before = magic32
948 x.after = magic32
949 for delta := uint32(1); delta+delta > delta; delta += delta {
950 k := LoadUint32(&x.i)
951 if k != x.i {
952 t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
953 }
954 x.i += delta
955 }
956 if x.before != magic32 || x.after != magic32 {
957 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
958 }
959 }
960
961 func TestLoadUint32Method(t *testing.T) {
962 var x struct {
963 before uint32
964 i Uint32
965 after uint32
966 }
967 x.before = magic32
968 x.after = magic32
969 want := uint32(0)
970 for delta := uint32(1); delta+delta > delta; delta += delta {
971 k := x.i.Load()
972 if k != want {
973 t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want)
974 }
975 x.i.Store(k + delta)
976 want = k + delta
977 }
978 if x.before != magic32 || x.after != magic32 {
979 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
980 }
981 }
982
983 func TestLoadInt64(t *testing.T) {
984 var x struct {
985 before int64
986 i int64
987 after int64
988 }
989 magic64 := int64(magic64)
990 x.before = magic64
991 x.after = magic64
992 for delta := int64(1); delta+delta > delta; delta += delta {
993 k := LoadInt64(&x.i)
994 if k != x.i {
995 t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
996 }
997 x.i += delta
998 }
999 if x.before != magic64 || x.after != magic64 {
1000 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1001 }
1002 }
1003
1004 func TestLoadInt64Method(t *testing.T) {
1005 var x struct {
1006 before int64
1007 i Int64
1008 after int64
1009 }
1010 magic64 := int64(magic64)
1011 x.before = magic64
1012 x.after = magic64
1013 want := int64(0)
1014 for delta := int64(1); delta+delta > delta; delta += delta {
1015 k := x.i.Load()
1016 if k != want {
1017 t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want)
1018 }
1019 x.i.Store(k + delta)
1020 want = k + delta
1021 }
1022 if x.before != magic64 || x.after != magic64 {
1023 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1024 }
1025 }
1026
1027 func TestLoadUint64(t *testing.T) {
1028 var x struct {
1029 before uint64
1030 i uint64
1031 after uint64
1032 }
1033 magic64 := uint64(magic64)
1034 x.before = magic64
1035 x.after = magic64
1036 for delta := uint64(1); delta+delta > delta; delta += delta {
1037 k := LoadUint64(&x.i)
1038 if k != x.i {
1039 t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
1040 }
1041 x.i += delta
1042 }
1043 if x.before != magic64 || x.after != magic64 {
1044 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1045 }
1046 }
1047
1048 func TestLoadUint64Method(t *testing.T) {
1049 var x struct {
1050 before uint64
1051 i Uint64
1052 after uint64
1053 }
1054 magic64 := uint64(magic64)
1055 x.before = magic64
1056 x.after = magic64
1057 want := uint64(0)
1058 for delta := uint64(1); delta+delta > delta; delta += delta {
1059 k := x.i.Load()
1060 if k != want {
1061 t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want)
1062 }
1063 x.i.Store(k + delta)
1064 want = k + delta
1065 }
1066 if x.before != magic64 || x.after != magic64 {
1067 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1068 }
1069 }
1070
1071 func TestLoadUintptr(t *testing.T) {
1072 var x struct {
1073 before uintptr
1074 i uintptr
1075 after uintptr
1076 }
1077 var m uint64 = magic64
1078 magicptr := uintptr(m)
1079 x.before = magicptr
1080 x.after = magicptr
1081 for delta := uintptr(1); delta+delta > delta; delta += delta {
1082 k := LoadUintptr(&x.i)
1083 if k != x.i {
1084 t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
1085 }
1086 x.i += delta
1087 }
1088 if x.before != magicptr || x.after != magicptr {
1089 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
1090 }
1091 }
1092
1093 func TestLoadUintptrMethod(t *testing.T) {
1094 var x struct {
1095 before uintptr
1096 i Uintptr
1097 after uintptr
1098 }
1099 var m uint64 = magic64
1100 magicptr := uintptr(m)
1101 x.before = magicptr
1102 x.after = magicptr
1103 want := uintptr(0)
1104 for delta := uintptr(1); delta+delta > delta; delta += delta {
1105 k := x.i.Load()
1106 if k != want {
1107 t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want)
1108 }
1109 x.i.Store(k + delta)
1110 want = k + delta
1111 }
1112 if x.before != magicptr || x.after != magicptr {
1113 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
1114 }
1115 }
1116
1117 func TestLoadPointer(t *testing.T) {
1118 var x struct {
1119 before uintptr
1120 i unsafe.Pointer
1121 after uintptr
1122 }
1123 var m uint64 = magic64
1124 magicptr := uintptr(m)
1125 x.before = magicptr
1126 x.after = magicptr
1127 for _, p := range testPointers() {
1128 x.i = p
1129 k := LoadPointer(&x.i)
1130 if k != p {
1131 t.Fatalf("p=%x k=%x", p, k)
1132 }
1133 }
1134 if x.before != magicptr || x.after != magicptr {
1135 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
1136 }
1137 }
1138
1139 func TestLoadPointerMethod(t *testing.T) {
1140 var x struct {
1141 before uintptr
1142 i Pointer[byte]
1143 after uintptr
1144 }
1145 var m uint64 = magic64
1146 magicptr := uintptr(m)
1147 x.before = magicptr
1148 x.after = magicptr
1149 for _, p := range testPointers() {
1150 p := (*byte)(p)
1151 x.i.Store(p)
1152 k := x.i.Load()
1153 if k != p {
1154 t.Fatalf("p=%x k=%x", p, k)
1155 }
1156 }
1157 if x.before != magicptr || x.after != magicptr {
1158 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
1159 }
1160 }
1161
1162 func TestStoreInt32(t *testing.T) {
1163 var x struct {
1164 before int32
1165 i int32
1166 after int32
1167 }
1168 x.before = magic32
1169 x.after = magic32
1170 v := int32(0)
1171 for delta := int32(1); delta+delta > delta; delta += delta {
1172 StoreInt32(&x.i, v)
1173 if x.i != v {
1174 t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
1175 }
1176 v += delta
1177 }
1178 if x.before != magic32 || x.after != magic32 {
1179 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
1180 }
1181 }
1182
1183 func TestStoreInt32Method(t *testing.T) {
1184 var x struct {
1185 before int32
1186 i Int32
1187 after int32
1188 }
1189 x.before = magic32
1190 x.after = magic32
1191 v := int32(0)
1192 for delta := int32(1); delta+delta > delta; delta += delta {
1193 x.i.Store(v)
1194 if x.i.Load() != v {
1195 t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v)
1196 }
1197 v += delta
1198 }
1199 if x.before != magic32 || x.after != magic32 {
1200 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
1201 }
1202 }
1203
1204 func TestStoreUint32(t *testing.T) {
1205 var x struct {
1206 before uint32
1207 i uint32
1208 after uint32
1209 }
1210 x.before = magic32
1211 x.after = magic32
1212 v := uint32(0)
1213 for delta := uint32(1); delta+delta > delta; delta += delta {
1214 StoreUint32(&x.i, v)
1215 if x.i != v {
1216 t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
1217 }
1218 v += delta
1219 }
1220 if x.before != magic32 || x.after != magic32 {
1221 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
1222 }
1223 }
1224
1225 func TestStoreUint32Method(t *testing.T) {
1226 var x struct {
1227 before uint32
1228 i Uint32
1229 after uint32
1230 }
1231 x.before = magic32
1232 x.after = magic32
1233 v := uint32(0)
1234 for delta := uint32(1); delta+delta > delta; delta += delta {
1235 x.i.Store(v)
1236 if x.i.Load() != v {
1237 t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v)
1238 }
1239 v += delta
1240 }
1241 if x.before != magic32 || x.after != magic32 {
1242 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
1243 }
1244 }
1245
1246 func TestStoreInt64(t *testing.T) {
1247 var x struct {
1248 before int64
1249 i int64
1250 after int64
1251 }
1252 magic64 := int64(magic64)
1253 x.before = magic64
1254 x.after = magic64
1255 v := int64(0)
1256 for delta := int64(1); delta+delta > delta; delta += delta {
1257 StoreInt64(&x.i, v)
1258 if x.i != v {
1259 t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
1260 }
1261 v += delta
1262 }
1263 if x.before != magic64 || x.after != magic64 {
1264 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1265 }
1266 }
1267
1268 func TestStoreInt64Method(t *testing.T) {
1269 var x struct {
1270 before int64
1271 i Int64
1272 after int64
1273 }
1274 magic64 := int64(magic64)
1275 x.before = magic64
1276 x.after = magic64
1277 v := int64(0)
1278 for delta := int64(1); delta+delta > delta; delta += delta {
1279 x.i.Store(v)
1280 if x.i.Load() != v {
1281 t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v)
1282 }
1283 v += delta
1284 }
1285 if x.before != magic64 || x.after != magic64 {
1286 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1287 }
1288 }
1289
1290 func TestStoreUint64(t *testing.T) {
1291 var x struct {
1292 before uint64
1293 i uint64
1294 after uint64
1295 }
1296 magic64 := uint64(magic64)
1297 x.before = magic64
1298 x.after = magic64
1299 v := uint64(0)
1300 for delta := uint64(1); delta+delta > delta; delta += delta {
1301 StoreUint64(&x.i, v)
1302 if x.i != v {
1303 t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
1304 }
1305 v += delta
1306 }
1307 if x.before != magic64 || x.after != magic64 {
1308 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1309 }
1310 }
1311
1312 func TestStoreUint64Method(t *testing.T) {
1313 var x struct {
1314 before uint64
1315 i Uint64
1316 after uint64
1317 }
1318 magic64 := uint64(magic64)
1319 x.before = magic64
1320 x.after = magic64
1321 v := uint64(0)
1322 for delta := uint64(1); delta+delta > delta; delta += delta {
1323 x.i.Store(v)
1324 if x.i.Load() != v {
1325 t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v)
1326 }
1327 v += delta
1328 }
1329 if x.before != magic64 || x.after != magic64 {
1330 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64)
1331 }
1332 }
1333
1334 func TestStoreUintptr(t *testing.T) {
1335 var x struct {
1336 before uintptr
1337 i uintptr
1338 after uintptr
1339 }
1340 var m uint64 = magic64
1341 magicptr := uintptr(m)
1342 x.before = magicptr
1343 x.after = magicptr
1344 v := uintptr(0)
1345 for delta := uintptr(1); delta+delta > delta; delta += delta {
1346 StoreUintptr(&x.i, v)
1347 if x.i != v {
1348 t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
1349 }
1350 v += delta
1351 }
1352 if x.before != magicptr || x.after != magicptr {
1353 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
1354 }
1355 }
1356
1357 func TestStoreUintptrMethod(t *testing.T) {
1358 var x struct {
1359 before uintptr
1360 i Uintptr
1361 after uintptr
1362 }
1363 var m uint64 = magic64
1364 magicptr := uintptr(m)
1365 x.before = magicptr
1366 x.after = magicptr
1367 v := uintptr(0)
1368 for delta := uintptr(1); delta+delta > delta; delta += delta {
1369 x.i.Store(v)
1370 if x.i.Load() != v {
1371 t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v)
1372 }
1373 v += delta
1374 }
1375 if x.before != magicptr || x.after != magicptr {
1376 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
1377 }
1378 }
1379
1380 func TestStorePointer(t *testing.T) {
1381 var x struct {
1382 before uintptr
1383 i unsafe.Pointer
1384 after uintptr
1385 }
1386 var m uint64 = magic64
1387 magicptr := uintptr(m)
1388 x.before = magicptr
1389 x.after = magicptr
1390 for _, p := range testPointers() {
1391 StorePointer(&x.i, p)
1392 if x.i != p {
1393 t.Fatalf("x.i=%p p=%p", x.i, p)
1394 }
1395 }
1396 if x.before != magicptr || x.after != magicptr {
1397 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
1398 }
1399 }
1400
1401 func TestStorePointerMethod(t *testing.T) {
1402 var x struct {
1403 before uintptr
1404 i Pointer[byte]
1405 after uintptr
1406 }
1407 var m uint64 = magic64
1408 magicptr := uintptr(m)
1409 x.before = magicptr
1410 x.after = magicptr
1411 for _, p := range testPointers() {
1412 p := (*byte)(p)
1413 x.i.Store(p)
1414 if x.i.Load() != p {
1415 t.Fatalf("x.i=%p p=%p", x.i.Load(), p)
1416 }
1417 }
1418 if x.before != magicptr || x.after != magicptr {
1419 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
1420 }
1421 }
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435 var hammer32 = map[string]func(*uint32, int){
1436 "SwapInt32": hammerSwapInt32,
1437 "SwapUint32": hammerSwapUint32,
1438 "SwapUintptr": hammerSwapUintptr32,
1439 "AddInt32": hammerAddInt32,
1440 "AddUint32": hammerAddUint32,
1441 "AddUintptr": hammerAddUintptr32,
1442 "CompareAndSwapInt32": hammerCompareAndSwapInt32,
1443 "CompareAndSwapUint32": hammerCompareAndSwapUint32,
1444 "CompareAndSwapUintptr": hammerCompareAndSwapUintptr32,
1445
1446 "SwapInt32Method": hammerSwapInt32Method,
1447 "SwapUint32Method": hammerSwapUint32Method,
1448 "SwapUintptrMethod": hammerSwapUintptr32Method,
1449 "AddInt32Method": hammerAddInt32Method,
1450 "AddUint32Method": hammerAddUint32Method,
1451 "AddUintptrMethod": hammerAddUintptr32Method,
1452 "CompareAndSwapInt32Method": hammerCompareAndSwapInt32Method,
1453 "CompareAndSwapUint32Method": hammerCompareAndSwapUint32Method,
1454 "CompareAndSwapUintptrMethod": hammerCompareAndSwapUintptr32Method,
1455 }
1456
1457 func init() {
1458 var v uint64 = 1 << 50
1459 if uintptr(v) != 0 {
1460
1461 delete(hammer32, "SwapUintptr")
1462 delete(hammer32, "AddUintptr")
1463 delete(hammer32, "CompareAndSwapUintptr")
1464 delete(hammer32, "SwapUintptrMethod")
1465 delete(hammer32, "AddUintptrMethod")
1466 delete(hammer32, "CompareAndSwapUintptrMethod")
1467 }
1468 }
1469
1470 func hammerSwapInt32(uaddr *uint32, count int) {
1471 addr := (*int32)(unsafe.Pointer(uaddr))
1472 seed := int(uintptr(unsafe.Pointer(&count)))
1473 for i := 0; i < count; i++ {
1474 new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
1475 old := uint32(SwapInt32(addr, int32(new)))
1476 if old>>16 != old<<16>>16 {
1477 panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old))
1478 }
1479 }
1480 }
1481
1482 func hammerSwapInt32Method(uaddr *uint32, count int) {
1483 addr := (*Int32)(unsafe.Pointer(uaddr))
1484 seed := int(uintptr(unsafe.Pointer(&count)))
1485 for i := 0; i < count; i++ {
1486 new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
1487 old := uint32(addr.Swap(int32(new)))
1488 if old>>16 != old<<16>>16 {
1489 panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old))
1490 }
1491 }
1492 }
1493
1494 func hammerSwapUint32(addr *uint32, count int) {
1495 seed := int(uintptr(unsafe.Pointer(&count)))
1496 for i := 0; i < count; i++ {
1497 new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
1498 old := SwapUint32(addr, new)
1499 if old>>16 != old<<16>>16 {
1500 panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old))
1501 }
1502 }
1503 }
1504
1505 func hammerSwapUint32Method(uaddr *uint32, count int) {
1506 addr := (*Uint32)(unsafe.Pointer(uaddr))
1507 seed := int(uintptr(unsafe.Pointer(&count)))
1508 for i := 0; i < count; i++ {
1509 new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
1510 old := addr.Swap(new)
1511 if old>>16 != old<<16>>16 {
1512 panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old))
1513 }
1514 }
1515 }
1516
1517 func hammerSwapUintptr32(uaddr *uint32, count int) {
1518
1519
1520 addr := (*uintptr)(unsafe.Pointer(uaddr))
1521 seed := int(uintptr(unsafe.Pointer(&count)))
1522 for i := 0; i < count; i++ {
1523 new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16
1524 old := SwapUintptr(addr, new)
1525 if old>>16 != old<<16>>16 {
1526 panic(fmt.Sprintf("SwapUintptr is not atomic: %#08x", old))
1527 }
1528 }
1529 }
1530
1531 func hammerSwapUintptr32Method(uaddr *uint32, count int) {
1532
1533
1534 addr := (*Uintptr)(unsafe.Pointer(uaddr))
1535 seed := int(uintptr(unsafe.Pointer(&count)))
1536 for i := 0; i < count; i++ {
1537 new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16
1538 old := addr.Swap(new)
1539 if old>>16 != old<<16>>16 {
1540 panic(fmt.Sprintf("Uintptr.Swap is not atomic: %#08x", old))
1541 }
1542 }
1543 }
1544
1545 func hammerAddInt32(uaddr *uint32, count int) {
1546 addr := (*int32)(unsafe.Pointer(uaddr))
1547 for i := 0; i < count; i++ {
1548 AddInt32(addr, 1)
1549 }
1550 }
1551
1552 func hammerAddInt32Method(uaddr *uint32, count int) {
1553 addr := (*Int32)(unsafe.Pointer(uaddr))
1554 for i := 0; i < count; i++ {
1555 addr.Add(1)
1556 }
1557 }
1558
1559 func hammerAddUint32(addr *uint32, count int) {
1560 for i := 0; i < count; i++ {
1561 AddUint32(addr, 1)
1562 }
1563 }
1564
1565 func hammerAddUint32Method(uaddr *uint32, count int) {
1566 addr := (*Uint32)(unsafe.Pointer(uaddr))
1567 for i := 0; i < count; i++ {
1568 addr.Add(1)
1569 }
1570 }
1571
1572 func hammerAddUintptr32(uaddr *uint32, count int) {
1573
1574
1575 addr := (*uintptr)(unsafe.Pointer(uaddr))
1576 for i := 0; i < count; i++ {
1577 AddUintptr(addr, 1)
1578 }
1579 }
1580
1581 func hammerAddUintptr32Method(uaddr *uint32, count int) {
1582
1583
1584 addr := (*Uintptr)(unsafe.Pointer(uaddr))
1585 for i := 0; i < count; i++ {
1586 addr.Add(1)
1587 }
1588 }
1589
1590 func hammerCompareAndSwapInt32(uaddr *uint32, count int) {
1591 addr := (*int32)(unsafe.Pointer(uaddr))
1592 for i := 0; i < count; i++ {
1593 for {
1594 v := LoadInt32(addr)
1595 if CompareAndSwapInt32(addr, v, v+1) {
1596 break
1597 }
1598 }
1599 }
1600 }
1601
1602 func hammerCompareAndSwapInt32Method(uaddr *uint32, count int) {
1603 addr := (*Int32)(unsafe.Pointer(uaddr))
1604 for i := 0; i < count; i++ {
1605 for {
1606 v := addr.Load()
1607 if addr.CompareAndSwap(v, v+1) {
1608 break
1609 }
1610 }
1611 }
1612 }
1613
1614 func hammerCompareAndSwapUint32(addr *uint32, count int) {
1615 for i := 0; i < count; i++ {
1616 for {
1617 v := LoadUint32(addr)
1618 if CompareAndSwapUint32(addr, v, v+1) {
1619 break
1620 }
1621 }
1622 }
1623 }
1624
1625 func hammerCompareAndSwapUint32Method(uaddr *uint32, count int) {
1626 addr := (*Uint32)(unsafe.Pointer(uaddr))
1627 for i := 0; i < count; i++ {
1628 for {
1629 v := addr.Load()
1630 if addr.CompareAndSwap(v, v+1) {
1631 break
1632 }
1633 }
1634 }
1635 }
1636
1637 func hammerCompareAndSwapUintptr32(uaddr *uint32, count int) {
1638
1639
1640 addr := (*uintptr)(unsafe.Pointer(uaddr))
1641 for i := 0; i < count; i++ {
1642 for {
1643 v := LoadUintptr(addr)
1644 if CompareAndSwapUintptr(addr, v, v+1) {
1645 break
1646 }
1647 }
1648 }
1649 }
1650
1651 func hammerCompareAndSwapUintptr32Method(uaddr *uint32, count int) {
1652
1653
1654 addr := (*Uintptr)(unsafe.Pointer(uaddr))
1655 for i := 0; i < count; i++ {
1656 for {
1657 v := addr.Load()
1658 if addr.CompareAndSwap(v, v+1) {
1659 break
1660 }
1661 }
1662 }
1663 }
1664
1665 func TestHammer32(t *testing.T) {
1666 const p = 4
1667 n := 100000
1668 if testing.Short() {
1669 n = 1000
1670 }
1671 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
1672
1673 for name, testf := range hammer32 {
1674 c := make(chan int)
1675 var val uint32
1676 for i := 0; i < p; i++ {
1677 go func() {
1678 defer func() {
1679 if err := recover(); err != nil {
1680 t.Error(err.(string))
1681 }
1682 c <- 1
1683 }()
1684 testf(&val, n)
1685 }()
1686 }
1687 for i := 0; i < p; i++ {
1688 <-c
1689 }
1690 if !strings.HasPrefix(name, "Swap") && val != uint32(n)*p {
1691 t.Fatalf("%s: val=%d want %d", name, val, n*p)
1692 }
1693 }
1694 }
1695
1696 var hammer64 = map[string]func(*uint64, int){
1697 "SwapInt64": hammerSwapInt64,
1698 "SwapUint64": hammerSwapUint64,
1699 "SwapUintptr": hammerSwapUintptr64,
1700 "AddInt64": hammerAddInt64,
1701 "AddUint64": hammerAddUint64,
1702 "AddUintptr": hammerAddUintptr64,
1703 "CompareAndSwapInt64": hammerCompareAndSwapInt64,
1704 "CompareAndSwapUint64": hammerCompareAndSwapUint64,
1705 "CompareAndSwapUintptr": hammerCompareAndSwapUintptr64,
1706
1707 "SwapInt64Method": hammerSwapInt64Method,
1708 "SwapUint64Method": hammerSwapUint64Method,
1709 "SwapUintptrMethod": hammerSwapUintptr64Method,
1710 "AddInt64Method": hammerAddInt64Method,
1711 "AddUint64Method": hammerAddUint64Method,
1712 "AddUintptrMethod": hammerAddUintptr64Method,
1713 "CompareAndSwapInt64Method": hammerCompareAndSwapInt64Method,
1714 "CompareAndSwapUint64Method": hammerCompareAndSwapUint64Method,
1715 "CompareAndSwapUintptrMethod": hammerCompareAndSwapUintptr64Method,
1716 }
1717
1718 func init() {
1719 var v uint64 = 1 << 50
1720 if uintptr(v) == 0 {
1721
1722 delete(hammer64, "SwapUintptr")
1723 delete(hammer64, "SwapUintptrMethod")
1724 delete(hammer64, "AddUintptr")
1725 delete(hammer64, "AddUintptrMethod")
1726 delete(hammer64, "CompareAndSwapUintptr")
1727 delete(hammer64, "CompareAndSwapUintptrMethod")
1728 }
1729 }
1730
1731 func hammerSwapInt64(uaddr *uint64, count int) {
1732 addr := (*int64)(unsafe.Pointer(uaddr))
1733 seed := int(uintptr(unsafe.Pointer(&count)))
1734 for i := 0; i < count; i++ {
1735 new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
1736 old := uint64(SwapInt64(addr, int64(new)))
1737 if old>>32 != old<<32>>32 {
1738 panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old))
1739 }
1740 }
1741 }
1742
1743 func hammerSwapInt64Method(uaddr *uint64, count int) {
1744 addr := (*Int64)(unsafe.Pointer(uaddr))
1745 seed := int(uintptr(unsafe.Pointer(&count)))
1746 for i := 0; i < count; i++ {
1747 new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
1748 old := uint64(addr.Swap(int64(new)))
1749 if old>>32 != old<<32>>32 {
1750 panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old))
1751 }
1752 }
1753 }
1754
1755 func hammerSwapUint64(addr *uint64, count int) {
1756 seed := int(uintptr(unsafe.Pointer(&count)))
1757 for i := 0; i < count; i++ {
1758 new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
1759 old := SwapUint64(addr, new)
1760 if old>>32 != old<<32>>32 {
1761 panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old))
1762 }
1763 }
1764 }
1765
1766 func hammerSwapUint64Method(uaddr *uint64, count int) {
1767 addr := (*Uint64)(unsafe.Pointer(uaddr))
1768 seed := int(uintptr(unsafe.Pointer(&count)))
1769 for i := 0; i < count; i++ {
1770 new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
1771 old := addr.Swap(new)
1772 if old>>32 != old<<32>>32 {
1773 panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old))
1774 }
1775 }
1776 }
1777
1778 const arch32 = unsafe.Sizeof(uintptr(0)) == 4
1779
1780 func hammerSwapUintptr64(uaddr *uint64, count int) {
1781
1782
1783 if !arch32 {
1784 addr := (*uintptr)(unsafe.Pointer(uaddr))
1785 seed := int(uintptr(unsafe.Pointer(&count)))
1786 for i := 0; i < count; i++ {
1787 new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32
1788 old := SwapUintptr(addr, new)
1789 if old>>32 != old<<32>>32 {
1790 panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old))
1791 }
1792 }
1793 }
1794 }
1795
1796 func hammerSwapUintptr64Method(uaddr *uint64, count int) {
1797
1798
1799 if !arch32 {
1800 addr := (*Uintptr)(unsafe.Pointer(uaddr))
1801 seed := int(uintptr(unsafe.Pointer(&count)))
1802 for i := 0; i < count; i++ {
1803 new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32
1804 old := addr.Swap(new)
1805 if old>>32 != old<<32>>32 {
1806 panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old))
1807 }
1808 }
1809 }
1810 }
1811
1812 func hammerAddInt64(uaddr *uint64, count int) {
1813 addr := (*int64)(unsafe.Pointer(uaddr))
1814 for i := 0; i < count; i++ {
1815 AddInt64(addr, 1)
1816 }
1817 }
1818
1819 func hammerAddInt64Method(uaddr *uint64, count int) {
1820 addr := (*Int64)(unsafe.Pointer(uaddr))
1821 for i := 0; i < count; i++ {
1822 addr.Add(1)
1823 }
1824 }
1825
1826 func hammerAddUint64(addr *uint64, count int) {
1827 for i := 0; i < count; i++ {
1828 AddUint64(addr, 1)
1829 }
1830 }
1831
1832 func hammerAddUint64Method(uaddr *uint64, count int) {
1833 addr := (*Uint64)(unsafe.Pointer(uaddr))
1834 for i := 0; i < count; i++ {
1835 addr.Add(1)
1836 }
1837 }
1838
1839 func hammerAddUintptr64(uaddr *uint64, count int) {
1840
1841
1842 addr := (*uintptr)(unsafe.Pointer(uaddr))
1843 for i := 0; i < count; i++ {
1844 AddUintptr(addr, 1)
1845 }
1846 }
1847
1848 func hammerAddUintptr64Method(uaddr *uint64, count int) {
1849
1850
1851 addr := (*Uintptr)(unsafe.Pointer(uaddr))
1852 for i := 0; i < count; i++ {
1853 addr.Add(1)
1854 }
1855 }
1856
1857 func hammerCompareAndSwapInt64(uaddr *uint64, count int) {
1858 addr := (*int64)(unsafe.Pointer(uaddr))
1859 for i := 0; i < count; i++ {
1860 for {
1861 v := LoadInt64(addr)
1862 if CompareAndSwapInt64(addr, v, v+1) {
1863 break
1864 }
1865 }
1866 }
1867 }
1868
1869 func hammerCompareAndSwapInt64Method(uaddr *uint64, count int) {
1870 addr := (*Int64)(unsafe.Pointer(uaddr))
1871 for i := 0; i < count; i++ {
1872 for {
1873 v := addr.Load()
1874 if addr.CompareAndSwap(v, v+1) {
1875 break
1876 }
1877 }
1878 }
1879 }
1880
1881 func hammerCompareAndSwapUint64(addr *uint64, count int) {
1882 for i := 0; i < count; i++ {
1883 for {
1884 v := LoadUint64(addr)
1885 if CompareAndSwapUint64(addr, v, v+1) {
1886 break
1887 }
1888 }
1889 }
1890 }
1891
1892 func hammerCompareAndSwapUint64Method(uaddr *uint64, count int) {
1893 addr := (*Uint64)(unsafe.Pointer(uaddr))
1894 for i := 0; i < count; i++ {
1895 for {
1896 v := addr.Load()
1897 if addr.CompareAndSwap(v, v+1) {
1898 break
1899 }
1900 }
1901 }
1902 }
1903
1904 func hammerCompareAndSwapUintptr64(uaddr *uint64, count int) {
1905
1906
1907 addr := (*uintptr)(unsafe.Pointer(uaddr))
1908 for i := 0; i < count; i++ {
1909 for {
1910 v := LoadUintptr(addr)
1911 if CompareAndSwapUintptr(addr, v, v+1) {
1912 break
1913 }
1914 }
1915 }
1916 }
1917
1918 func hammerCompareAndSwapUintptr64Method(uaddr *uint64, count int) {
1919
1920
1921 addr := (*Uintptr)(unsafe.Pointer(uaddr))
1922 for i := 0; i < count; i++ {
1923 for {
1924 v := addr.Load()
1925 if addr.CompareAndSwap(v, v+1) {
1926 break
1927 }
1928 }
1929 }
1930 }
1931
1932 func TestHammer64(t *testing.T) {
1933 const p = 4
1934 n := 100000
1935 if testing.Short() {
1936 n = 1000
1937 }
1938 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
1939
1940 for name, testf := range hammer64 {
1941 c := make(chan int)
1942 var val uint64
1943 for i := 0; i < p; i++ {
1944 go func() {
1945 defer func() {
1946 if err := recover(); err != nil {
1947 t.Error(err.(string))
1948 }
1949 c <- 1
1950 }()
1951 testf(&val, n)
1952 }()
1953 }
1954 for i := 0; i < p; i++ {
1955 <-c
1956 }
1957 if !strings.HasPrefix(name, "Swap") && val != uint64(n)*p {
1958 t.Fatalf("%s: val=%d want %d", name, val, n*p)
1959 }
1960 }
1961 }
1962
1963 func hammerStoreLoadInt32(t *testing.T, paddr unsafe.Pointer) {
1964 addr := (*int32)(paddr)
1965 v := LoadInt32(addr)
1966 vlo := v & ((1 << 16) - 1)
1967 vhi := v >> 16
1968 if vlo != vhi {
1969 t.Fatalf("Int32: %#x != %#x", vlo, vhi)
1970 }
1971 new := v + 1 + 1<<16
1972 if vlo == 1e4 {
1973 new = 0
1974 }
1975 StoreInt32(addr, new)
1976 }
1977
1978 func hammerStoreLoadInt32Method(t *testing.T, paddr unsafe.Pointer) {
1979 addr := (*int32)(paddr)
1980 v := LoadInt32(addr)
1981 vlo := v & ((1 << 16) - 1)
1982 vhi := v >> 16
1983 if vlo != vhi {
1984 t.Fatalf("Int32: %#x != %#x", vlo, vhi)
1985 }
1986 new := v + 1 + 1<<16
1987 if vlo == 1e4 {
1988 new = 0
1989 }
1990 StoreInt32(addr, new)
1991 }
1992
1993 func hammerStoreLoadUint32(t *testing.T, paddr unsafe.Pointer) {
1994 addr := (*uint32)(paddr)
1995 v := LoadUint32(addr)
1996 vlo := v & ((1 << 16) - 1)
1997 vhi := v >> 16
1998 if vlo != vhi {
1999 t.Fatalf("Uint32: %#x != %#x", vlo, vhi)
2000 }
2001 new := v + 1 + 1<<16
2002 if vlo == 1e4 {
2003 new = 0
2004 }
2005 StoreUint32(addr, new)
2006 }
2007
2008 func hammerStoreLoadUint32Method(t *testing.T, paddr unsafe.Pointer) {
2009 addr := (*Uint32)(paddr)
2010 v := addr.Load()
2011 vlo := v & ((1 << 16) - 1)
2012 vhi := v >> 16
2013 if vlo != vhi {
2014 t.Fatalf("Uint32: %#x != %#x", vlo, vhi)
2015 }
2016 new := v + 1 + 1<<16
2017 if vlo == 1e4 {
2018 new = 0
2019 }
2020 addr.Store(new)
2021 }
2022
2023 func hammerStoreLoadInt64(t *testing.T, paddr unsafe.Pointer) {
2024 addr := (*int64)(paddr)
2025 v := LoadInt64(addr)
2026 vlo := v & ((1 << 32) - 1)
2027 vhi := v >> 32
2028 if vlo != vhi {
2029 t.Fatalf("Int64: %#x != %#x", vlo, vhi)
2030 }
2031 new := v + 1 + 1<<32
2032 StoreInt64(addr, new)
2033 }
2034
2035 func hammerStoreLoadInt64Method(t *testing.T, paddr unsafe.Pointer) {
2036 addr := (*Int64)(paddr)
2037 v := addr.Load()
2038 vlo := v & ((1 << 32) - 1)
2039 vhi := v >> 32
2040 if vlo != vhi {
2041 t.Fatalf("Int64: %#x != %#x", vlo, vhi)
2042 }
2043 new := v + 1 + 1<<32
2044 addr.Store(new)
2045 }
2046
2047 func hammerStoreLoadUint64(t *testing.T, paddr unsafe.Pointer) {
2048 addr := (*uint64)(paddr)
2049 v := LoadUint64(addr)
2050 vlo := v & ((1 << 32) - 1)
2051 vhi := v >> 32
2052 if vlo != vhi {
2053 t.Fatalf("Uint64: %#x != %#x", vlo, vhi)
2054 }
2055 new := v + 1 + 1<<32
2056 StoreUint64(addr, new)
2057 }
2058
2059 func hammerStoreLoadUint64Method(t *testing.T, paddr unsafe.Pointer) {
2060 addr := (*Uint64)(paddr)
2061 v := addr.Load()
2062 vlo := v & ((1 << 32) - 1)
2063 vhi := v >> 32
2064 if vlo != vhi {
2065 t.Fatalf("Uint64: %#x != %#x", vlo, vhi)
2066 }
2067 new := v + 1 + 1<<32
2068 addr.Store(new)
2069 }
2070
2071 func hammerStoreLoadUintptr(t *testing.T, paddr unsafe.Pointer) {
2072 addr := (*uintptr)(paddr)
2073 v := LoadUintptr(addr)
2074 new := v
2075 if arch32 {
2076 vlo := v & ((1 << 16) - 1)
2077 vhi := v >> 16
2078 if vlo != vhi {
2079 t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
2080 }
2081 new = v + 1 + 1<<16
2082 if vlo == 1e4 {
2083 new = 0
2084 }
2085 } else {
2086 vlo := v & ((1 << 32) - 1)
2087 vhi := v >> 32
2088 if vlo != vhi {
2089 t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
2090 }
2091 inc := uint64(1 + 1<<32)
2092 new = v + uintptr(inc)
2093 }
2094 StoreUintptr(addr, new)
2095 }
2096
2097
2098 func hammerStoreLoadUintptrMethod(t *testing.T, paddr unsafe.Pointer) {
2099 addr := (*Uintptr)(paddr)
2100 v := addr.Load()
2101 new := v
2102 if arch32 {
2103 vlo := v & ((1 << 16) - 1)
2104 vhi := v >> 16
2105 if vlo != vhi {
2106 t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
2107 }
2108 new = v + 1 + 1<<16
2109 if vlo == 1e4 {
2110 new = 0
2111 }
2112 } else {
2113 vlo := v & ((1 << 32) - 1)
2114 vhi := v >> 32
2115 if vlo != vhi {
2116 t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
2117 }
2118 inc := uint64(1 + 1<<32)
2119 new = v + uintptr(inc)
2120 }
2121 addr.Store(new)
2122 }
2123
2124
2125
2126
2127
2128 func hammerStoreLoadPointer(t *testing.T, paddr unsafe.Pointer) {
2129 addr := (*unsafe.Pointer)(paddr)
2130 v := uintptr(LoadPointer(addr))
2131 new := v
2132 if arch32 {
2133 vlo := v & ((1 << 16) - 1)
2134 vhi := v >> 16
2135 if vlo != vhi {
2136 t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
2137 }
2138 new = v + 1 + 1<<16
2139 if vlo == 1e4 {
2140 new = 0
2141 }
2142 } else {
2143 vlo := v & ((1 << 32) - 1)
2144 vhi := v >> 32
2145 if vlo != vhi {
2146 t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
2147 }
2148 inc := uint64(1 + 1<<32)
2149 new = v + uintptr(inc)
2150 }
2151 StorePointer(addr, unsafe.Pointer(new))
2152 }
2153
2154
2155
2156
2157
2158 func hammerStoreLoadPointerMethod(t *testing.T, paddr unsafe.Pointer) {
2159 addr := (*Pointer[byte])(paddr)
2160 v := uintptr(unsafe.Pointer(addr.Load()))
2161 new := v
2162 if arch32 {
2163 vlo := v & ((1 << 16) - 1)
2164 vhi := v >> 16
2165 if vlo != vhi {
2166 t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
2167 }
2168 new = v + 1 + 1<<16
2169 if vlo == 1e4 {
2170 new = 0
2171 }
2172 } else {
2173 vlo := v & ((1 << 32) - 1)
2174 vhi := v >> 32
2175 if vlo != vhi {
2176 t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
2177 }
2178 inc := uint64(1 + 1<<32)
2179 new = v + uintptr(inc)
2180 }
2181 addr.Store((*byte)(unsafe.Pointer(new)))
2182 }
2183
2184 func TestHammerStoreLoad(t *testing.T) {
2185 tests := []func(*testing.T, unsafe.Pointer){
2186 hammerStoreLoadInt32, hammerStoreLoadUint32,
2187 hammerStoreLoadUintptr, hammerStoreLoadPointer,
2188 hammerStoreLoadInt32Method, hammerStoreLoadUint32Method,
2189 hammerStoreLoadUintptrMethod, hammerStoreLoadPointerMethod,
2190 hammerStoreLoadInt64, hammerStoreLoadUint64,
2191 hammerStoreLoadInt64Method, hammerStoreLoadUint64Method,
2192 }
2193 n := int(1e6)
2194 if testing.Short() {
2195 n = int(1e4)
2196 }
2197 const procs = 8
2198 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(procs))
2199
2200
2201 defer debug.SetGCPercent(debug.SetGCPercent(-1))
2202
2203 runtime.GC()
2204 for _, tt := range tests {
2205 c := make(chan int)
2206 var val uint64
2207 for p := 0; p < procs; p++ {
2208 go func() {
2209 for i := 0; i < n; i++ {
2210 tt(t, unsafe.Pointer(&val))
2211 }
2212 c <- 1
2213 }()
2214 }
2215 for p := 0; p < procs; p++ {
2216 <-c
2217 }
2218 }
2219 }
2220
2221 func TestStoreLoadSeqCst32(t *testing.T) {
2222 if runtime.NumCPU() == 1 {
2223 t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
2224 }
2225 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
2226 N := int32(1e3)
2227 if testing.Short() {
2228 N = int32(1e2)
2229 }
2230 c := make(chan bool, 2)
2231 X := [2]int32{}
2232 ack := [2][3]int32{{-1, -1, -1}, {-1, -1, -1}}
2233 for p := 0; p < 2; p++ {
2234 go func(me int) {
2235 he := 1 - me
2236 for i := int32(1); i < N; i++ {
2237 StoreInt32(&X[me], i)
2238 my := LoadInt32(&X[he])
2239 StoreInt32(&ack[me][i%3], my)
2240 for w := 1; LoadInt32(&ack[he][i%3]) == -1; w++ {
2241 if w%1000 == 0 {
2242 runtime.Gosched()
2243 }
2244 }
2245 his := LoadInt32(&ack[he][i%3])
2246 if (my != i && my != i-1) || (his != i && his != i-1) {
2247 t.Errorf("invalid values: %d/%d (%d)", my, his, i)
2248 break
2249 }
2250 if my != i && his != i {
2251 t.Errorf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
2252 break
2253 }
2254 StoreInt32(&ack[me][(i-1)%3], -1)
2255 }
2256 c <- true
2257 }(p)
2258 }
2259 <-c
2260 <-c
2261 }
2262
2263 func TestStoreLoadSeqCst64(t *testing.T) {
2264 if runtime.NumCPU() == 1 {
2265 t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
2266 }
2267 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
2268 N := int64(1e3)
2269 if testing.Short() {
2270 N = int64(1e2)
2271 }
2272 c := make(chan bool, 2)
2273 X := [2]int64{}
2274 ack := [2][3]int64{{-1, -1, -1}, {-1, -1, -1}}
2275 for p := 0; p < 2; p++ {
2276 go func(me int) {
2277 he := 1 - me
2278 for i := int64(1); i < N; i++ {
2279 StoreInt64(&X[me], i)
2280 my := LoadInt64(&X[he])
2281 StoreInt64(&ack[me][i%3], my)
2282 for w := 1; LoadInt64(&ack[he][i%3]) == -1; w++ {
2283 if w%1000 == 0 {
2284 runtime.Gosched()
2285 }
2286 }
2287 his := LoadInt64(&ack[he][i%3])
2288 if (my != i && my != i-1) || (his != i && his != i-1) {
2289 t.Errorf("invalid values: %d/%d (%d)", my, his, i)
2290 break
2291 }
2292 if my != i && his != i {
2293 t.Errorf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
2294 break
2295 }
2296 StoreInt64(&ack[me][(i-1)%3], -1)
2297 }
2298 c <- true
2299 }(p)
2300 }
2301 <-c
2302 <-c
2303 }
2304
2305 func TestStoreLoadRelAcq32(t *testing.T) {
2306 if runtime.NumCPU() == 1 {
2307 t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
2308 }
2309 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
2310 N := int32(1e3)
2311 if testing.Short() {
2312 N = int32(1e2)
2313 }
2314 c := make(chan bool, 2)
2315 type Data struct {
2316 signal int32
2317 pad1 [128]int8
2318 data1 int32
2319 pad2 [128]int8
2320 data2 float32
2321 }
2322 var X Data
2323 for p := int32(0); p < 2; p++ {
2324 go func(p int32) {
2325 for i := int32(1); i < N; i++ {
2326 if (i+p)%2 == 0 {
2327 X.data1 = i
2328 X.data2 = float32(i)
2329 StoreInt32(&X.signal, i)
2330 } else {
2331 for w := 1; LoadInt32(&X.signal) != i; w++ {
2332 if w%1000 == 0 {
2333 runtime.Gosched()
2334 }
2335 }
2336 d1 := X.data1
2337 d2 := X.data2
2338 if d1 != i || d2 != float32(i) {
2339 t.Errorf("incorrect data: %d/%g (%d)", d1, d2, i)
2340 break
2341 }
2342 }
2343 }
2344 c <- true
2345 }(p)
2346 }
2347 <-c
2348 <-c
2349 }
2350
2351 func TestStoreLoadRelAcq64(t *testing.T) {
2352 if runtime.NumCPU() == 1 {
2353 t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
2354 }
2355 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
2356 N := int64(1e3)
2357 if testing.Short() {
2358 N = int64(1e2)
2359 }
2360 c := make(chan bool, 2)
2361 type Data struct {
2362 signal int64
2363 pad1 [128]int8
2364 data1 int64
2365 pad2 [128]int8
2366 data2 float64
2367 }
2368 var X Data
2369 for p := int64(0); p < 2; p++ {
2370 go func(p int64) {
2371 for i := int64(1); i < N; i++ {
2372 if (i+p)%2 == 0 {
2373 X.data1 = i
2374 X.data2 = float64(i)
2375 StoreInt64(&X.signal, i)
2376 } else {
2377 for w := 1; LoadInt64(&X.signal) != i; w++ {
2378 if w%1000 == 0 {
2379 runtime.Gosched()
2380 }
2381 }
2382 d1 := X.data1
2383 d2 := X.data2
2384 if d1 != i || d2 != float64(i) {
2385 t.Errorf("incorrect data: %d/%g (%d)", d1, d2, i)
2386 break
2387 }
2388 }
2389 }
2390 c <- true
2391 }(p)
2392 }
2393 <-c
2394 <-c
2395 }
2396
2397 func shouldPanic(t *testing.T, name string, f func()) {
2398 defer func() {
2399
2400 runtime.GC()
2401
2402 err := recover()
2403 want := "unaligned 64-bit atomic operation"
2404 if err == nil {
2405 t.Errorf("%s did not panic", name)
2406 } else if s, _ := err.(string); s != want {
2407 t.Errorf("%s: wanted panic %q, got %q", name, want, err)
2408 }
2409 }()
2410 f()
2411 }
2412
2413 func TestUnaligned64(t *testing.T) {
2414
2415
2416
2417 if !arch32 {
2418 t.Skip("test only runs on 32-bit systems")
2419 }
2420
2421 x := make([]uint32, 4)
2422 p := (*uint64)(unsafe.Pointer(&x[1]))
2423
2424 shouldPanic(t, "LoadUint64", func() { LoadUint64(p) })
2425 shouldPanic(t, "LoadUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).Load() })
2426 shouldPanic(t, "StoreUint64", func() { StoreUint64(p, 1) })
2427 shouldPanic(t, "StoreUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).Store(1) })
2428 shouldPanic(t, "CompareAndSwapUint64", func() { CompareAndSwapUint64(p, 1, 2) })
2429 shouldPanic(t, "CompareAndSwapUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).CompareAndSwap(1, 2) })
2430 shouldPanic(t, "AddUint64", func() { AddUint64(p, 3) })
2431 shouldPanic(t, "AddUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).Add(3) })
2432 }
2433
2434 func TestAutoAligned64(t *testing.T) {
2435 var signed struct {
2436 _ uint32
2437 i Int64
2438 }
2439 if o := reflect.TypeOf(&signed).Elem().Field(1).Offset; o != 8 {
2440 t.Fatalf("Int64 offset = %d, want 8", o)
2441 }
2442 if p := reflect.ValueOf(&signed).Elem().Field(1).Addr().Pointer(); p&7 != 0 {
2443 t.Fatalf("Int64 pointer = %#x, want 8-aligned", p)
2444 }
2445
2446 var unsigned struct {
2447 _ uint32
2448 i Uint64
2449 }
2450 if o := reflect.TypeOf(&unsigned).Elem().Field(1).Offset; o != 8 {
2451 t.Fatalf("Uint64 offset = %d, want 8", o)
2452 }
2453 if p := reflect.ValueOf(&unsigned).Elem().Field(1).Addr().Pointer(); p&7 != 0 {
2454 t.Fatalf("Int64 pointer = %#x, want 8-aligned", p)
2455 }
2456 }
2457
2458 func TestNilDeref(t *testing.T) {
2459 funcs := [...]func(){
2460 func() { CompareAndSwapInt32(nil, 0, 0) },
2461 func() { (*Int32)(nil).CompareAndSwap(0, 0) },
2462 func() { CompareAndSwapInt64(nil, 0, 0) },
2463 func() { (*Int64)(nil).CompareAndSwap(0, 0) },
2464 func() { CompareAndSwapUint32(nil, 0, 0) },
2465 func() { (*Uint32)(nil).CompareAndSwap(0, 0) },
2466 func() { CompareAndSwapUint64(nil, 0, 0) },
2467 func() { (*Uint64)(nil).CompareAndSwap(0, 0) },
2468 func() { CompareAndSwapUintptr(nil, 0, 0) },
2469 func() { (*Uintptr)(nil).CompareAndSwap(0, 0) },
2470 func() { CompareAndSwapPointer(nil, nil, nil) },
2471 func() { (*Pointer[byte])(nil).CompareAndSwap(nil, nil) },
2472 func() { SwapInt32(nil, 0) },
2473 func() { (*Int32)(nil).Swap(0) },
2474 func() { SwapUint32(nil, 0) },
2475 func() { (*Uint32)(nil).Swap(0) },
2476 func() { SwapInt64(nil, 0) },
2477 func() { (*Int64)(nil).Swap(0) },
2478 func() { SwapUint64(nil, 0) },
2479 func() { (*Uint64)(nil).Swap(0) },
2480 func() { SwapUintptr(nil, 0) },
2481 func() { (*Uintptr)(nil).Swap(0) },
2482 func() { SwapPointer(nil, nil) },
2483 func() { (*Pointer[byte])(nil).Swap(nil) },
2484 func() { AddInt32(nil, 0) },
2485 func() { (*Int32)(nil).Add(0) },
2486 func() { AddUint32(nil, 0) },
2487 func() { (*Uint32)(nil).Add(0) },
2488 func() { AddInt64(nil, 0) },
2489 func() { (*Int64)(nil).Add(0) },
2490 func() { AddUint64(nil, 0) },
2491 func() { (*Uint64)(nil).Add(0) },
2492 func() { AddUintptr(nil, 0) },
2493 func() { (*Uintptr)(nil).Add(0) },
2494 func() { LoadInt32(nil) },
2495 func() { (*Int32)(nil).Load() },
2496 func() { LoadInt64(nil) },
2497 func() { (*Int64)(nil).Load() },
2498 func() { LoadUint32(nil) },
2499 func() { (*Uint32)(nil).Load() },
2500 func() { LoadUint64(nil) },
2501 func() { (*Uint64)(nil).Load() },
2502 func() { LoadUintptr(nil) },
2503 func() { (*Uintptr)(nil).Load() },
2504 func() { LoadPointer(nil) },
2505 func() { (*Pointer[byte])(nil).Load() },
2506 func() { StoreInt32(nil, 0) },
2507 func() { (*Int32)(nil).Store(0) },
2508 func() { StoreInt64(nil, 0) },
2509 func() { (*Int64)(nil).Store(0) },
2510 func() { StoreUint32(nil, 0) },
2511 func() { (*Uint32)(nil).Store(0) },
2512 func() { StoreUint64(nil, 0) },
2513 func() { (*Uint64)(nil).Store(0) },
2514 func() { StoreUintptr(nil, 0) },
2515 func() { (*Uintptr)(nil).Store(0) },
2516 func() { StorePointer(nil, nil) },
2517 func() { (*Pointer[byte])(nil).Store(nil) },
2518 }
2519 for _, f := range funcs {
2520 func() {
2521 defer func() {
2522 runtime.GC()
2523 recover()
2524 }()
2525 f()
2526 }()
2527 }
2528 }
2529
2530
2531
2532 type List struct {
2533 Next Pointer[List]
2534 }
2535
View as plain text