OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [sync/] [atomic/] [atomic_test.go] - Blame information for rev 747

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// 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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.