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, "SwapPointer") 776 delete(hammer32, "AddUintptr") 777 delete(hammer32, "CompareAndSwapUintptr") 778 delete(hammer32, "CompareAndSwapPointer") 779 } 780 } 781 782 func hammerSwapInt32(uaddr *uint32, count int) { 783 addr := (*int32)(unsafe.Pointer(uaddr)) 784 seed := int(uintptr(unsafe.Pointer(&count))) 785 for i := 0; i < count; i++ { 786 new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16 787 old := uint32(SwapInt32(addr, int32(new))) 788 if old>>16 != old<<16>>16 { 789 panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old)) 790 } 791 } 792 } 793 794 func hammerSwapUint32(addr *uint32, count int) { 795 seed := int(uintptr(unsafe.Pointer(&count))) 796 for i := 0; i < count; i++ { 797 new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16 798 old := SwapUint32(addr, new) 799 if old>>16 != old<<16>>16 { 800 panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old)) 801 } 802 } 803 } 804 805 func hammerSwapUintptr32(uaddr *uint32, count int) { 806 // only safe when uintptr is 32-bit. 807 // not called on 64-bit systems. 808 addr := (*uintptr)(unsafe.Pointer(uaddr)) 809 seed := int(uintptr(unsafe.Pointer(&count))) 810 for i := 0; i < count; i++ { 811 new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16 812 old := SwapUintptr(addr, new) 813 if old>>16 != old<<16>>16 { 814 panic(fmt.Sprintf("SwapUintptr is not atomic: %#08x", old)) 815 } 816 } 817 } 818 819 func hammerAddInt32(uaddr *uint32, count int) { 820 addr := (*int32)(unsafe.Pointer(uaddr)) 821 for i := 0; i < count; i++ { 822 AddInt32(addr, 1) 823 } 824 } 825 826 func hammerAddUint32(addr *uint32, count int) { 827 for i := 0; i < count; i++ { 828 AddUint32(addr, 1) 829 } 830 } 831 832 func hammerAddUintptr32(uaddr *uint32, count int) { 833 // only safe when uintptr is 32-bit. 834 // not called on 64-bit systems. 835 addr := (*uintptr)(unsafe.Pointer(uaddr)) 836 for i := 0; i < count; i++ { 837 AddUintptr(addr, 1) 838 } 839 } 840 841 func hammerCompareAndSwapInt32(uaddr *uint32, count int) { 842 addr := (*int32)(unsafe.Pointer(uaddr)) 843 for i := 0; i < count; i++ { 844 for { 845 v := LoadInt32(addr) 846 if CompareAndSwapInt32(addr, v, v+1) { 847 break 848 } 849 } 850 } 851 } 852 853 func hammerCompareAndSwapUint32(addr *uint32, count int) { 854 for i := 0; i < count; i++ { 855 for { 856 v := LoadUint32(addr) 857 if CompareAndSwapUint32(addr, v, v+1) { 858 break 859 } 860 } 861 } 862 } 863 864 func hammerCompareAndSwapUintptr32(uaddr *uint32, count int) { 865 // only safe when uintptr is 32-bit. 866 // not called on 64-bit systems. 867 addr := (*uintptr)(unsafe.Pointer(uaddr)) 868 for i := 0; i < count; i++ { 869 for { 870 v := LoadUintptr(addr) 871 if CompareAndSwapUintptr(addr, v, v+1) { 872 break 873 } 874 } 875 } 876 } 877 878 func TestHammer32(t *testing.T) { 879 const p = 4 880 n := 100000 881 if testing.Short() { 882 n = 1000 883 } 884 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p)) 885 886 for name, testf := range hammer32 { 887 c := make(chan int) 888 var val uint32 889 for i := 0; i < p; i++ { 890 go func() { 891 defer func() { 892 if err := recover(); err != nil { 893 t.Error(err.(string)) 894 } 895 c <- 1 896 }() 897 testf(&val, n) 898 }() 899 } 900 for i := 0; i < p; i++ { 901 <-c 902 } 903 if !strings.HasPrefix(name, "Swap") && val != uint32(n)*p { 904 t.Fatalf("%s: val=%d want %d", name, val, n*p) 905 } 906 } 907 } 908 909 var hammer64 = map[string]func(*uint64, int){ 910 "SwapInt64": hammerSwapInt64, 911 "SwapUint64": hammerSwapUint64, 912 "SwapUintptr": hammerSwapUintptr64, 913 "AddInt64": hammerAddInt64, 914 "AddUint64": hammerAddUint64, 915 "AddUintptr": hammerAddUintptr64, 916 "CompareAndSwapInt64": hammerCompareAndSwapInt64, 917 "CompareAndSwapUint64": hammerCompareAndSwapUint64, 918 "CompareAndSwapUintptr": hammerCompareAndSwapUintptr64, 919 } 920 921 func init() { 922 var v uint64 = 1 << 50 923 if uintptr(v) == 0 { 924 // 32-bit system; clear uintptr tests 925 delete(hammer64, "SwapUintptr") 926 delete(hammer64, "SwapPointer") 927 delete(hammer64, "AddUintptr") 928 delete(hammer64, "CompareAndSwapUintptr") 929 delete(hammer64, "CompareAndSwapPointer") 930 } 931 } 932 933 func hammerSwapInt64(uaddr *uint64, count int) { 934 addr := (*int64)(unsafe.Pointer(uaddr)) 935 seed := int(uintptr(unsafe.Pointer(&count))) 936 for i := 0; i < count; i++ { 937 new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32 938 old := uint64(SwapInt64(addr, int64(new))) 939 if old>>32 != old<<32>>32 { 940 panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old)) 941 } 942 } 943 } 944 945 func hammerSwapUint64(addr *uint64, count int) { 946 seed := int(uintptr(unsafe.Pointer(&count))) 947 for i := 0; i < count; i++ { 948 new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32 949 old := SwapUint64(addr, new) 950 if old>>32 != old<<32>>32 { 951 panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old)) 952 } 953 } 954 } 955 956 func hammerSwapUintptr64(uaddr *uint64, count int) { 957 // only safe when uintptr is 64-bit. 958 // not called on 32-bit systems. 959 addr := (*uintptr)(unsafe.Pointer(uaddr)) 960 seed := int(uintptr(unsafe.Pointer(&count))) 961 for i := 0; i < count; i++ { 962 new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32 963 old := SwapUintptr(addr, new) 964 if old>>32 != old<<32>>32 { 965 panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old)) 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 var test64 uint64 = 1 << 50 1120 arch32 := uintptr(test64) == 0 1121 v := LoadUintptr(addr) 1122 new := v 1123 if arch32 { 1124 vlo := v & ((1 << 16) - 1) 1125 vhi := v >> 16 1126 if vlo != vhi { 1127 t.Fatalf("Uintptr: %#x != %#x", vlo, vhi) 1128 } 1129 new = v + 1 + 1<<16 1130 if vlo == 1e4 { 1131 new = 0 1132 } 1133 } else { 1134 vlo := v & ((1 << 32) - 1) 1135 vhi := v >> 32 1136 if vlo != vhi { 1137 t.Fatalf("Uintptr: %#x != %#x", vlo, vhi) 1138 } 1139 inc := uint64(1 + 1<<32) 1140 new = v + uintptr(inc) 1141 } 1142 StoreUintptr(addr, new) 1143 } 1144 1145 func hammerStoreLoadPointer(t *testing.T, paddr unsafe.Pointer) { 1146 addr := (*unsafe.Pointer)(paddr) 1147 var test64 uint64 = 1 << 50 1148 arch32 := uintptr(test64) == 0 1149 v := uintptr(LoadPointer(addr)) 1150 new := v 1151 if arch32 { 1152 vlo := v & ((1 << 16) - 1) 1153 vhi := v >> 16 1154 if vlo != vhi { 1155 t.Fatalf("Pointer: %#x != %#x", vlo, vhi) 1156 } 1157 new = v + 1 + 1<<16 1158 if vlo == 1e4 { 1159 new = 0 1160 } 1161 } else { 1162 vlo := v & ((1 << 32) - 1) 1163 vhi := v >> 32 1164 if vlo != vhi { 1165 t.Fatalf("Pointer: %#x != %#x", vlo, vhi) 1166 } 1167 inc := uint64(1 + 1<<32) 1168 new = v + uintptr(inc) 1169 } 1170 StorePointer(addr, unsafe.Pointer(new)) 1171 } 1172 1173 func TestHammerStoreLoad(t *testing.T) { 1174 var tests []func(*testing.T, unsafe.Pointer) 1175 tests = append(tests, hammerStoreLoadInt32, hammerStoreLoadUint32, 1176 hammerStoreLoadUintptr, hammerStoreLoadPointer) 1177 if test64err == nil { 1178 tests = append(tests, hammerStoreLoadInt64, hammerStoreLoadUint64) 1179 } 1180 n := int(1e6) 1181 if testing.Short() { 1182 n = int(1e4) 1183 } 1184 const procs = 8 1185 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(procs)) 1186 for _, tt := range tests { 1187 c := make(chan int) 1188 var val uint64 1189 for p := 0; p < procs; p++ { 1190 go func() { 1191 for i := 0; i < n; i++ { 1192 tt(t, unsafe.Pointer(&val)) 1193 } 1194 c <- 1 1195 }() 1196 } 1197 for p := 0; p < procs; p++ { 1198 <-c 1199 } 1200 } 1201 } 1202 1203 func TestStoreLoadSeqCst32(t *testing.T) { 1204 if runtime.NumCPU() == 1 { 1205 t.Skipf("Skipping test on %v processor machine", runtime.NumCPU()) 1206 } 1207 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) 1208 N := int32(1e3) 1209 if testing.Short() { 1210 N = int32(1e2) 1211 } 1212 c := make(chan bool, 2) 1213 X := [2]int32{} 1214 ack := [2][3]int32{{-1, -1, -1}, {-1, -1, -1}} 1215 for p := 0; p < 2; p++ { 1216 go func(me int) { 1217 he := 1 - me 1218 for i := int32(1); i < N; i++ { 1219 StoreInt32(&X[me], i) 1220 my := LoadInt32(&X[he]) 1221 StoreInt32(&ack[me][i%3], my) 1222 for w := 1; LoadInt32(&ack[he][i%3]) == -1; w++ { 1223 if w%1000 == 0 { 1224 runtime.Gosched() 1225 } 1226 } 1227 his := LoadInt32(&ack[he][i%3]) 1228 if (my != i && my != i-1) || (his != i && his != i-1) { 1229 t.Fatalf("invalid values: %d/%d (%d)", my, his, i) 1230 } 1231 if my != i && his != i { 1232 t.Fatalf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i) 1233 } 1234 StoreInt32(&ack[me][(i-1)%3], -1) 1235 } 1236 c <- true 1237 }(p) 1238 } 1239 <-c 1240 <-c 1241 } 1242 1243 func TestStoreLoadSeqCst64(t *testing.T) { 1244 if runtime.NumCPU() == 1 { 1245 t.Skipf("Skipping test on %v processor machine", runtime.NumCPU()) 1246 } 1247 if test64err != nil { 1248 t.Skipf("Skipping 64-bit tests: %v", test64err) 1249 } 1250 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) 1251 N := int64(1e3) 1252 if testing.Short() { 1253 N = int64(1e2) 1254 } 1255 c := make(chan bool, 2) 1256 X := [2]int64{} 1257 ack := [2][3]int64{{-1, -1, -1}, {-1, -1, -1}} 1258 for p := 0; p < 2; p++ { 1259 go func(me int) { 1260 he := 1 - me 1261 for i := int64(1); i < N; i++ { 1262 StoreInt64(&X[me], i) 1263 my := LoadInt64(&X[he]) 1264 StoreInt64(&ack[me][i%3], my) 1265 for w := 1; LoadInt64(&ack[he][i%3]) == -1; w++ { 1266 if w%1000 == 0 { 1267 runtime.Gosched() 1268 } 1269 } 1270 his := LoadInt64(&ack[he][i%3]) 1271 if (my != i && my != i-1) || (his != i && his != i-1) { 1272 t.Fatalf("invalid values: %d/%d (%d)", my, his, i) 1273 } 1274 if my != i && his != i { 1275 t.Fatalf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i) 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.Fatalf("incorrect data: %d/%g (%d)", d1, d2, i) 1321 } 1322 } 1323 } 1324 c <- true 1325 }(p) 1326 } 1327 <-c 1328 <-c 1329 } 1330 1331 func TestStoreLoadRelAcq64(t *testing.T) { 1332 if runtime.NumCPU() == 1 { 1333 t.Skipf("Skipping test on %v processor machine", runtime.NumCPU()) 1334 } 1335 if test64err != nil { 1336 t.Skipf("Skipping 64-bit tests: %v", test64err) 1337 } 1338 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) 1339 N := int64(1e3) 1340 if testing.Short() { 1341 N = int64(1e2) 1342 } 1343 c := make(chan bool, 2) 1344 type Data struct { 1345 signal int64 1346 pad1 [128]int8 1347 data1 int64 1348 pad2 [128]int8 1349 data2 float64 1350 } 1351 var X Data 1352 for p := int64(0); p < 2; p++ { 1353 go func(p int64) { 1354 for i := int64(1); i < N; i++ { 1355 if (i+p)%2 == 0 { 1356 X.data1 = i 1357 X.data2 = float64(i) 1358 StoreInt64(&X.signal, i) 1359 } else { 1360 for w := 1; LoadInt64(&X.signal) != i; w++ { 1361 if w%1000 == 0 { 1362 runtime.Gosched() 1363 } 1364 } 1365 d1 := X.data1 1366 d2 := X.data2 1367 if d1 != i || d2 != float64(i) { 1368 t.Fatalf("incorrect data: %d/%g (%d)", d1, d2, i) 1369 } 1370 } 1371 } 1372 c <- true 1373 }(p) 1374 } 1375 <-c 1376 <-c 1377 } 1378 1379 func shouldPanic(t *testing.T, name string, f func()) { 1380 defer func() { 1381 if recover() == nil { 1382 t.Errorf("%s did not panic", name) 1383 } 1384 }() 1385 f() 1386 } 1387 1388 func TestUnaligned64(t *testing.T) { 1389 // Unaligned 64-bit atomics on 32-bit systems are 1390 // a continual source of pain. Test that on 32-bit systems they crash 1391 // instead of failing silently. 1392 if unsafe.Sizeof(int(0)) != 4 { 1393 t.Skip("test only runs on 32-bit systems") 1394 } 1395 1396 x := make([]uint32, 4) 1397 p := (*uint64)(unsafe.Pointer(&x[1])) // misaligned 1398 1399 shouldPanic(t, "LoadUint64", func() { LoadUint64(p) }) 1400 shouldPanic(t, "StoreUint64", func() { StoreUint64(p, 1) }) 1401 shouldPanic(t, "CompareAndSwapUint64", func() { CompareAndSwapUint64(p, 1, 2) }) 1402 shouldPanic(t, "AddUint64", func() { AddUint64(p, 3) }) 1403 } 1404 1405 func TestNilDeref(t *testing.T) { 1406 funcs := [...]func(){ 1407 func() { CompareAndSwapInt32(nil, 0, 0) }, 1408 func() { CompareAndSwapInt64(nil, 0, 0) }, 1409 func() { CompareAndSwapUint32(nil, 0, 0) }, 1410 func() { CompareAndSwapUint64(nil, 0, 0) }, 1411 func() { CompareAndSwapUintptr(nil, 0, 0) }, 1412 func() { CompareAndSwapPointer(nil, nil, nil) }, 1413 func() { SwapInt32(nil, 0) }, 1414 func() { SwapUint32(nil, 0) }, 1415 func() { SwapInt64(nil, 0) }, 1416 func() { SwapUint64(nil, 0) }, 1417 func() { SwapUintptr(nil, 0) }, 1418 func() { SwapPointer(nil, nil) }, 1419 func() { AddInt32(nil, 0) }, 1420 func() { AddUint32(nil, 0) }, 1421 func() { AddInt64(nil, 0) }, 1422 func() { AddUint64(nil, 0) }, 1423 func() { AddUintptr(nil, 0) }, 1424 func() { LoadInt32(nil) }, 1425 func() { LoadInt64(nil) }, 1426 func() { LoadUint32(nil) }, 1427 func() { LoadUint64(nil) }, 1428 func() { LoadUintptr(nil) }, 1429 func() { LoadPointer(nil) }, 1430 func() { StoreInt32(nil, 0) }, 1431 func() { StoreInt64(nil, 0) }, 1432 func() { StoreUint32(nil, 0) }, 1433 func() { StoreUint64(nil, 0) }, 1434 func() { StoreUintptr(nil, 0) }, 1435 func() { StorePointer(nil, nil) }, 1436 } 1437 for _, f := range funcs { 1438 func() { 1439 defer func() { 1440 runtime.GC() 1441 recover() 1442 }() 1443 f() 1444 }() 1445 } 1446 } 1447