Home | History | Annotate | Download | only in atomic
      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 	"fmt"
      9 	"runtime"
     10 	"strings"
     11 	. "sync/atomic"
     12 	"testing"
     13 	"unsafe"
     14 )
     15 
     16 // Tests of correct behavior, without contention.
     17 // (Does the function work as advertised?)
     18 //
     19 // Test that the Add functions add correctly.
     20 // Test that the CompareAndSwap functions actually
     21 // do the comparison and the swap correctly.
     22 //
     23 // The loop over power-of-two values is meant to
     24 // ensure that the operations apply to the full word size.
     25 // The struct fields x.before and x.after check that the
     26 // operations do not extend past the full word size.
     27 
     28 const (
     29 	magic32 = 0xdedbeef
     30 	magic64 = 0xdeddeadbeefbeef
     31 )
     32 
     33 // Do the 64-bit functions panic? If so, don't bother testing.
     34 var test64err = func() (err interface{}) {
     35 	defer func() {
     36 		err = recover()
     37 	}()
     38 	var x int64
     39 	AddInt64(&x, 1)
     40 	return nil
     41 }()
     42 
     43 func TestSwapInt32(t *testing.T) {
     44 	var x struct {
     45 		before int32
     46 		i      int32
     47 		after  int32
     48 	}
     49 	x.before = magic32
     50 	x.after = magic32
     51 	var j int32
     52 	for delta := int32(1); delta+delta > delta; delta += delta {
     53 		k := SwapInt32(&x.i, delta)
     54 		if x.i != delta || k != j {
     55 			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
     56 		}
     57 		j = delta
     58 	}
     59 	if x.before != magic32 || x.after != magic32 {
     60 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
     61 	}
     62 }
     63 
     64 func TestSwapUint32(t *testing.T) {
     65 	var x struct {
     66 		before uint32
     67 		i      uint32
     68 		after  uint32
     69 	}
     70 	x.before = magic32
     71 	x.after = magic32
     72 	var j uint32
     73 	for delta := uint32(1); delta+delta > delta; delta += delta {
     74 		k := SwapUint32(&x.i, delta)
     75 		if x.i != delta || k != j {
     76 			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
     77 		}
     78 		j = delta
     79 	}
     80 	if x.before != magic32 || x.after != magic32 {
     81 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
     82 	}
     83 }
     84 
     85 func TestSwapInt64(t *testing.T) {
     86 	if test64err != nil {
     87 		t.Skipf("Skipping 64-bit tests: %v", test64err)
     88 	}
     89 	var x struct {
     90 		before int64
     91 		i      int64
     92 		after  int64
     93 	}
     94 	x.before = magic64
     95 	x.after = magic64
     96 	var j int64
     97 	for delta := int64(1); delta+delta > delta; delta += delta {
     98 		k := SwapInt64(&x.i, delta)
     99 		if x.i != delta || k != j {
    100 			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
    101 		}
    102 		j = delta
    103 	}
    104 	if x.before != magic64 || x.after != magic64 {
    105 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
    106 	}
    107 }
    108 
    109 func TestSwapUint64(t *testing.T) {
    110 	if test64err != nil {
    111 		t.Skipf("Skipping 64-bit tests: %v", test64err)
    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 := SwapUint64(&x.i, delta)
    123 		if x.i != delta || k != j {
    124 			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
    125 		}
    126 		j = delta
    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 TestSwapUintptr(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 := SwapUintptr(&x.i, delta)
    146 		if x.i != delta || k != j {
    147 			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
    148 		}
    149 		j = delta
    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 TestSwapPointer(t *testing.T) {
    157 	var x struct {
    158 		before uintptr
    159 		i      unsafe.Pointer
    160 		after  uintptr
    161 	}
    162 	var m uint64 = magic64
    163 	magicptr := uintptr(m)
    164 	x.before = magicptr
    165 	x.after = magicptr
    166 	var j uintptr
    167 	for delta := uintptr(1 << 16); delta+delta > delta; delta += delta {
    168 		k := SwapPointer(&x.i, unsafe.Pointer(delta))
    169 		if uintptr(x.i) != delta || uintptr(k) != j {
    170 			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
    171 		}
    172 		j = delta
    173 	}
    174 	if x.before != magicptr || x.after != magicptr {
    175 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
    176 	}
    177 }
    178 
    179 func TestAddInt32(t *testing.T) {
    180 	var x struct {
    181 		before int32
    182 		i      int32
    183 		after  int32
    184 	}
    185 	x.before = magic32
    186 	x.after = magic32
    187 	var j int32
    188 	for delta := int32(1); delta+delta > delta; delta += delta {
    189 		k := AddInt32(&x.i, delta)
    190 		j += delta
    191 		if x.i != j || k != j {
    192 			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
    193 		}
    194 	}
    195 	if x.before != magic32 || x.after != magic32 {
    196 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
    197 	}
    198 }
    199 
    200 func TestAddUint32(t *testing.T) {
    201 	var x struct {
    202 		before uint32
    203 		i      uint32
    204 		after  uint32
    205 	}
    206 	x.before = magic32
    207 	x.after = magic32
    208 	var j uint32
    209 	for delta := uint32(1); delta+delta > delta; delta += delta {
    210 		k := AddUint32(&x.i, delta)
    211 		j += delta
    212 		if x.i != j || k != j {
    213 			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
    214 		}
    215 	}
    216 	if x.before != magic32 || x.after != magic32 {
    217 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
    218 	}
    219 }
    220 
    221 func TestAddInt64(t *testing.T) {
    222 	if test64err != nil {
    223 		t.Skipf("Skipping 64-bit tests: %v", test64err)
    224 	}
    225 	var x struct {
    226 		before int64
    227 		i      int64
    228 		after  int64
    229 	}
    230 	x.before = magic64
    231 	x.after = magic64
    232 	var j int64
    233 	for delta := int64(1); delta+delta > delta; delta += delta {
    234 		k := AddInt64(&x.i, delta)
    235 		j += delta
    236 		if x.i != j || k != j {
    237 			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
    238 		}
    239 	}
    240 	if x.before != magic64 || x.after != magic64 {
    241 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, int64(magic64), int64(magic64))
    242 	}
    243 }
    244 
    245 func TestAddUint64(t *testing.T) {
    246 	if test64err != nil {
    247 		t.Skipf("Skipping 64-bit tests: %v", test64err)
    248 	}
    249 	var x struct {
    250 		before uint64
    251 		i      uint64
    252 		after  uint64
    253 	}
    254 	x.before = magic64
    255 	x.after = magic64
    256 	var j uint64
    257 	for delta := uint64(1); delta+delta > delta; delta += delta {
    258 		k := AddUint64(&x.i, delta)
    259 		j += delta
    260 		if x.i != j || k != j {
    261 			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
    262 		}
    263 	}
    264 	if x.before != magic64 || x.after != magic64 {
    265 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
    266 	}
    267 }
    268 
    269 func TestAddUintptr(t *testing.T) {
    270 	var x struct {
    271 		before uintptr
    272 		i      uintptr
    273 		after  uintptr
    274 	}
    275 	var m uint64 = magic64
    276 	magicptr := uintptr(m)
    277 	x.before = magicptr
    278 	x.after = magicptr
    279 	var j uintptr
    280 	for delta := uintptr(1); delta+delta > delta; delta += delta {
    281 		k := AddUintptr(&x.i, delta)
    282 		j += delta
    283 		if x.i != j || k != j {
    284 			t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
    285 		}
    286 	}
    287 	if x.before != magicptr || x.after != magicptr {
    288 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
    289 	}
    290 }
    291 
    292 func TestCompareAndSwapInt32(t *testing.T) {
    293 	var x struct {
    294 		before int32
    295 		i      int32
    296 		after  int32
    297 	}
    298 	x.before = magic32
    299 	x.after = magic32
    300 	for val := int32(1); val+val > val; val += val {
    301 		x.i = val
    302 		if !CompareAndSwapInt32(&x.i, val, val+1) {
    303 			t.Fatalf("should have swapped %#x %#x", val, val+1)
    304 		}
    305 		if x.i != val+1 {
    306 			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
    307 		}
    308 		x.i = val + 1
    309 		if CompareAndSwapInt32(&x.i, val, val+2) {
    310 			t.Fatalf("should not have swapped %#x %#x", val, val+2)
    311 		}
    312 		if x.i != val+1 {
    313 			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
    314 		}
    315 	}
    316 	if x.before != magic32 || x.after != magic32 {
    317 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
    318 	}
    319 }
    320 
    321 func TestCompareAndSwapUint32(t *testing.T) {
    322 	var x struct {
    323 		before uint32
    324 		i      uint32
    325 		after  uint32
    326 	}
    327 	x.before = magic32
    328 	x.after = magic32
    329 	for val := uint32(1); val+val > val; val += val {
    330 		x.i = val
    331 		if !CompareAndSwapUint32(&x.i, val, val+1) {
    332 			t.Fatalf("should have swapped %#x %#x", val, val+1)
    333 		}
    334 		if x.i != val+1 {
    335 			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
    336 		}
    337 		x.i = val + 1
    338 		if CompareAndSwapUint32(&x.i, val, val+2) {
    339 			t.Fatalf("should not have swapped %#x %#x", val, val+2)
    340 		}
    341 		if x.i != val+1 {
    342 			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
    343 		}
    344 	}
    345 	if x.before != magic32 || x.after != magic32 {
    346 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
    347 	}
    348 }
    349 
    350 func TestCompareAndSwapInt64(t *testing.T) {
    351 	if test64err != nil {
    352 		t.Skipf("Skipping 64-bit tests: %v", test64err)
    353 	}
    354 	var x struct {
    355 		before int64
    356 		i      int64
    357 		after  int64
    358 	}
    359 	x.before = magic64
    360 	x.after = magic64
    361 	for val := int64(1); val+val > val; val += val {
    362 		x.i = val
    363 		if !CompareAndSwapInt64(&x.i, val, val+1) {
    364 			t.Fatalf("should have swapped %#x %#x", val, val+1)
    365 		}
    366 		if x.i != val+1 {
    367 			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
    368 		}
    369 		x.i = val + 1
    370 		if CompareAndSwapInt64(&x.i, val, val+2) {
    371 			t.Fatalf("should not have swapped %#x %#x", val, val+2)
    372 		}
    373 		if x.i != val+1 {
    374 			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
    375 		}
    376 	}
    377 	if x.before != magic64 || x.after != magic64 {
    378 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
    379 	}
    380 }
    381 
    382 func testCompareAndSwapUint64(t *testing.T, cas func(*uint64, uint64, uint64) bool) {
    383 	if test64err != nil {
    384 		t.Skipf("Skipping 64-bit tests: %v", test64err)
    385 	}
    386 	var x struct {
    387 		before uint64
    388 		i      uint64
    389 		after  uint64
    390 	}
    391 	x.before = magic64
    392 	x.after = magic64
    393 	for val := uint64(1); val+val > val; val += val {
    394 		x.i = val
    395 		if !cas(&x.i, val, val+1) {
    396 			t.Fatalf("should have swapped %#x %#x", val, val+1)
    397 		}
    398 		if x.i != val+1 {
    399 			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
    400 		}
    401 		x.i = val + 1
    402 		if cas(&x.i, val, val+2) {
    403 			t.Fatalf("should not have swapped %#x %#x", val, val+2)
    404 		}
    405 		if x.i != val+1 {
    406 			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
    407 		}
    408 	}
    409 	if x.before != magic64 || x.after != magic64 {
    410 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
    411 	}
    412 }
    413 
    414 func TestCompareAndSwapUint64(t *testing.T) {
    415 	testCompareAndSwapUint64(t, CompareAndSwapUint64)
    416 }
    417 
    418 func TestCompareAndSwapUintptr(t *testing.T) {
    419 	var x struct {
    420 		before uintptr
    421 		i      uintptr
    422 		after  uintptr
    423 	}
    424 	var m uint64 = magic64
    425 	magicptr := uintptr(m)
    426 	x.before = magicptr
    427 	x.after = magicptr
    428 	for val := uintptr(1); val+val > val; val += val {
    429 		x.i = val
    430 		if !CompareAndSwapUintptr(&x.i, val, val+1) {
    431 			t.Fatalf("should have swapped %#x %#x", val, val+1)
    432 		}
    433 		if x.i != val+1 {
    434 			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
    435 		}
    436 		x.i = val + 1
    437 		if CompareAndSwapUintptr(&x.i, val, val+2) {
    438 			t.Fatalf("should not have swapped %#x %#x", val, val+2)
    439 		}
    440 		if x.i != val+1 {
    441 			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
    442 		}
    443 	}
    444 	if x.before != magicptr || x.after != magicptr {
    445 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
    446 	}
    447 }
    448 
    449 func TestCompareAndSwapPointer(t *testing.T) {
    450 	var x struct {
    451 		before uintptr
    452 		i      unsafe.Pointer
    453 		after  uintptr
    454 	}
    455 	var m uint64 = magic64
    456 	magicptr := uintptr(m)
    457 	x.before = magicptr
    458 	x.after = magicptr
    459 	for val := uintptr(1 << 16); val+val > val; val += val {
    460 		x.i = unsafe.Pointer(val)
    461 		if !CompareAndSwapPointer(&x.i, unsafe.Pointer(val), unsafe.Pointer(val+1)) {
    462 			t.Fatalf("should have swapped %#x %#x", val, val+1)
    463 		}
    464 		if x.i != unsafe.Pointer(val+1) {
    465 			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
    466 		}
    467 		x.i = unsafe.Pointer(val + 1)
    468 		if CompareAndSwapPointer(&x.i, unsafe.Pointer(val), unsafe.Pointer(val+2)) {
    469 			t.Fatalf("should not have swapped %#x %#x", val, val+2)
    470 		}
    471 		if x.i != unsafe.Pointer(val+1) {
    472 			t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
    473 		}
    474 	}
    475 	if x.before != magicptr || x.after != magicptr {
    476 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
    477 	}
    478 }
    479 
    480 func TestLoadInt32(t *testing.T) {
    481 	var x struct {
    482 		before int32
    483 		i      int32
    484 		after  int32
    485 	}
    486 	x.before = magic32
    487 	x.after = magic32
    488 	for delta := int32(1); delta+delta > delta; delta += delta {
    489 		k := LoadInt32(&x.i)
    490 		if k != x.i {
    491 			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
    492 		}
    493 		x.i += delta
    494 	}
    495 	if x.before != magic32 || x.after != magic32 {
    496 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
    497 	}
    498 }
    499 
    500 func TestLoadUint32(t *testing.T) {
    501 	var x struct {
    502 		before uint32
    503 		i      uint32
    504 		after  uint32
    505 	}
    506 	x.before = magic32
    507 	x.after = magic32
    508 	for delta := uint32(1); delta+delta > delta; delta += delta {
    509 		k := LoadUint32(&x.i)
    510 		if k != x.i {
    511 			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
    512 		}
    513 		x.i += delta
    514 	}
    515 	if x.before != magic32 || x.after != magic32 {
    516 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
    517 	}
    518 }
    519 
    520 func TestLoadInt64(t *testing.T) {
    521 	if test64err != nil {
    522 		t.Skipf("Skipping 64-bit tests: %v", test64err)
    523 	}
    524 	var x struct {
    525 		before int64
    526 		i      int64
    527 		after  int64
    528 	}
    529 	x.before = magic64
    530 	x.after = magic64
    531 	for delta := int64(1); delta+delta > delta; delta += delta {
    532 		k := LoadInt64(&x.i)
    533 		if k != x.i {
    534 			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
    535 		}
    536 		x.i += delta
    537 	}
    538 	if x.before != magic64 || x.after != magic64 {
    539 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
    540 	}
    541 }
    542 
    543 func TestLoadUint64(t *testing.T) {
    544 	if test64err != nil {
    545 		t.Skipf("Skipping 64-bit tests: %v", test64err)
    546 	}
    547 	var x struct {
    548 		before uint64
    549 		i      uint64
    550 		after  uint64
    551 	}
    552 	x.before = magic64
    553 	x.after = magic64
    554 	for delta := uint64(1); delta+delta > delta; delta += delta {
    555 		k := LoadUint64(&x.i)
    556 		if k != x.i {
    557 			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
    558 		}
    559 		x.i += 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 TestLoadUintptr(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 	for delta := uintptr(1); delta+delta > delta; delta += delta {
    577 		k := LoadUintptr(&x.i)
    578 		if k != x.i {
    579 			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
    580 		}
    581 		x.i += delta
    582 	}
    583 	if x.before != magicptr || x.after != magicptr {
    584 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
    585 	}
    586 }
    587 
    588 func TestLoadPointer(t *testing.T) {
    589 	var x struct {
    590 		before uintptr
    591 		i      unsafe.Pointer
    592 		after  uintptr
    593 	}
    594 	var m uint64 = magic64
    595 	magicptr := uintptr(m)
    596 	x.before = magicptr
    597 	x.after = magicptr
    598 	for delta := uintptr(1 << 16); delta+delta > delta; delta += delta {
    599 		k := LoadPointer(&x.i)
    600 		if k != x.i {
    601 			t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
    602 		}
    603 		x.i = unsafe.Pointer(uintptr(x.i) + delta)
    604 	}
    605 	if x.before != magicptr || x.after != magicptr {
    606 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
    607 	}
    608 }
    609 
    610 func TestStoreInt32(t *testing.T) {
    611 	var x struct {
    612 		before int32
    613 		i      int32
    614 		after  int32
    615 	}
    616 	x.before = magic32
    617 	x.after = magic32
    618 	v := int32(0)
    619 	for delta := int32(1); delta+delta > delta; delta += delta {
    620 		StoreInt32(&x.i, v)
    621 		if x.i != v {
    622 			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
    623 		}
    624 		v += delta
    625 	}
    626 	if x.before != magic32 || x.after != magic32 {
    627 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
    628 	}
    629 }
    630 
    631 func TestStoreUint32(t *testing.T) {
    632 	var x struct {
    633 		before uint32
    634 		i      uint32
    635 		after  uint32
    636 	}
    637 	x.before = magic32
    638 	x.after = magic32
    639 	v := uint32(0)
    640 	for delta := uint32(1); delta+delta > delta; delta += delta {
    641 		StoreUint32(&x.i, v)
    642 		if x.i != v {
    643 			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
    644 		}
    645 		v += delta
    646 	}
    647 	if x.before != magic32 || x.after != magic32 {
    648 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
    649 	}
    650 }
    651 
    652 func TestStoreInt64(t *testing.T) {
    653 	if test64err != nil {
    654 		t.Skipf("Skipping 64-bit tests: %v", test64err)
    655 	}
    656 	var x struct {
    657 		before int64
    658 		i      int64
    659 		after  int64
    660 	}
    661 	x.before = magic64
    662 	x.after = magic64
    663 	v := int64(0)
    664 	for delta := int64(1); delta+delta > delta; delta += delta {
    665 		StoreInt64(&x.i, v)
    666 		if x.i != v {
    667 			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
    668 		}
    669 		v += delta
    670 	}
    671 	if x.before != magic64 || x.after != magic64 {
    672 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
    673 	}
    674 }
    675 
    676 func TestStoreUint64(t *testing.T) {
    677 	if test64err != nil {
    678 		t.Skipf("Skipping 64-bit tests: %v", test64err)
    679 	}
    680 	var x struct {
    681 		before uint64
    682 		i      uint64
    683 		after  uint64
    684 	}
    685 	x.before = magic64
    686 	x.after = magic64
    687 	v := uint64(0)
    688 	for delta := uint64(1); delta+delta > delta; delta += delta {
    689 		StoreUint64(&x.i, v)
    690 		if x.i != v {
    691 			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
    692 		}
    693 		v += delta
    694 	}
    695 	if x.before != magic64 || x.after != magic64 {
    696 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
    697 	}
    698 }
    699 
    700 func TestStoreUintptr(t *testing.T) {
    701 	var x struct {
    702 		before uintptr
    703 		i      uintptr
    704 		after  uintptr
    705 	}
    706 	var m uint64 = magic64
    707 	magicptr := uintptr(m)
    708 	x.before = magicptr
    709 	x.after = magicptr
    710 	v := uintptr(0)
    711 	for delta := uintptr(1); delta+delta > delta; delta += delta {
    712 		StoreUintptr(&x.i, v)
    713 		if x.i != v {
    714 			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
    715 		}
    716 		v += delta
    717 	}
    718 	if x.before != magicptr || x.after != magicptr {
    719 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
    720 	}
    721 }
    722 
    723 func TestStorePointer(t *testing.T) {
    724 	var x struct {
    725 		before uintptr
    726 		i      unsafe.Pointer
    727 		after  uintptr
    728 	}
    729 	var m uint64 = magic64
    730 	magicptr := uintptr(m)
    731 	x.before = magicptr
    732 	x.after = magicptr
    733 	v := unsafe.Pointer(uintptr(0))
    734 	for delta := uintptr(1 << 16); delta+delta > delta; delta += delta {
    735 		StorePointer(&x.i, unsafe.Pointer(v))
    736 		if x.i != v {
    737 			t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
    738 		}
    739 		v = unsafe.Pointer(uintptr(v) + delta)
    740 	}
    741 	if x.before != magicptr || x.after != magicptr {
    742 		t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
    743 	}
    744 }
    745 
    746 // Tests of correct behavior, with contention.
    747 // (Is the function atomic?)
    748 //
    749 // For each function, we write a "hammer" function that repeatedly
    750 // uses the atomic operation to add 1 to a value. After running
    751 // multiple hammers in parallel, check that we end with the correct
    752 // total.
    753 // Swap can't add 1, so it uses a different scheme.
    754 // The functions repeatedly generate a pseudo-random number such that
    755 // low bits are equal to high bits, swap, check that the old value
    756 // has low and high bits equal.
    757 
    758 var hammer32 = map[string]func(*uint32, int){
    759 	"SwapInt32":             hammerSwapInt32,
    760 	"SwapUint32":            hammerSwapUint32,
    761 	"SwapUintptr":           hammerSwapUintptr32,
    762 	"AddInt32":              hammerAddInt32,
    763 	"AddUint32":             hammerAddUint32,
    764 	"AddUintptr":            hammerAddUintptr32,
    765 	"CompareAndSwapInt32":   hammerCompareAndSwapInt32,
    766 	"CompareAndSwapUint32":  hammerCompareAndSwapUint32,
    767 	"CompareAndSwapUintptr": hammerCompareAndSwapUintptr32,
    768 }
    769 
    770 func init() {
    771 	var v uint64 = 1 << 50
    772 	if uintptr(v) != 0 {
    773 		// 64-bit system; clear uintptr tests
    774 		delete(hammer32, "SwapUintptr")
    775 		delete(hammer32, "AddUintptr")
    776 		delete(hammer32, "CompareAndSwapUintptr")
    777 	}
    778 }
    779 
    780 func hammerSwapInt32(uaddr *uint32, count int) {
    781 	addr := (*int32)(unsafe.Pointer(uaddr))
    782 	seed := int(uintptr(unsafe.Pointer(&count)))
    783 	for i := 0; i < count; i++ {
    784 		new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
    785 		old := uint32(SwapInt32(addr, int32(new)))
    786 		if old>>16 != old<<16>>16 {
    787 			panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old))
    788 		}
    789 	}
    790 }
    791 
    792 func hammerSwapUint32(addr *uint32, count int) {
    793 	seed := int(uintptr(unsafe.Pointer(&count)))
    794 	for i := 0; i < count; i++ {
    795 		new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
    796 		old := SwapUint32(addr, new)
    797 		if old>>16 != old<<16>>16 {
    798 			panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old))
    799 		}
    800 	}
    801 }
    802 
    803 func hammerSwapUintptr32(uaddr *uint32, count int) {
    804 	// only safe when uintptr is 32-bit.
    805 	// not called on 64-bit systems.
    806 	addr := (*uintptr)(unsafe.Pointer(uaddr))
    807 	seed := int(uintptr(unsafe.Pointer(&count)))
    808 	for i := 0; i < count; i++ {
    809 		new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16
    810 		old := SwapUintptr(addr, new)
    811 		if old>>16 != old<<16>>16 {
    812 			panic(fmt.Sprintf("SwapUintptr is not atomic: %#08x", old))
    813 		}
    814 	}
    815 }
    816 
    817 func hammerAddInt32(uaddr *uint32, count int) {
    818 	addr := (*int32)(unsafe.Pointer(uaddr))
    819 	for i := 0; i < count; i++ {
    820 		AddInt32(addr, 1)
    821 	}
    822 }
    823 
    824 func hammerAddUint32(addr *uint32, count int) {
    825 	for i := 0; i < count; i++ {
    826 		AddUint32(addr, 1)
    827 	}
    828 }
    829 
    830 func hammerAddUintptr32(uaddr *uint32, count int) {
    831 	// only safe when uintptr is 32-bit.
    832 	// not called on 64-bit systems.
    833 	addr := (*uintptr)(unsafe.Pointer(uaddr))
    834 	for i := 0; i < count; i++ {
    835 		AddUintptr(addr, 1)
    836 	}
    837 }
    838 
    839 func hammerCompareAndSwapInt32(uaddr *uint32, count int) {
    840 	addr := (*int32)(unsafe.Pointer(uaddr))
    841 	for i := 0; i < count; i++ {
    842 		for {
    843 			v := LoadInt32(addr)
    844 			if CompareAndSwapInt32(addr, v, v+1) {
    845 				break
    846 			}
    847 		}
    848 	}
    849 }
    850 
    851 func hammerCompareAndSwapUint32(addr *uint32, count int) {
    852 	for i := 0; i < count; i++ {
    853 		for {
    854 			v := LoadUint32(addr)
    855 			if CompareAndSwapUint32(addr, v, v+1) {
    856 				break
    857 			}
    858 		}
    859 	}
    860 }
    861 
    862 func hammerCompareAndSwapUintptr32(uaddr *uint32, count int) {
    863 	// only safe when uintptr is 32-bit.
    864 	// not called on 64-bit systems.
    865 	addr := (*uintptr)(unsafe.Pointer(uaddr))
    866 	for i := 0; i < count; i++ {
    867 		for {
    868 			v := LoadUintptr(addr)
    869 			if CompareAndSwapUintptr(addr, v, v+1) {
    870 				break
    871 			}
    872 		}
    873 	}
    874 }
    875 
    876 func TestHammer32(t *testing.T) {
    877 	const p = 4
    878 	n := 100000
    879 	if testing.Short() {
    880 		n = 1000
    881 	}
    882 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
    883 
    884 	for name, testf := range hammer32 {
    885 		c := make(chan int)
    886 		var val uint32
    887 		for i := 0; i < p; i++ {
    888 			go func() {
    889 				defer func() {
    890 					if err := recover(); err != nil {
    891 						t.Error(err.(string))
    892 					}
    893 					c <- 1
    894 				}()
    895 				testf(&val, n)
    896 			}()
    897 		}
    898 		for i := 0; i < p; i++ {
    899 			<-c
    900 		}
    901 		if !strings.HasPrefix(name, "Swap") && val != uint32(n)*p {
    902 			t.Fatalf("%s: val=%d want %d", name, val, n*p)
    903 		}
    904 	}
    905 }
    906 
    907 var hammer64 = map[string]func(*uint64, int){
    908 	"SwapInt64":             hammerSwapInt64,
    909 	"SwapUint64":            hammerSwapUint64,
    910 	"SwapUintptr":           hammerSwapUintptr64,
    911 	"AddInt64":              hammerAddInt64,
    912 	"AddUint64":             hammerAddUint64,
    913 	"AddUintptr":            hammerAddUintptr64,
    914 	"CompareAndSwapInt64":   hammerCompareAndSwapInt64,
    915 	"CompareAndSwapUint64":  hammerCompareAndSwapUint64,
    916 	"CompareAndSwapUintptr": hammerCompareAndSwapUintptr64,
    917 }
    918 
    919 func init() {
    920 	var v uint64 = 1 << 50
    921 	if uintptr(v) == 0 {
    922 		// 32-bit system; clear uintptr tests
    923 		delete(hammer64, "SwapUintptr")
    924 		delete(hammer64, "AddUintptr")
    925 		delete(hammer64, "CompareAndSwapUintptr")
    926 	}
    927 }
    928 
    929 func hammerSwapInt64(uaddr *uint64, count int) {
    930 	addr := (*int64)(unsafe.Pointer(uaddr))
    931 	seed := int(uintptr(unsafe.Pointer(&count)))
    932 	for i := 0; i < count; i++ {
    933 		new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
    934 		old := uint64(SwapInt64(addr, int64(new)))
    935 		if old>>32 != old<<32>>32 {
    936 			panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old))
    937 		}
    938 	}
    939 }
    940 
    941 func hammerSwapUint64(addr *uint64, count int) {
    942 	seed := int(uintptr(unsafe.Pointer(&count)))
    943 	for i := 0; i < count; i++ {
    944 		new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
    945 		old := SwapUint64(addr, new)
    946 		if old>>32 != old<<32>>32 {
    947 			panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old))
    948 		}
    949 	}
    950 }
    951 
    952 const arch32 = unsafe.Sizeof(uintptr(0)) == 4
    953 
    954 func hammerSwapUintptr64(uaddr *uint64, count int) {
    955 	// only safe when uintptr is 64-bit.
    956 	// not called on 32-bit systems.
    957 	if !arch32 {
    958 		addr := (*uintptr)(unsafe.Pointer(uaddr))
    959 		seed := int(uintptr(unsafe.Pointer(&count)))
    960 		for i := 0; i < count; i++ {
    961 			new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32
    962 			old := SwapUintptr(addr, new)
    963 			if old>>32 != old<<32>>32 {
    964 				panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old))
    965 			}
    966 		}
    967 	}
    968 }
    969 
    970 func hammerAddInt64(uaddr *uint64, count int) {
    971 	addr := (*int64)(unsafe.Pointer(uaddr))
    972 	for i := 0; i < count; i++ {
    973 		AddInt64(addr, 1)
    974 	}
    975 }
    976 
    977 func hammerAddUint64(addr *uint64, count int) {
    978 	for i := 0; i < count; i++ {
    979 		AddUint64(addr, 1)
    980 	}
    981 }
    982 
    983 func hammerAddUintptr64(uaddr *uint64, count int) {
    984 	// only safe when uintptr is 64-bit.
    985 	// not called on 32-bit systems.
    986 	addr := (*uintptr)(unsafe.Pointer(uaddr))
    987 	for i := 0; i < count; i++ {
    988 		AddUintptr(addr, 1)
    989 	}
    990 }
    991 
    992 func hammerCompareAndSwapInt64(uaddr *uint64, count int) {
    993 	addr := (*int64)(unsafe.Pointer(uaddr))
    994 	for i := 0; i < count; i++ {
    995 		for {
    996 			v := LoadInt64(addr)
    997 			if CompareAndSwapInt64(addr, v, v+1) {
    998 				break
    999 			}
   1000 		}
   1001 	}
   1002 }
   1003 
   1004 func hammerCompareAndSwapUint64(addr *uint64, count int) {
   1005 	for i := 0; i < count; i++ {
   1006 		for {
   1007 			v := LoadUint64(addr)
   1008 			if CompareAndSwapUint64(addr, v, v+1) {
   1009 				break
   1010 			}
   1011 		}
   1012 	}
   1013 }
   1014 
   1015 func hammerCompareAndSwapUintptr64(uaddr *uint64, count int) {
   1016 	// only safe when uintptr is 64-bit.
   1017 	// not called on 32-bit systems.
   1018 	addr := (*uintptr)(unsafe.Pointer(uaddr))
   1019 	for i := 0; i < count; i++ {
   1020 		for {
   1021 			v := LoadUintptr(addr)
   1022 			if CompareAndSwapUintptr(addr, v, v+1) {
   1023 				break
   1024 			}
   1025 		}
   1026 	}
   1027 }
   1028 
   1029 func TestHammer64(t *testing.T) {
   1030 	if test64err != nil {
   1031 		t.Skipf("Skipping 64-bit tests: %v", test64err)
   1032 	}
   1033 	const p = 4
   1034 	n := 100000
   1035 	if testing.Short() {
   1036 		n = 1000
   1037 	}
   1038 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
   1039 
   1040 	for name, testf := range hammer64 {
   1041 		c := make(chan int)
   1042 		var val uint64
   1043 		for i := 0; i < p; i++ {
   1044 			go func() {
   1045 				defer func() {
   1046 					if err := recover(); err != nil {
   1047 						t.Error(err.(string))
   1048 					}
   1049 					c <- 1
   1050 				}()
   1051 				testf(&val, n)
   1052 			}()
   1053 		}
   1054 		for i := 0; i < p; i++ {
   1055 			<-c
   1056 		}
   1057 		if !strings.HasPrefix(name, "Swap") && val != uint64(n)*p {
   1058 			t.Fatalf("%s: val=%d want %d", name, val, n*p)
   1059 		}
   1060 	}
   1061 }
   1062 
   1063 func hammerStoreLoadInt32(t *testing.T, paddr unsafe.Pointer) {
   1064 	addr := (*int32)(paddr)
   1065 	v := LoadInt32(addr)
   1066 	vlo := v & ((1 << 16) - 1)
   1067 	vhi := v >> 16
   1068 	if vlo != vhi {
   1069 		t.Fatalf("Int32: %#x != %#x", vlo, vhi)
   1070 	}
   1071 	new := v + 1 + 1<<16
   1072 	if vlo == 1e4 {
   1073 		new = 0
   1074 	}
   1075 	StoreInt32(addr, new)
   1076 }
   1077 
   1078 func hammerStoreLoadUint32(t *testing.T, paddr unsafe.Pointer) {
   1079 	addr := (*uint32)(paddr)
   1080 	v := LoadUint32(addr)
   1081 	vlo := v & ((1 << 16) - 1)
   1082 	vhi := v >> 16
   1083 	if vlo != vhi {
   1084 		t.Fatalf("Uint32: %#x != %#x", vlo, vhi)
   1085 	}
   1086 	new := v + 1 + 1<<16
   1087 	if vlo == 1e4 {
   1088 		new = 0
   1089 	}
   1090 	StoreUint32(addr, new)
   1091 }
   1092 
   1093 func hammerStoreLoadInt64(t *testing.T, paddr unsafe.Pointer) {
   1094 	addr := (*int64)(paddr)
   1095 	v := LoadInt64(addr)
   1096 	vlo := v & ((1 << 32) - 1)
   1097 	vhi := v >> 32
   1098 	if vlo != vhi {
   1099 		t.Fatalf("Int64: %#x != %#x", vlo, vhi)
   1100 	}
   1101 	new := v + 1 + 1<<32
   1102 	StoreInt64(addr, new)
   1103 }
   1104 
   1105 func hammerStoreLoadUint64(t *testing.T, paddr unsafe.Pointer) {
   1106 	addr := (*uint64)(paddr)
   1107 	v := LoadUint64(addr)
   1108 	vlo := v & ((1 << 32) - 1)
   1109 	vhi := v >> 32
   1110 	if vlo != vhi {
   1111 		t.Fatalf("Uint64: %#x != %#x", vlo, vhi)
   1112 	}
   1113 	new := v + 1 + 1<<32
   1114 	StoreUint64(addr, new)
   1115 }
   1116 
   1117 func hammerStoreLoadUintptr(t *testing.T, paddr unsafe.Pointer) {
   1118 	addr := (*uintptr)(paddr)
   1119 	v := LoadUintptr(addr)
   1120 	new := v
   1121 	if arch32 {
   1122 		vlo := v & ((1 << 16) - 1)
   1123 		vhi := v >> 16
   1124 		if vlo != vhi {
   1125 			t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
   1126 		}
   1127 		new = v + 1 + 1<<16
   1128 		if vlo == 1e4 {
   1129 			new = 0
   1130 		}
   1131 	} else {
   1132 		vlo := v & ((1 << 32) - 1)
   1133 		vhi := v >> 32
   1134 		if vlo != vhi {
   1135 			t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
   1136 		}
   1137 		inc := uint64(1 + 1<<32)
   1138 		new = v + uintptr(inc)
   1139 	}
   1140 	StoreUintptr(addr, new)
   1141 }
   1142 
   1143 func hammerStoreLoadPointer(t *testing.T, paddr unsafe.Pointer) {
   1144 	addr := (*unsafe.Pointer)(paddr)
   1145 	v := uintptr(LoadPointer(addr))
   1146 	new := v
   1147 	if arch32 {
   1148 		vlo := v & ((1 << 16) - 1)
   1149 		vhi := v >> 16
   1150 		if vlo != vhi {
   1151 			t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
   1152 		}
   1153 		new = v + 1 + 1<<16
   1154 		if vlo == 1e4 {
   1155 			new = 0
   1156 		}
   1157 	} else {
   1158 		vlo := v & ((1 << 32) - 1)
   1159 		vhi := v >> 32
   1160 		if vlo != vhi {
   1161 			t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
   1162 		}
   1163 		inc := uint64(1 + 1<<32)
   1164 		new = v + uintptr(inc)
   1165 	}
   1166 	StorePointer(addr, unsafe.Pointer(new))
   1167 }
   1168 
   1169 func TestHammerStoreLoad(t *testing.T) {
   1170 	var tests []func(*testing.T, unsafe.Pointer)
   1171 	tests = append(tests, hammerStoreLoadInt32, hammerStoreLoadUint32,
   1172 		hammerStoreLoadUintptr, hammerStoreLoadPointer)
   1173 	if test64err == nil {
   1174 		tests = append(tests, hammerStoreLoadInt64, hammerStoreLoadUint64)
   1175 	}
   1176 	n := int(1e6)
   1177 	if testing.Short() {
   1178 		n = int(1e4)
   1179 	}
   1180 	const procs = 8
   1181 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(procs))
   1182 	for _, tt := range tests {
   1183 		c := make(chan int)
   1184 		var val uint64
   1185 		for p := 0; p < procs; p++ {
   1186 			go func() {
   1187 				for i := 0; i < n; i++ {
   1188 					tt(t, unsafe.Pointer(&val))
   1189 				}
   1190 				c <- 1
   1191 			}()
   1192 		}
   1193 		for p := 0; p < procs; p++ {
   1194 			<-c
   1195 		}
   1196 	}
   1197 }
   1198 
   1199 func TestStoreLoadSeqCst32(t *testing.T) {
   1200 	if runtime.NumCPU() == 1 {
   1201 		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
   1202 	}
   1203 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
   1204 	N := int32(1e3)
   1205 	if testing.Short() {
   1206 		N = int32(1e2)
   1207 	}
   1208 	c := make(chan bool, 2)
   1209 	X := [2]int32{}
   1210 	ack := [2][3]int32{{-1, -1, -1}, {-1, -1, -1}}
   1211 	for p := 0; p < 2; p++ {
   1212 		go func(me int) {
   1213 			he := 1 - me
   1214 			for i := int32(1); i < N; i++ {
   1215 				StoreInt32(&X[me], i)
   1216 				my := LoadInt32(&X[he])
   1217 				StoreInt32(&ack[me][i%3], my)
   1218 				for w := 1; LoadInt32(&ack[he][i%3]) == -1; w++ {
   1219 					if w%1000 == 0 {
   1220 						runtime.Gosched()
   1221 					}
   1222 				}
   1223 				his := LoadInt32(&ack[he][i%3])
   1224 				if (my != i && my != i-1) || (his != i && his != i-1) {
   1225 					t.Errorf("invalid values: %d/%d (%d)", my, his, i)
   1226 					break
   1227 				}
   1228 				if my != i && his != i {
   1229 					t.Errorf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
   1230 					break
   1231 				}
   1232 				StoreInt32(&ack[me][(i-1)%3], -1)
   1233 			}
   1234 			c <- true
   1235 		}(p)
   1236 	}
   1237 	<-c
   1238 	<-c
   1239 }
   1240 
   1241 func TestStoreLoadSeqCst64(t *testing.T) {
   1242 	if runtime.NumCPU() == 1 {
   1243 		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
   1244 	}
   1245 	if test64err != nil {
   1246 		t.Skipf("Skipping 64-bit tests: %v", test64err)
   1247 	}
   1248 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
   1249 	N := int64(1e3)
   1250 	if testing.Short() {
   1251 		N = int64(1e2)
   1252 	}
   1253 	c := make(chan bool, 2)
   1254 	X := [2]int64{}
   1255 	ack := [2][3]int64{{-1, -1, -1}, {-1, -1, -1}}
   1256 	for p := 0; p < 2; p++ {
   1257 		go func(me int) {
   1258 			he := 1 - me
   1259 			for i := int64(1); i < N; i++ {
   1260 				StoreInt64(&X[me], i)
   1261 				my := LoadInt64(&X[he])
   1262 				StoreInt64(&ack[me][i%3], my)
   1263 				for w := 1; LoadInt64(&ack[he][i%3]) == -1; w++ {
   1264 					if w%1000 == 0 {
   1265 						runtime.Gosched()
   1266 					}
   1267 				}
   1268 				his := LoadInt64(&ack[he][i%3])
   1269 				if (my != i && my != i-1) || (his != i && his != i-1) {
   1270 					t.Errorf("invalid values: %d/%d (%d)", my, his, i)
   1271 					break
   1272 				}
   1273 				if my != i && his != i {
   1274 					t.Errorf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
   1275 					break
   1276 				}
   1277 				StoreInt64(&ack[me][(i-1)%3], -1)
   1278 			}
   1279 			c <- true
   1280 		}(p)
   1281 	}
   1282 	<-c
   1283 	<-c
   1284 }
   1285 
   1286 func TestStoreLoadRelAcq32(t *testing.T) {
   1287 	if runtime.NumCPU() == 1 {
   1288 		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
   1289 	}
   1290 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
   1291 	N := int32(1e3)
   1292 	if testing.Short() {
   1293 		N = int32(1e2)
   1294 	}
   1295 	c := make(chan bool, 2)
   1296 	type Data struct {
   1297 		signal int32
   1298 		pad1   [128]int8
   1299 		data1  int32
   1300 		pad2   [128]int8
   1301 		data2  float32
   1302 	}
   1303 	var X Data
   1304 	for p := int32(0); p < 2; p++ {
   1305 		go func(p int32) {
   1306 			for i := int32(1); i < N; i++ {
   1307 				if (i+p)%2 == 0 {
   1308 					X.data1 = i
   1309 					X.data2 = float32(i)
   1310 					StoreInt32(&X.signal, i)
   1311 				} else {
   1312 					for w := 1; LoadInt32(&X.signal) != i; w++ {
   1313 						if w%1000 == 0 {
   1314 							runtime.Gosched()
   1315 						}
   1316 					}
   1317 					d1 := X.data1
   1318 					d2 := X.data2
   1319 					if d1 != i || d2 != float32(i) {
   1320 						t.Errorf("incorrect data: %d/%g (%d)", d1, d2, i)
   1321 						break
   1322 					}
   1323 				}
   1324 			}
   1325 			c <- true
   1326 		}(p)
   1327 	}
   1328 	<-c
   1329 	<-c
   1330 }
   1331 
   1332 func TestStoreLoadRelAcq64(t *testing.T) {
   1333 	if runtime.NumCPU() == 1 {
   1334 		t.Skipf("Skipping test on %v processor machine", runtime.NumCPU())
   1335 	}
   1336 	if test64err != nil {
   1337 		t.Skipf("Skipping 64-bit tests: %v", test64err)
   1338 	}
   1339 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
   1340 	N := int64(1e3)
   1341 	if testing.Short() {
   1342 		N = int64(1e2)
   1343 	}
   1344 	c := make(chan bool, 2)
   1345 	type Data struct {
   1346 		signal int64
   1347 		pad1   [128]int8
   1348 		data1  int64
   1349 		pad2   [128]int8
   1350 		data2  float64
   1351 	}
   1352 	var X Data
   1353 	for p := int64(0); p < 2; p++ {
   1354 		go func(p int64) {
   1355 			for i := int64(1); i < N; i++ {
   1356 				if (i+p)%2 == 0 {
   1357 					X.data1 = i
   1358 					X.data2 = float64(i)
   1359 					StoreInt64(&X.signal, i)
   1360 				} else {
   1361 					for w := 1; LoadInt64(&X.signal) != i; w++ {
   1362 						if w%1000 == 0 {
   1363 							runtime.Gosched()
   1364 						}
   1365 					}
   1366 					d1 := X.data1
   1367 					d2 := X.data2
   1368 					if d1 != i || d2 != float64(i) {
   1369 						t.Errorf("incorrect data: %d/%g (%d)", d1, d2, i)
   1370 						break
   1371 					}
   1372 				}
   1373 			}
   1374 			c <- true
   1375 		}(p)
   1376 	}
   1377 	<-c
   1378 	<-c
   1379 }
   1380 
   1381 func shouldPanic(t *testing.T, name string, f func()) {
   1382 	defer func() {
   1383 		if recover() == nil {
   1384 			t.Errorf("%s did not panic", name)
   1385 		}
   1386 	}()
   1387 	f()
   1388 }
   1389 
   1390 func TestUnaligned64(t *testing.T) {
   1391 	// Unaligned 64-bit atomics on 32-bit systems are
   1392 	// a continual source of pain. Test that on 32-bit systems they crash
   1393 	// instead of failing silently.
   1394 
   1395 	switch runtime.GOARCH {
   1396 	default:
   1397 		if !arch32 {
   1398 			t.Skip("test only runs on 32-bit systems")
   1399 		}
   1400 	case "amd64p32":
   1401 		// amd64p32 can handle unaligned atomics.
   1402 		t.Skipf("test not needed on %v", runtime.GOARCH)
   1403 	}
   1404 
   1405 	x := make([]uint32, 4)
   1406 	p := (*uint64)(unsafe.Pointer(&x[1])) // misaligned
   1407 
   1408 	shouldPanic(t, "LoadUint64", func() { LoadUint64(p) })
   1409 	shouldPanic(t, "StoreUint64", func() { StoreUint64(p, 1) })
   1410 	shouldPanic(t, "CompareAndSwapUint64", func() { CompareAndSwapUint64(p, 1, 2) })
   1411 	shouldPanic(t, "AddUint64", func() { AddUint64(p, 3) })
   1412 }
   1413 
   1414 func TestNilDeref(t *testing.T) {
   1415 	funcs := [...]func(){
   1416 		func() { CompareAndSwapInt32(nil, 0, 0) },
   1417 		func() { CompareAndSwapInt64(nil, 0, 0) },
   1418 		func() { CompareAndSwapUint32(nil, 0, 0) },
   1419 		func() { CompareAndSwapUint64(nil, 0, 0) },
   1420 		func() { CompareAndSwapUintptr(nil, 0, 0) },
   1421 		func() { CompareAndSwapPointer(nil, nil, nil) },
   1422 		func() { SwapInt32(nil, 0) },
   1423 		func() { SwapUint32(nil, 0) },
   1424 		func() { SwapInt64(nil, 0) },
   1425 		func() { SwapUint64(nil, 0) },
   1426 		func() { SwapUintptr(nil, 0) },
   1427 		func() { SwapPointer(nil, nil) },
   1428 		func() { AddInt32(nil, 0) },
   1429 		func() { AddUint32(nil, 0) },
   1430 		func() { AddInt64(nil, 0) },
   1431 		func() { AddUint64(nil, 0) },
   1432 		func() { AddUintptr(nil, 0) },
   1433 		func() { LoadInt32(nil) },
   1434 		func() { LoadInt64(nil) },
   1435 		func() { LoadUint32(nil) },
   1436 		func() { LoadUint64(nil) },
   1437 		func() { LoadUintptr(nil) },
   1438 		func() { LoadPointer(nil) },
   1439 		func() { StoreInt32(nil, 0) },
   1440 		func() { StoreInt64(nil, 0) },
   1441 		func() { StoreUint32(nil, 0) },
   1442 		func() { StoreUint64(nil, 0) },
   1443 		func() { StoreUintptr(nil, 0) },
   1444 		func() { StorePointer(nil, nil) },
   1445 	}
   1446 	for _, f := range funcs {
   1447 		func() {
   1448 			defer func() {
   1449 				runtime.GC()
   1450 				recover()
   1451 			}()
   1452 			f()
   1453 		}()
   1454 	}
   1455 }
   1456