github.com/mattn/go@v0.0.0-20171011075504-07f7db3ea99f/src/sync/atomic/atomic_test.go (about) 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 }