OSDN Git Service

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