Imported Upstream version 4.8.1
[platform/upstream/gcc48.git] / libgo / go / sync / atomic / atomic_test.go
1 // Copyright 2011 The Go Authors.  All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package atomic_test
6
7 import (
8         "runtime"
9         . "sync/atomic"
10         "testing"
11         "unsafe"
12 )
13
14 // Tests of correct behavior, without contention.
15 // (Does the function work as advertised?)
16 //
17 // Test that the Add functions add correctly.
18 // Test that the CompareAndSwap functions actually
19 // do the comparison and the swap correctly.
20 //
21 // The loop over power-of-two values is meant to
22 // ensure that the operations apply to the full word size.
23 // The struct fields x.before and x.after check that the
24 // operations do not extend past the full word size.
25
26 const (
27         magic32 = 0xdedbeef
28         magic64 = 0xdeddeadbeefbeef
29 )
30
31 // Do the 64-bit functions panic?  If so, don't bother testing.
32 var test64err = func() (err interface{}) {
33         defer func() {
34                 err = recover()
35         }()
36         var x int64
37         AddInt64(&x, 1)
38         return nil
39 }()
40
41 func TestAddInt32(t *testing.T) {
42         var x struct {
43                 before int32
44                 i      int32
45                 after  int32
46         }
47         x.before = magic32
48         x.after = magic32
49         var j int32
50         for delta := int32(1); delta+delta > delta; delta += delta {
51                 k := AddInt32(&x.i, delta)
52                 j += delta
53                 if x.i != j || k != j {
54                         t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
55                 }
56         }
57         if x.before != magic32 || x.after != magic32 {
58                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
59         }
60 }
61
62 func TestAddUint32(t *testing.T) {
63         var x struct {
64                 before uint32
65                 i      uint32
66                 after  uint32
67         }
68         x.before = magic32
69         x.after = magic32
70         var j uint32
71         for delta := uint32(1); delta+delta > delta; delta += delta {
72                 k := AddUint32(&x.i, delta)
73                 j += delta
74                 if x.i != j || k != j {
75                         t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
76                 }
77         }
78         if x.before != magic32 || x.after != magic32 {
79                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
80         }
81 }
82
83 func TestAddInt64(t *testing.T) {
84         if test64err != nil {
85                 t.Skipf("Skipping 64-bit tests: %v", test64err)
86         }
87         var x struct {
88                 before int64
89                 i      int64
90                 after  int64
91         }
92         x.before = magic64
93         x.after = magic64
94         var j int64
95         for delta := int64(1); delta+delta > delta; delta += delta {
96                 k := AddInt64(&x.i, delta)
97                 j += delta
98                 if x.i != j || k != j {
99                         t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
100                 }
101         }
102         if x.before != magic64 || x.after != magic64 {
103                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, int64(magic64), int64(magic64))
104         }
105 }
106
107 func TestAddUint64(t *testing.T) {
108         if test64err != nil {
109                 t.Skipf("Skipping 64-bit tests: %v", test64err)
110         }
111         var x struct {
112                 before uint64
113                 i      uint64
114                 after  uint64
115         }
116         x.before = magic64
117         x.after = magic64
118         var j uint64
119         for delta := uint64(1); delta+delta > delta; delta += delta {
120                 k := AddUint64(&x.i, delta)
121                 j += delta
122                 if x.i != j || k != j {
123                         t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
124                 }
125         }
126         if x.before != magic64 || x.after != magic64 {
127                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
128         }
129 }
130
131 func TestAddUintptr(t *testing.T) {
132         var x struct {
133                 before uintptr
134                 i      uintptr
135                 after  uintptr
136         }
137         var m uint64 = magic64
138         magicptr := uintptr(m)
139         x.before = magicptr
140         x.after = magicptr
141         var j uintptr
142         for delta := uintptr(1); delta+delta > delta; delta += delta {
143                 k := AddUintptr(&x.i, delta)
144                 j += delta
145                 if x.i != j || k != j {
146                         t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
147                 }
148         }
149         if x.before != magicptr || x.after != magicptr {
150                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
151         }
152 }
153
154 func TestCompareAndSwapInt32(t *testing.T) {
155         var x struct {
156                 before int32
157                 i      int32
158                 after  int32
159         }
160         x.before = magic32
161         x.after = magic32
162         for val := int32(1); val+val > val; val += val {
163                 x.i = val
164                 if !CompareAndSwapInt32(&x.i, val, val+1) {
165                         t.Fatalf("should have swapped %#x %#x", val, val+1)
166                 }
167                 if x.i != val+1 {
168                         t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
169                 }
170                 x.i = val + 1
171                 if CompareAndSwapInt32(&x.i, val, val+2) {
172                         t.Fatalf("should not have swapped %#x %#x", val, val+2)
173                 }
174                 if x.i != val+1 {
175                         t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
176                 }
177         }
178         if x.before != magic32 || x.after != magic32 {
179                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
180         }
181 }
182
183 func TestCompareAndSwapUint32(t *testing.T) {
184         var x struct {
185                 before uint32
186                 i      uint32
187                 after  uint32
188         }
189         x.before = magic32
190         x.after = magic32
191         for val := uint32(1); val+val > val; val += val {
192                 x.i = val
193                 if !CompareAndSwapUint32(&x.i, val, val+1) {
194                         t.Fatalf("should have swapped %#x %#x", val, val+1)
195                 }
196                 if x.i != val+1 {
197                         t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
198                 }
199                 x.i = val + 1
200                 if CompareAndSwapUint32(&x.i, val, val+2) {
201                         t.Fatalf("should not have swapped %#x %#x", val, val+2)
202                 }
203                 if x.i != val+1 {
204                         t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
205                 }
206         }
207         if x.before != magic32 || x.after != magic32 {
208                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
209         }
210 }
211
212 func TestCompareAndSwapInt64(t *testing.T) {
213         if test64err != nil {
214                 t.Skipf("Skipping 64-bit tests: %v", test64err)
215         }
216         var x struct {
217                 before int64
218                 i      int64
219                 after  int64
220         }
221         x.before = magic64
222         x.after = magic64
223         for val := int64(1); val+val > val; val += val {
224                 x.i = val
225                 if !CompareAndSwapInt64(&x.i, val, val+1) {
226                         t.Fatalf("should have swapped %#x %#x", val, val+1)
227                 }
228                 if x.i != val+1 {
229                         t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
230                 }
231                 x.i = val + 1
232                 if CompareAndSwapInt64(&x.i, val, val+2) {
233                         t.Fatalf("should not have swapped %#x %#x", val, val+2)
234                 }
235                 if x.i != val+1 {
236                         t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
237                 }
238         }
239         if x.before != magic64 || x.after != magic64 {
240                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
241         }
242 }
243
244 func TestCompareAndSwapUint64(t *testing.T) {
245         if test64err != nil {
246                 t.Skipf("Skipping 64-bit tests: %v", test64err)
247         }
248         var x struct {
249                 before uint64
250                 i      uint64
251                 after  uint64
252         }
253         x.before = magic64
254         x.after = magic64
255         for val := uint64(1); val+val > val; val += val {
256                 x.i = val
257                 if !CompareAndSwapUint64(&x.i, val, val+1) {
258                         t.Fatalf("should have swapped %#x %#x", val, val+1)
259                 }
260                 if x.i != val+1 {
261                         t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
262                 }
263                 x.i = val + 1
264                 if CompareAndSwapUint64(&x.i, val, val+2) {
265                         t.Fatalf("should not have swapped %#x %#x", val, val+2)
266                 }
267                 if x.i != val+1 {
268                         t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
269                 }
270         }
271         if x.before != magic64 || x.after != magic64 {
272                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
273         }
274 }
275
276 func TestCompareAndSwapUintptr(t *testing.T) {
277         var x struct {
278                 before uintptr
279                 i      uintptr
280                 after  uintptr
281         }
282         var m uint64 = magic64
283         magicptr := uintptr(m)
284         x.before = magicptr
285         x.after = magicptr
286         for val := uintptr(1); val+val > val; val += val {
287                 x.i = val
288                 if !CompareAndSwapUintptr(&x.i, val, val+1) {
289                         t.Fatalf("should have swapped %#x %#x", val, val+1)
290                 }
291                 if x.i != val+1 {
292                         t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
293                 }
294                 x.i = val + 1
295                 if CompareAndSwapUintptr(&x.i, val, val+2) {
296                         t.Fatalf("should not have swapped %#x %#x", val, val+2)
297                 }
298                 if x.i != val+1 {
299                         t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
300                 }
301         }
302         if x.before != magicptr || x.after != magicptr {
303                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
304         }
305 }
306
307 func TestCompareAndSwapPointer(t *testing.T) {
308         var x struct {
309                 before uintptr
310                 i      unsafe.Pointer
311                 after  uintptr
312         }
313         var m uint64 = magic64
314         magicptr := uintptr(m)
315         x.before = magicptr
316         x.after = magicptr
317         for val := uintptr(1); val+val > val; val += val {
318                 x.i = unsafe.Pointer(val)
319                 if !CompareAndSwapPointer(&x.i, unsafe.Pointer(val), unsafe.Pointer(val+1)) {
320                         t.Fatalf("should have swapped %#x %#x", val, val+1)
321                 }
322                 if x.i != unsafe.Pointer(val+1) {
323                         t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
324                 }
325                 x.i = unsafe.Pointer(val + 1)
326                 if CompareAndSwapPointer(&x.i, unsafe.Pointer(val), unsafe.Pointer(val+2)) {
327                         t.Fatalf("should not have swapped %#x %#x", val, val+2)
328                 }
329                 if x.i != unsafe.Pointer(val+1) {
330                         t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
331                 }
332         }
333         if x.before != magicptr || x.after != magicptr {
334                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
335         }
336 }
337
338 func TestLoadInt32(t *testing.T) {
339         var x struct {
340                 before int32
341                 i      int32
342                 after  int32
343         }
344         x.before = magic32
345         x.after = magic32
346         for delta := int32(1); delta+delta > delta; delta += delta {
347                 k := LoadInt32(&x.i)
348                 if k != x.i {
349                         t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
350                 }
351                 x.i += delta
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 TestLoadUint32(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         for delta := uint32(1); delta+delta > delta; delta += delta {
367                 k := LoadUint32(&x.i)
368                 if k != x.i {
369                         t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
370                 }
371                 x.i += delta
372         }
373         if x.before != magic32 || x.after != magic32 {
374                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
375         }
376 }
377
378 func TestLoadInt64(t *testing.T) {
379         if test64err != nil {
380                 t.Skipf("Skipping 64-bit tests: %v", test64err)
381         }
382         var x struct {
383                 before int64
384                 i      int64
385                 after  int64
386         }
387         x.before = magic64
388         x.after = magic64
389         for delta := int64(1); delta+delta > delta; delta += delta {
390                 k := LoadInt64(&x.i)
391                 if k != x.i {
392                         t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
393                 }
394                 x.i += delta
395         }
396         if x.before != magic64 || x.after != magic64 {
397                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
398         }
399 }
400
401 func TestLoadUint64(t *testing.T) {
402         if test64err != nil {
403                 t.Skipf("Skipping 64-bit tests: %v", test64err)
404         }
405         var x struct {
406                 before uint64
407                 i      uint64
408                 after  uint64
409         }
410         x.before = magic64
411         x.after = magic64
412         for delta := uint64(1); delta+delta > delta; delta += delta {
413                 k := LoadUint64(&x.i)
414                 if k != x.i {
415                         t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
416                 }
417                 x.i += delta
418         }
419         if x.before != magic64 || x.after != magic64 {
420                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
421         }
422 }
423
424 func TestLoadUintptr(t *testing.T) {
425         var x struct {
426                 before uintptr
427                 i      uintptr
428                 after  uintptr
429         }
430         var m uint64 = magic64
431         magicptr := uintptr(m)
432         x.before = magicptr
433         x.after = magicptr
434         for delta := uintptr(1); delta+delta > delta; delta += delta {
435                 k := LoadUintptr(&x.i)
436                 if k != x.i {
437                         t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
438                 }
439                 x.i += delta
440         }
441         if x.before != magicptr || x.after != magicptr {
442                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
443         }
444 }
445
446 func TestLoadPointer(t *testing.T) {
447         var x struct {
448                 before uintptr
449                 i      unsafe.Pointer
450                 after  uintptr
451         }
452         var m uint64 = magic64
453         magicptr := uintptr(m)
454         x.before = magicptr
455         x.after = magicptr
456         for delta := uintptr(1); delta+delta > delta; delta += delta {
457                 k := LoadPointer(&x.i)
458                 if k != x.i {
459                         t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
460                 }
461                 x.i = unsafe.Pointer(uintptr(x.i) + delta)
462         }
463         if x.before != magicptr || x.after != magicptr {
464                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
465         }
466 }
467
468 func TestStoreInt32(t *testing.T) {
469         var x struct {
470                 before int32
471                 i      int32
472                 after  int32
473         }
474         x.before = magic32
475         x.after = magic32
476         v := int32(0)
477         for delta := int32(1); delta+delta > delta; delta += delta {
478                 StoreInt32(&x.i, v)
479                 if x.i != v {
480                         t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
481                 }
482                 v += delta
483         }
484         if x.before != magic32 || x.after != magic32 {
485                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
486         }
487 }
488
489 func TestStoreUint32(t *testing.T) {
490         var x struct {
491                 before uint32
492                 i      uint32
493                 after  uint32
494         }
495         x.before = magic32
496         x.after = magic32
497         v := uint32(0)
498         for delta := uint32(1); delta+delta > delta; delta += delta {
499                 StoreUint32(&x.i, v)
500                 if x.i != v {
501                         t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
502                 }
503                 v += delta
504         }
505         if x.before != magic32 || x.after != magic32 {
506                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
507         }
508 }
509
510 func TestStoreInt64(t *testing.T) {
511         if test64err != nil {
512                 t.Skipf("Skipping 64-bit tests: %v", test64err)
513         }
514         var x struct {
515                 before int64
516                 i      int64
517                 after  int64
518         }
519         x.before = magic64
520         x.after = magic64
521         v := int64(0)
522         for delta := int64(1); delta+delta > delta; delta += delta {
523                 StoreInt64(&x.i, v)
524                 if x.i != v {
525                         t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
526                 }
527                 v += delta
528         }
529         if x.before != magic64 || x.after != magic64 {
530                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
531         }
532 }
533
534 func TestStoreUint64(t *testing.T) {
535         if test64err != nil {
536                 t.Skipf("Skipping 64-bit tests: %v", test64err)
537         }
538         var x struct {
539                 before uint64
540                 i      uint64
541                 after  uint64
542         }
543         x.before = magic64
544         x.after = magic64
545         v := uint64(0)
546         for delta := uint64(1); delta+delta > delta; delta += delta {
547                 StoreUint64(&x.i, v)
548                 if x.i != v {
549                         t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
550                 }
551                 v += delta
552         }
553         if x.before != magic64 || x.after != magic64 {
554                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
555         }
556 }
557
558 func TestStoreUintptr(t *testing.T) {
559         var x struct {
560                 before uintptr
561                 i      uintptr
562                 after  uintptr
563         }
564         var m uint64 = magic64
565         magicptr := uintptr(m)
566         x.before = magicptr
567         x.after = magicptr
568         v := uintptr(0)
569         for delta := uintptr(1); delta+delta > delta; delta += delta {
570                 StoreUintptr(&x.i, v)
571                 if x.i != v {
572                         t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
573                 }
574                 v += delta
575         }
576         if x.before != magicptr || x.after != magicptr {
577                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
578         }
579 }
580
581 func TestStorePointer(t *testing.T) {
582         var x struct {
583                 before uintptr
584                 i      unsafe.Pointer
585                 after  uintptr
586         }
587         var m uint64 = magic64
588         magicptr := uintptr(m)
589         x.before = magicptr
590         x.after = magicptr
591         v := unsafe.Pointer(uintptr(0))
592         for delta := uintptr(1); delta+delta > delta; delta += delta {
593                 StorePointer(&x.i, unsafe.Pointer(v))
594                 if x.i != v {
595                         t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
596                 }
597                 v = unsafe.Pointer(uintptr(v) + delta)
598         }
599         if x.before != magicptr || x.after != magicptr {
600                 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
601         }
602 }
603
604 // Tests of correct behavior, with contention.
605 // (Is the function atomic?)
606 //
607 // For each function, we write a "hammer" function that repeatedly
608 // uses the atomic operation to add 1 to a value.  After running
609 // multiple hammers in parallel, check that we end with the correct
610 // total.
611
612 var hammer32 = []struct {
613         name string
614         f    func(*uint32, int)
615 }{
616         {"AddInt32", hammerAddInt32},
617         {"AddUint32", hammerAddUint32},
618         {"AddUintptr", hammerAddUintptr32},
619         {"CompareAndSwapInt32", hammerCompareAndSwapInt32},
620         {"CompareAndSwapUint32", hammerCompareAndSwapUint32},
621         {"CompareAndSwapUintptr", hammerCompareAndSwapUintptr32},
622         {"CompareAndSwapPointer", hammerCompareAndSwapPointer32},
623 }
624
625 func init() {
626         var v uint64 = 1 << 50
627         if uintptr(v) != 0 {
628                 // 64-bit system; clear uintptr tests
629                 hammer32[2].f = nil
630                 hammer32[5].f = nil
631                 hammer32[6].f = nil
632         }
633 }
634
635 func hammerAddInt32(uaddr *uint32, count int) {
636         addr := (*int32)(unsafe.Pointer(uaddr))
637         for i := 0; i < count; i++ {
638                 AddInt32(addr, 1)
639         }
640 }
641
642 func hammerAddUint32(addr *uint32, count int) {
643         for i := 0; i < count; i++ {
644                 AddUint32(addr, 1)
645         }
646 }
647
648 func hammerAddUintptr32(uaddr *uint32, count int) {
649         // only safe when uintptr is 32-bit.
650         // not called on 64-bit systems.
651         addr := (*uintptr)(unsafe.Pointer(uaddr))
652         for i := 0; i < count; i++ {
653                 AddUintptr(addr, 1)
654         }
655 }
656
657 func hammerCompareAndSwapInt32(uaddr *uint32, count int) {
658         addr := (*int32)(unsafe.Pointer(uaddr))
659         for i := 0; i < count; i++ {
660                 for {
661                         v := *addr
662                         if CompareAndSwapInt32(addr, v, v+1) {
663                                 break
664                         }
665                 }
666         }
667 }
668
669 func hammerCompareAndSwapUint32(addr *uint32, count int) {
670         for i := 0; i < count; i++ {
671                 for {
672                         v := *addr
673                         if CompareAndSwapUint32(addr, v, v+1) {
674                                 break
675                         }
676                 }
677         }
678 }
679
680 func hammerCompareAndSwapUintptr32(uaddr *uint32, count int) {
681         // only safe when uintptr is 32-bit.
682         // not called on 64-bit systems.
683         addr := (*uintptr)(unsafe.Pointer(uaddr))
684         for i := 0; i < count; i++ {
685                 for {
686                         v := *addr
687                         if CompareAndSwapUintptr(addr, v, v+1) {
688                                 break
689                         }
690                 }
691         }
692 }
693
694 func hammerCompareAndSwapPointer32(uaddr *uint32, count int) {
695         // only safe when uintptr is 32-bit.
696         // not called on 64-bit systems.
697         addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
698         for i := 0; i < count; i++ {
699                 for {
700                         v := *addr
701                         if CompareAndSwapPointer(addr, v, unsafe.Pointer(uintptr(v)+1)) {
702                                 break
703                         }
704                 }
705         }
706 }
707
708 func TestHammer32(t *testing.T) {
709         const p = 4
710         n := 100000
711         if testing.Short() {
712                 n = 1000
713         }
714         defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
715
716         for _, tt := range hammer32 {
717                 if tt.f == nil {
718                         continue
719                 }
720                 c := make(chan int)
721                 var val uint32
722                 for i := 0; i < p; i++ {
723                         go func() {
724                                 tt.f(&val, n)
725                                 c <- 1
726                         }()
727                 }
728                 for i := 0; i < p; i++ {
729                         <-c
730                 }
731                 if val != uint32(n)*p {
732                         t.Fatalf("%s: val=%d want %d", tt.name, val, n*p)
733                 }
734         }
735 }
736
737 var hammer64 = []struct {
738         name string
739         f    func(*uint64, int)
740 }{
741         {"AddInt64", hammerAddInt64},
742         {"AddUint64", hammerAddUint64},
743         {"AddUintptr", hammerAddUintptr64},
744         {"CompareAndSwapInt64", hammerCompareAndSwapInt64},
745         {"CompareAndSwapUint64", hammerCompareAndSwapUint64},
746         {"CompareAndSwapUintptr", hammerCompareAndSwapUintptr64},
747         {"CompareAndSwapPointer", hammerCompareAndSwapPointer64},
748 }
749
750 func init() {
751         var v uint64 = 1 << 50
752         if uintptr(v) == 0 {
753                 // 32-bit system; clear uintptr tests
754                 hammer64[2].f = nil
755                 hammer64[5].f = nil
756                 hammer64[6].f = nil
757         }
758 }
759
760 func hammerAddInt64(uaddr *uint64, count int) {
761         addr := (*int64)(unsafe.Pointer(uaddr))
762         for i := 0; i < count; i++ {
763                 AddInt64(addr, 1)
764         }
765 }
766
767 func hammerAddUint64(addr *uint64, count int) {
768         for i := 0; i < count; i++ {
769                 AddUint64(addr, 1)
770         }
771 }
772
773 func hammerAddUintptr64(uaddr *uint64, count int) {
774         // only safe when uintptr is 64-bit.
775         // not called on 32-bit systems.
776         addr := (*uintptr)(unsafe.Pointer(uaddr))
777         for i := 0; i < count; i++ {
778                 AddUintptr(addr, 1)
779         }
780 }
781
782 func hammerCompareAndSwapInt64(uaddr *uint64, count int) {
783         addr := (*int64)(unsafe.Pointer(uaddr))
784         for i := 0; i < count; i++ {
785                 for {
786                         v := *addr
787                         if CompareAndSwapInt64(addr, v, v+1) {
788                                 break
789                         }
790                 }
791         }
792 }
793
794 func hammerCompareAndSwapUint64(addr *uint64, count int) {
795         for i := 0; i < count; i++ {
796                 for {
797                         v := *addr
798                         if CompareAndSwapUint64(addr, v, v+1) {
799                                 break
800                         }
801                 }
802         }
803 }
804
805 func hammerCompareAndSwapUintptr64(uaddr *uint64, count int) {
806         // only safe when uintptr is 64-bit.
807         // not called on 32-bit systems.
808         addr := (*uintptr)(unsafe.Pointer(uaddr))
809         for i := 0; i < count; i++ {
810                 for {
811                         v := *addr
812                         if CompareAndSwapUintptr(addr, v, v+1) {
813                                 break
814                         }
815                 }
816         }
817 }
818
819 func hammerCompareAndSwapPointer64(uaddr *uint64, count int) {
820         // only safe when uintptr is 64-bit.
821         // not called on 32-bit systems.
822         addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
823         for i := 0; i < count; i++ {
824                 for {
825                         v := *addr
826                         if CompareAndSwapPointer(addr, v, unsafe.Pointer(uintptr(v)+1)) {
827                                 break
828                         }
829                 }
830         }
831 }
832
833 func TestHammer64(t *testing.T) {
834         if test64err != nil {
835                 t.Skipf("Skipping 64-bit tests: %v", test64err)
836         }
837         const p = 4
838         n := 100000
839         if testing.Short() {
840                 n = 1000
841         }
842         defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
843
844         for _, tt := range hammer64 {
845                 if tt.f == nil {
846                         continue
847                 }
848                 c := make(chan int)
849                 var val uint64
850                 for i := 0; i < p; i++ {
851                         go func() {
852                                 tt.f(&val, n)
853                                 c <- 1
854                         }()
855                 }
856                 for i := 0; i < p; i++ {
857                         <-c
858                 }
859                 if val != uint64(n)*p {
860                         t.Fatalf("%s: val=%d want %d", tt.name, val, n*p)
861                 }
862         }
863 }
864
865 func hammerStoreLoadInt32(t *testing.T, paddr unsafe.Pointer) {
866         addr := (*int32)(paddr)
867         v := LoadInt32(addr)
868         vlo := v & ((1 << 16) - 1)
869         vhi := v >> 16
870         if vlo != vhi {
871                 t.Fatalf("Int32: %#x != %#x", vlo, vhi)
872         }
873         new := v + 1 + 1<<16
874         if vlo == 1e4 {
875                 new = 0
876         }
877         StoreInt32(addr, new)
878 }
879
880 func hammerStoreLoadUint32(t *testing.T, paddr unsafe.Pointer) {
881         addr := (*uint32)(paddr)
882         v := LoadUint32(addr)
883         vlo := v & ((1 << 16) - 1)
884         vhi := v >> 16
885         if vlo != vhi {
886                 t.Fatalf("Uint32: %#x != %#x", vlo, vhi)
887         }
888         new := v + 1 + 1<<16
889         if vlo == 1e4 {
890                 new = 0
891         }
892         StoreUint32(addr, new)
893 }
894
895 func hammerStoreLoadInt64(t *testing.T, paddr unsafe.Pointer) {
896         addr := (*int64)(paddr)
897         v := LoadInt64(addr)
898         vlo := v & ((1 << 32) - 1)
899         vhi := v >> 32
900         if vlo != vhi {
901                 t.Fatalf("Int64: %#x != %#x", vlo, vhi)
902         }
903         new := v + 1 + 1<<32
904         StoreInt64(addr, new)
905 }
906
907 func hammerStoreLoadUint64(t *testing.T, paddr unsafe.Pointer) {
908         addr := (*uint64)(paddr)
909         v := LoadUint64(addr)
910         vlo := v & ((1 << 32) - 1)
911         vhi := v >> 32
912         if vlo != vhi {
913                 t.Fatalf("Uint64: %#x != %#x", vlo, vhi)
914         }
915         new := v + 1 + 1<<32
916         StoreUint64(addr, new)
917 }
918
919 func hammerStoreLoadUintptr(t *testing.T, paddr unsafe.Pointer) {
920         addr := (*uintptr)(paddr)
921         var test64 uint64 = 1 << 50
922         arch32 := uintptr(test64) == 0
923         v := LoadUintptr(addr)
924         new := v
925         if arch32 {
926                 vlo := v & ((1 << 16) - 1)
927                 vhi := v >> 16
928                 if vlo != vhi {
929                         t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
930                 }
931                 new = v + 1 + 1<<16
932                 if vlo == 1e4 {
933                         new = 0
934                 }
935         } else {
936                 vlo := v & ((1 << 32) - 1)
937                 vhi := v >> 32
938                 if vlo != vhi {
939                         t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
940                 }
941                 inc := uint64(1 + 1<<32)
942                 new = v + uintptr(inc)
943         }
944         StoreUintptr(addr, new)
945 }
946
947 func hammerStoreLoadPointer(t *testing.T, paddr unsafe.Pointer) {
948         addr := (*unsafe.Pointer)(paddr)
949         var test64 uint64 = 1 << 50
950         arch32 := uintptr(test64) == 0
951         v := uintptr(LoadPointer(addr))
952         new := v
953         if arch32 {
954                 vlo := v & ((1 << 16) - 1)
955                 vhi := v >> 16
956                 if vlo != vhi {
957                         t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
958                 }
959                 new = v + 1 + 1<<16
960                 if vlo == 1e4 {
961                         new = 0
962                 }
963         } else {
964                 vlo := v & ((1 << 32) - 1)
965                 vhi := v >> 32
966                 if vlo != vhi {
967                         t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
968                 }
969                 inc := uint64(1 + 1<<32)
970                 new = v + uintptr(inc)
971         }
972         StorePointer(addr, unsafe.Pointer(new))
973 }
974
975 func TestHammerStoreLoad(t *testing.T) {
976         var tests []func(*testing.T, unsafe.Pointer)
977         tests = append(tests, hammerStoreLoadInt32, hammerStoreLoadUint32,
978                 hammerStoreLoadUintptr, hammerStoreLoadPointer)
979         if test64err == nil {
980                 tests = append(tests, hammerStoreLoadInt64, hammerStoreLoadUint64)
981         }
982         n := int(1e6)
983         if testing.Short() {
984                 n = int(1e4)
985         }
986         const procs = 8
987         defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(procs))
988         for _, tt := range tests {
989                 c := make(chan int)
990                 var val uint64
991                 for p := 0; p < procs; p++ {
992                         go func() {
993                                 for i := 0; i < n; i++ {
994                                         tt(t, unsafe.Pointer(&val))
995                                 }
996                                 c <- 1
997                         }()
998                 }
999                 for p := 0; p < procs; p++ {
1000                         <-c
1001                 }
1002         }
1003 }
1004
1005 func TestStoreLoadSeqCst32(t *testing.T) {
1006         if runtime.NumCPU() == 1 {
1007                 t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
1008         }
1009         defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
1010         N := int32(1e3)
1011         if testing.Short() {
1012                 N = int32(1e2)
1013         }
1014         c := make(chan bool, 2)
1015         X := [2]int32{}
1016         ack := [2][3]int32{{-1, -1, -1}, {-1, -1, -1}}
1017         for p := 0; p < 2; p++ {
1018                 go func(me int) {
1019                         he := 1 - me
1020                         for i := int32(1); i < N; i++ {
1021                                 StoreInt32(&X[me], i)
1022                                 my := LoadInt32(&X[he])
1023                                 StoreInt32(&ack[me][i%3], my)
1024                                 for w := 1; LoadInt32(&ack[he][i%3]) == -1; w++ {
1025                                         if w%1000 == 0 {
1026                                                 runtime.Gosched()
1027                                         }
1028                                 }
1029                                 his := LoadInt32(&ack[he][i%3])
1030                                 if (my != i && my != i-1) || (his != i && his != i-1) {
1031                                         t.Fatalf("invalid values: %d/%d (%d)", my, his, i)
1032                                 }
1033                                 if my != i && his != i {
1034                                         t.Fatalf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
1035                                 }
1036                                 StoreInt32(&ack[me][(i-1)%3], -1)
1037                         }
1038                         c <- true
1039                 }(p)
1040         }
1041         <-c
1042         <-c
1043 }
1044
1045 func TestStoreLoadSeqCst64(t *testing.T) {
1046         if runtime.NumCPU() == 1 {
1047                 t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
1048         }
1049         if test64err != nil {
1050                 t.Skipf("Skipping 64-bit tests: %v", test64err)
1051         }
1052         defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
1053         N := int64(1e3)
1054         if testing.Short() {
1055                 N = int64(1e2)
1056         }
1057         c := make(chan bool, 2)
1058         X := [2]int64{}
1059         ack := [2][3]int64{{-1, -1, -1}, {-1, -1, -1}}
1060         for p := 0; p < 2; p++ {
1061                 go func(me int) {
1062                         he := 1 - me
1063                         for i := int64(1); i < N; i++ {
1064                                 StoreInt64(&X[me], i)
1065                                 my := LoadInt64(&X[he])
1066                                 StoreInt64(&ack[me][i%3], my)
1067                                 for w := 1; LoadInt64(&ack[he][i%3]) == -1; w++ {
1068                                         if w%1000 == 0 {
1069                                                 runtime.Gosched()
1070                                         }
1071                                 }
1072                                 his := LoadInt64(&ack[he][i%3])
1073                                 if (my != i && my != i-1) || (his != i && his != i-1) {
1074                                         t.Fatalf("invalid values: %d/%d (%d)", my, his, i)
1075                                 }
1076                                 if my != i && his != i {
1077                                         t.Fatalf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
1078                                 }
1079                                 StoreInt64(&ack[me][(i-1)%3], -1)
1080                         }
1081                         c <- true
1082                 }(p)
1083         }
1084         <-c
1085         <-c
1086 }
1087
1088 func TestStoreLoadRelAcq32(t *testing.T) {
1089         if runtime.NumCPU() == 1 {
1090                 t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
1091         }
1092         defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
1093         N := int32(1e3)
1094         if testing.Short() {
1095                 N = int32(1e2)
1096         }
1097         c := make(chan bool, 2)
1098         type Data struct {
1099                 signal int32
1100                 pad1   [128]int8
1101                 data1  int32
1102                 pad2   [128]int8
1103                 data2  float32
1104         }
1105         var X Data
1106         for p := int32(0); p < 2; p++ {
1107                 go func(p int32) {
1108                         for i := int32(1); i < N; i++ {
1109                                 if (i+p)%2 == 0 {
1110                                         X.data1 = i
1111                                         X.data2 = float32(i)
1112                                         StoreInt32(&X.signal, i)
1113                                 } else {
1114                                         for w := 1; LoadInt32(&X.signal) != i; w++ {
1115                                                 if w%1000 == 0 {
1116                                                         runtime.Gosched()
1117                                                 }
1118                                         }
1119                                         d1 := X.data1
1120                                         d2 := X.data2
1121                                         if d1 != i || d2 != float32(i) {
1122                                                 t.Fatalf("incorrect data: %d/%d (%d)", d1, d2, i)
1123                                         }
1124                                 }
1125                         }
1126                         c <- true
1127                 }(p)
1128         }
1129         <-c
1130         <-c
1131 }
1132
1133 func TestStoreLoadRelAcq64(t *testing.T) {
1134         if runtime.NumCPU() == 1 {
1135                 t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
1136         }
1137         if test64err != nil {
1138                 t.Skipf("Skipping 64-bit tests: %v", test64err)
1139         }
1140         defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
1141         N := int64(1e3)
1142         if testing.Short() {
1143                 N = int64(1e2)
1144         }
1145         c := make(chan bool, 2)
1146         type Data struct {
1147                 signal int64
1148                 pad1   [128]int8
1149                 data1  int64
1150                 pad2   [128]int8
1151                 data2  float64
1152         }
1153         var X Data
1154         for p := int64(0); p < 2; p++ {
1155                 go func(p int64) {
1156                         for i := int64(1); i < N; i++ {
1157                                 if (i+p)%2 == 0 {
1158                                         X.data1 = i
1159                                         X.data2 = float64(i)
1160                                         StoreInt64(&X.signal, i)
1161                                 } else {
1162                                         for w := 1; LoadInt64(&X.signal) != i; w++ {
1163                                                 if w%1000 == 0 {
1164                                                         runtime.Gosched()
1165                                                 }
1166                                         }
1167                                         d1 := X.data1
1168                                         d2 := X.data2
1169                                         if d1 != i || d2 != float64(i) {
1170                                                 t.Fatalf("incorrect data: %d/%d (%d)", d1, d2, i)
1171                                         }
1172                                 }
1173                         }
1174                         c <- true
1175                 }(p)
1176         }
1177         <-c
1178         <-c
1179 }