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 5package atomic_test 6 7import ( 8 "fmt" 9 "reflect" 10 "runtime" 11 "runtime/debug" 12 "strings" 13 . "sync/atomic" 14 "testing" 15 "unsafe" 16) 17 18// Tests of correct behavior, without contention. 19// (Does the function work as advertised?) 20// 21// Test that the Add functions add correctly. 22// Test that the CompareAndSwap functions actually 23// do the comparison and the swap correctly. 24// 25// The loop over power-of-two values is meant to 26// ensure that the operations apply to the full word size. 27// The struct fields x.before and x.after check that the 28// operations do not extend past the full word size. 29 30const ( 31 magic32 = 0xdedbeef 32 magic64 = 0xdeddeadbeefbeef 33) 34 35func TestSwapInt32(t *testing.T) { 36 var x struct { 37 before int32 38 i int32 39 after int32 40 } 41 x.before = magic32 42 x.after = magic32 43 var j int32 44 for delta := int32(1); delta+delta > delta; delta += delta { 45 k := SwapInt32(&x.i, delta) 46 if x.i != delta || k != j { 47 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) 48 } 49 j = delta 50 } 51 if x.before != magic32 || x.after != magic32 { 52 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 53 } 54} 55 56func TestSwapInt32Method(t *testing.T) { 57 var x struct { 58 before int32 59 i Int32 60 after int32 61 } 62 x.before = magic32 63 x.after = magic32 64 var j int32 65 for delta := int32(1); delta+delta > delta; delta += delta { 66 k := x.i.Swap(delta) 67 if x.i.Load() != delta || k != j { 68 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) 69 } 70 j = delta 71 } 72 if x.before != magic32 || x.after != magic32 { 73 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 74 } 75} 76 77func TestSwapUint32(t *testing.T) { 78 var x struct { 79 before uint32 80 i uint32 81 after uint32 82 } 83 x.before = magic32 84 x.after = magic32 85 var j uint32 86 for delta := uint32(1); delta+delta > delta; delta += delta { 87 k := SwapUint32(&x.i, delta) 88 if x.i != delta || k != j { 89 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) 90 } 91 j = delta 92 } 93 if x.before != magic32 || x.after != magic32 { 94 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 95 } 96} 97 98func TestSwapUint32Method(t *testing.T) { 99 var x struct { 100 before uint32 101 i Uint32 102 after uint32 103 } 104 x.before = magic32 105 x.after = magic32 106 var j uint32 107 for delta := uint32(1); delta+delta > delta; delta += delta { 108 k := x.i.Swap(delta) 109 if x.i.Load() != delta || k != j { 110 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) 111 } 112 j = delta 113 } 114 if x.before != magic32 || x.after != magic32 { 115 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 116 } 117} 118 119func TestSwapInt64(t *testing.T) { 120 var x struct { 121 before int64 122 i int64 123 after int64 124 } 125 magic64 := int64(magic64) 126 x.before = magic64 127 x.after = magic64 128 var j int64 129 for delta := int64(1); delta+delta > delta; delta += delta { 130 k := SwapInt64(&x.i, delta) 131 if x.i != delta || k != j { 132 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) 133 } 134 j = delta 135 } 136 if x.before != magic64 || x.after != magic64 { 137 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 138 } 139} 140 141func TestSwapInt64Method(t *testing.T) { 142 var x struct { 143 before int64 144 i Int64 145 after int64 146 } 147 magic64 := int64(magic64) 148 x.before = magic64 149 x.after = magic64 150 var j int64 151 for delta := int64(1); delta+delta > delta; delta += delta { 152 k := x.i.Swap(delta) 153 if x.i.Load() != delta || k != j { 154 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) 155 } 156 j = delta 157 } 158 if x.before != magic64 || x.after != magic64 { 159 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 160 } 161} 162 163func TestSwapUint64(t *testing.T) { 164 var x struct { 165 before uint64 166 i uint64 167 after uint64 168 } 169 magic64 := uint64(magic64) 170 x.before = magic64 171 x.after = magic64 172 var j uint64 173 for delta := uint64(1); delta+delta > delta; delta += delta { 174 k := SwapUint64(&x.i, delta) 175 if x.i != delta || k != j { 176 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) 177 } 178 j = delta 179 } 180 if x.before != magic64 || x.after != magic64 { 181 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 182 } 183} 184 185func TestSwapUint64Method(t *testing.T) { 186 var x struct { 187 before uint64 188 i Uint64 189 after uint64 190 } 191 magic64 := uint64(magic64) 192 x.before = magic64 193 x.after = magic64 194 var j uint64 195 for delta := uint64(1); delta+delta > delta; delta += delta { 196 k := x.i.Swap(delta) 197 if x.i.Load() != delta || k != j { 198 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) 199 } 200 j = delta 201 } 202 if x.before != magic64 || x.after != magic64 { 203 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 204 } 205} 206 207func TestSwapUintptr(t *testing.T) { 208 var x struct { 209 before uintptr 210 i uintptr 211 after uintptr 212 } 213 var m uint64 = magic64 214 magicptr := uintptr(m) 215 x.before = magicptr 216 x.after = magicptr 217 var j uintptr 218 for delta := uintptr(1); delta+delta > delta; delta += delta { 219 k := SwapUintptr(&x.i, delta) 220 if x.i != delta || k != j { 221 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) 222 } 223 j = delta 224 } 225 if x.before != magicptr || x.after != magicptr { 226 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 227 } 228} 229 230func TestSwapUintptrMethod(t *testing.T) { 231 var x struct { 232 before uintptr 233 i Uintptr 234 after uintptr 235 } 236 var m uint64 = magic64 237 magicptr := uintptr(m) 238 x.before = magicptr 239 x.after = magicptr 240 var j uintptr 241 for delta := uintptr(1); delta+delta > delta; delta += delta { 242 k := x.i.Swap(delta) 243 if x.i.Load() != delta || k != j { 244 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) 245 } 246 j = delta 247 } 248 if x.before != magicptr || x.after != magicptr { 249 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 250 } 251} 252 253var global [1024]byte 254 255func testPointers() []unsafe.Pointer { 256 var pointers []unsafe.Pointer 257 // globals 258 for i := 0; i < 10; i++ { 259 pointers = append(pointers, unsafe.Pointer(&global[1<<i-1])) 260 } 261 // heap 262 pointers = append(pointers, unsafe.Pointer(new(byte))) 263 // nil 264 pointers = append(pointers, nil) 265 return pointers 266} 267 268func TestSwapPointer(t *testing.T) { 269 var x struct { 270 before uintptr 271 i unsafe.Pointer 272 after uintptr 273 } 274 var m uint64 = magic64 275 magicptr := uintptr(m) 276 x.before = magicptr 277 x.after = magicptr 278 var j unsafe.Pointer 279 280 for _, p := range testPointers() { 281 k := SwapPointer(&x.i, p) 282 if x.i != p || k != j { 283 t.Fatalf("p=%p i=%p j=%p k=%p", p, x.i, j, k) 284 } 285 j = p 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 292func TestSwapPointerMethod(t *testing.T) { 293 var x struct { 294 before uintptr 295 i Pointer[byte] 296 after uintptr 297 } 298 var m uint64 = magic64 299 magicptr := uintptr(m) 300 x.before = magicptr 301 x.after = magicptr 302 var j *byte 303 for _, p := range testPointers() { 304 p := (*byte)(p) 305 k := x.i.Swap(p) 306 if x.i.Load() != p || k != j { 307 t.Fatalf("p=%p i=%p j=%p k=%p", p, x.i.Load(), j, k) 308 } 309 j = p 310 } 311 if x.before != magicptr || x.after != magicptr { 312 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 313 } 314} 315 316func TestAddInt32(t *testing.T) { 317 var x struct { 318 before int32 319 i int32 320 after int32 321 } 322 x.before = magic32 323 x.after = magic32 324 var j int32 325 for delta := int32(1); delta+delta > delta; delta += delta { 326 k := AddInt32(&x.i, delta) 327 j += delta 328 if x.i != j || k != j { 329 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) 330 } 331 } 332 if x.before != magic32 || x.after != magic32 { 333 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 334 } 335} 336 337func TestAddInt32Method(t *testing.T) { 338 var x struct { 339 before int32 340 i Int32 341 after int32 342 } 343 x.before = magic32 344 x.after = magic32 345 var j int32 346 for delta := int32(1); delta+delta > delta; delta += delta { 347 k := x.i.Add(delta) 348 j += delta 349 if x.i.Load() != j || k != j { 350 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) 351 } 352 } 353 if x.before != magic32 || x.after != magic32 { 354 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 355 } 356} 357 358func TestAddUint32(t *testing.T) { 359 var x struct { 360 before uint32 361 i uint32 362 after uint32 363 } 364 x.before = magic32 365 x.after = magic32 366 var j uint32 367 for delta := uint32(1); delta+delta > delta; delta += delta { 368 k := AddUint32(&x.i, delta) 369 j += delta 370 if x.i != j || k != j { 371 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) 372 } 373 } 374 if x.before != magic32 || x.after != magic32 { 375 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 376 } 377} 378 379func TestAddUint32Method(t *testing.T) { 380 var x struct { 381 before uint32 382 i Uint32 383 after uint32 384 } 385 x.before = magic32 386 x.after = magic32 387 var j uint32 388 for delta := uint32(1); delta+delta > delta; delta += delta { 389 k := x.i.Add(delta) 390 j += delta 391 if x.i.Load() != j || k != j { 392 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) 393 } 394 } 395 if x.before != magic32 || x.after != magic32 { 396 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 397 } 398} 399 400func TestAddInt64(t *testing.T) { 401 var x struct { 402 before int64 403 i int64 404 after int64 405 } 406 magic64 := int64(magic64) 407 x.before = magic64 408 x.after = magic64 409 var j int64 410 for delta := int64(1); delta+delta > delta; delta += delta { 411 k := AddInt64(&x.i, delta) 412 j += delta 413 if x.i != j || k != j { 414 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) 415 } 416 } 417 if x.before != magic64 || x.after != magic64 { 418 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 419 } 420} 421 422func TestAddInt64Method(t *testing.T) { 423 var x struct { 424 before int64 425 i Int64 426 after int64 427 } 428 magic64 := int64(magic64) 429 x.before = magic64 430 x.after = magic64 431 var j int64 432 for delta := int64(1); delta+delta > delta; delta += delta { 433 k := x.i.Add(delta) 434 j += delta 435 if x.i.Load() != j || k != j { 436 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) 437 } 438 } 439 if x.before != magic64 || x.after != magic64 { 440 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 441 } 442} 443 444func TestAddUint64(t *testing.T) { 445 var x struct { 446 before uint64 447 i uint64 448 after uint64 449 } 450 magic64 := uint64(magic64) 451 x.before = magic64 452 x.after = magic64 453 var j uint64 454 for delta := uint64(1); delta+delta > delta; delta += delta { 455 k := AddUint64(&x.i, delta) 456 j += delta 457 if x.i != j || k != j { 458 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) 459 } 460 } 461 if x.before != magic64 || x.after != magic64 { 462 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 463 } 464} 465 466func TestAddUint64Method(t *testing.T) { 467 var x struct { 468 before uint64 469 i Uint64 470 after uint64 471 } 472 magic64 := uint64(magic64) 473 x.before = magic64 474 x.after = magic64 475 var j uint64 476 for delta := uint64(1); delta+delta > delta; delta += delta { 477 k := x.i.Add(delta) 478 j += delta 479 if x.i.Load() != j || k != j { 480 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) 481 } 482 } 483 if x.before != magic64 || x.after != magic64 { 484 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 485 } 486} 487 488func TestAddUintptr(t *testing.T) { 489 var x struct { 490 before uintptr 491 i uintptr 492 after uintptr 493 } 494 var m uint64 = magic64 495 magicptr := uintptr(m) 496 x.before = magicptr 497 x.after = magicptr 498 var j uintptr 499 for delta := uintptr(1); delta+delta > delta; delta += delta { 500 k := AddUintptr(&x.i, delta) 501 j += delta 502 if x.i != j || k != j { 503 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) 504 } 505 } 506 if x.before != magicptr || x.after != magicptr { 507 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 508 } 509} 510 511func TestAddUintptrMethod(t *testing.T) { 512 var x struct { 513 before uintptr 514 i Uintptr 515 after uintptr 516 } 517 var m uint64 = magic64 518 magicptr := uintptr(m) 519 x.before = magicptr 520 x.after = magicptr 521 var j uintptr 522 for delta := uintptr(1); delta+delta > delta; delta += delta { 523 k := x.i.Add(delta) 524 j += delta 525 if x.i.Load() != j || k != j { 526 t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i.Load(), j, k) 527 } 528 } 529 if x.before != magicptr || x.after != magicptr { 530 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 531 } 532} 533 534func TestAndInt32(t *testing.T) { 535 var x struct { 536 before int32 537 i int32 538 after int32 539 } 540 x.before = magic32 541 x.after = magic32 542 x.i = -1 543 j := x.i 544 for mask := int32(1); mask != 0; mask <<= 1 { 545 old := x.i 546 k := AndInt32(&x.i, ^mask) 547 j &= ^mask 548 if x.i != j || k != old { 549 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old) 550 } 551 } 552 if x.before != magic32 || x.after != magic32 { 553 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 554 } 555} 556 557func TestAndInt32Method(t *testing.T) { 558 var x struct { 559 before int32 560 i Int32 561 after int32 562 } 563 x.before = magic32 564 x.after = magic32 565 x.i.Store(-1) 566 j := x.i.Load() 567 for mask := int32(1); mask != 0; mask <<= 1 { 568 old := x.i.Load() 569 k := x.i.And(^mask) 570 j &= ^mask 571 if x.i.Load() != j || k != old { 572 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old) 573 } 574 } 575 if x.before != magic32 || x.after != magic32 { 576 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 577 } 578} 579 580func TestAndUint32(t *testing.T) { 581 var x struct { 582 before uint32 583 i uint32 584 after uint32 585 } 586 x.before = magic32 587 x.after = magic32 588 x.i = 0xffffffff 589 j := x.i 590 for mask := uint32(1); mask != 0; mask <<= 1 { 591 old := x.i 592 k := AndUint32(&x.i, ^mask) 593 j &= ^mask 594 if x.i != j || k != old { 595 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old) 596 } 597 } 598 if x.before != magic32 || x.after != magic32 { 599 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 600 } 601} 602 603func TestAndUint32Method(t *testing.T) { 604 var x struct { 605 before uint32 606 i Uint32 607 after uint32 608 } 609 x.before = magic32 610 x.after = magic32 611 x.i.Store(0xffffffff) 612 j := x.i.Load() 613 for mask := uint32(1); mask != 0; mask <<= 1 { 614 old := x.i.Load() 615 k := x.i.And(^mask) 616 j &= ^mask 617 if x.i.Load() != j || k != old { 618 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old) 619 } 620 } 621 if x.before != magic32 || x.after != magic32 { 622 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 623 } 624} 625 626func TestAndInt64(t *testing.T) { 627 var x struct { 628 before int64 629 i int64 630 after int64 631 } 632 magic64 := int64(magic64) 633 x.before = magic64 634 x.after = magic64 635 x.i = -1 636 j := x.i 637 for mask := int64(1); mask != 0; mask <<= 1 { 638 old := x.i 639 k := AndInt64(&x.i, ^mask) 640 j &= ^mask 641 if x.i != j || k != old { 642 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old) 643 } 644 } 645 if x.before != magic64 || x.after != magic64 { 646 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 647 } 648} 649 650func TestAndInt64Method(t *testing.T) { 651 var x struct { 652 before int64 653 i Int64 654 after int64 655 } 656 magic64 := int64(magic64) 657 x.before = magic64 658 x.after = magic64 659 x.i.Store(-1) 660 j := x.i.Load() 661 for mask := int64(1); mask != 0; mask <<= 1 { 662 old := x.i.Load() 663 k := x.i.And(^mask) 664 j &= ^mask 665 if x.i.Load() != j || k != old { 666 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old) 667 } 668 } 669 if x.before != magic64 || x.after != magic64 { 670 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 671 } 672} 673 674func TestAndUint64(t *testing.T) { 675 var x struct { 676 before uint64 677 i uint64 678 after uint64 679 } 680 magic64 := uint64(magic64) 681 x.before = magic64 682 x.after = magic64 683 x.i = 0xfffffffffffffff 684 j := x.i 685 for mask := uint64(1); mask != 0; mask <<= 1 { 686 old := x.i 687 k := AndUint64(&x.i, ^mask) 688 j &= ^mask 689 if x.i != j || k != old { 690 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old) 691 } 692 } 693 if x.before != magic64 || x.after != magic64 { 694 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 695 } 696} 697 698func TestAndUint64Method(t *testing.T) { 699 var x struct { 700 before uint64 701 i Uint64 702 after uint64 703 } 704 magic64 := uint64(magic64) 705 x.before = magic64 706 x.after = magic64 707 x.i.Store(0xfffffffffffffff) 708 j := x.i.Load() 709 for mask := uint64(1); mask != 0; mask <<= 1 { 710 old := x.i.Load() 711 k := x.i.And(^mask) 712 j &= ^mask 713 if x.i.Load() != j || k != old { 714 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old) 715 } 716 } 717 if x.before != magic64 || x.after != magic64 { 718 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 719 } 720} 721 722func TestAndUintptr(t *testing.T) { 723 var x struct { 724 before uintptr 725 i uintptr 726 after uintptr 727 } 728 var m uint64 = magic64 729 magicptr := uintptr(m) 730 x.before = magicptr 731 x.after = magicptr 732 x.i = ^uintptr(0) 733 j := x.i 734 for mask := uintptr(1); mask != 0; mask <<= 1 { 735 old := x.i 736 k := AndUintptr(&x.i, ^mask) 737 j &= ^mask 738 if x.i != j || k != old { 739 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old) 740 } 741 } 742 if x.before != magicptr || x.after != magicptr { 743 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 744 } 745} 746 747func TestAndUintptrMethod(t *testing.T) { 748 var x struct { 749 before uintptr 750 i Uintptr 751 after uintptr 752 } 753 var m uint64 = magic64 754 magicptr := uintptr(m) 755 x.before = magicptr 756 x.after = magicptr 757 x.i.Store(^uintptr(0)) 758 j := x.i.Load() 759 for mask := uintptr(1); mask != 0; mask <<= 1 { 760 old := x.i.Load() 761 k := x.i.And(^mask) 762 j &= ^mask 763 if x.i.Load() != j || k != old { 764 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old) 765 } 766 } 767 if x.before != magicptr || x.after != magicptr { 768 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 769 } 770} 771 772func TestOrInt32(t *testing.T) { 773 var x struct { 774 before int32 775 i int32 776 after int32 777 } 778 x.before = magic32 779 x.after = magic32 780 var j int32 781 for mask := int32(1); mask != 0; mask <<= 1 { 782 old := x.i 783 k := OrInt32(&x.i, mask) 784 j |= mask 785 if x.i != j || k != old { 786 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old) 787 } 788 } 789 if x.before != magic32 || x.after != magic32 { 790 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 791 } 792} 793 794func TestOrInt32Method(t *testing.T) { 795 var x struct { 796 before int32 797 i Int32 798 after int32 799 } 800 x.before = magic32 801 x.after = magic32 802 var j int32 803 for mask := int32(1); mask != 0; mask <<= 1 { 804 old := x.i.Load() 805 k := x.i.Or(mask) 806 j |= mask 807 if x.i.Load() != j || k != old { 808 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old) 809 } 810 } 811 if x.before != magic32 || x.after != magic32 { 812 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 813 } 814} 815 816func TestOrUint32(t *testing.T) { 817 var x struct { 818 before uint32 819 i uint32 820 after uint32 821 } 822 x.before = magic32 823 x.after = magic32 824 var j uint32 825 for mask := uint32(1); mask != 0; mask <<= 1 { 826 old := x.i 827 k := OrUint32(&x.i, mask) 828 j |= mask 829 if x.i != j || k != old { 830 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old) 831 } 832 } 833 if x.before != magic32 || x.after != magic32 { 834 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 835 } 836} 837 838func TestOrUint32Method(t *testing.T) { 839 var x struct { 840 before uint32 841 i Uint32 842 after uint32 843 } 844 x.before = magic32 845 x.after = magic32 846 var j uint32 847 for mask := uint32(1); mask != 0; mask <<= 1 { 848 old := x.i.Load() 849 k := x.i.Or(mask) 850 j |= mask 851 if x.i.Load() != j || k != old { 852 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old) 853 } 854 } 855 if x.before != magic32 || x.after != magic32 { 856 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 857 } 858} 859 860func TestOrInt64(t *testing.T) { 861 var x struct { 862 before int64 863 i int64 864 after int64 865 } 866 magic64 := int64(magic64) 867 x.before = magic64 868 x.after = magic64 869 var j int64 870 for mask := int64(1); mask != 0; mask <<= 1 { 871 old := x.i 872 k := OrInt64(&x.i, mask) 873 j |= mask 874 if x.i != j || k != old { 875 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old) 876 } 877 } 878 if x.before != magic64 || x.after != magic64 { 879 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 880 } 881} 882 883func TestOrInt64Method(t *testing.T) { 884 var x struct { 885 before int64 886 i Int64 887 after int64 888 } 889 magic64 := int64(magic64) 890 x.before = magic64 891 x.after = magic64 892 var j int64 893 for mask := int64(1); mask != 0; mask <<= 1 { 894 old := x.i.Load() 895 k := x.i.Or(mask) 896 j |= mask 897 if x.i.Load() != j || k != old { 898 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old) 899 } 900 } 901 if x.before != magic64 || x.after != magic64 { 902 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 903 } 904} 905 906func TestOrUint64(t *testing.T) { 907 var x struct { 908 before uint64 909 i uint64 910 after uint64 911 } 912 magic64 := uint64(magic64) 913 x.before = magic64 914 x.after = magic64 915 var j uint64 916 for mask := uint64(1); mask != 0; mask <<= 1 { 917 old := x.i 918 k := OrUint64(&x.i, mask) 919 j |= mask 920 if x.i != j || k != old { 921 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old) 922 } 923 } 924 if x.before != magic64 || x.after != magic64 { 925 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 926 } 927} 928 929func TestOrUint64Method(t *testing.T) { 930 var x struct { 931 before uint64 932 i Uint64 933 after uint64 934 } 935 magic64 := uint64(magic64) 936 x.before = magic64 937 x.after = magic64 938 var j uint64 939 for mask := uint64(1); mask != 0; mask <<= 1 { 940 old := x.i.Load() 941 k := x.i.Or(mask) 942 j |= mask 943 if x.i.Load() != j || k != old { 944 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old) 945 } 946 } 947 if x.before != magic64 || x.after != magic64 { 948 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 949 } 950} 951 952func TestOrUintptr(t *testing.T) { 953 var x struct { 954 before uintptr 955 i uintptr 956 after uintptr 957 } 958 var m uint64 = magic64 959 magicptr := uintptr(m) 960 x.before = magicptr 961 x.after = magicptr 962 var j uintptr 963 for mask := uintptr(1); mask != 0; mask <<= 1 { 964 old := x.i 965 k := OrUintptr(&x.i, mask) 966 j |= mask 967 if x.i != j || k != old { 968 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i, j, k, old) 969 } 970 } 971 if x.before != magicptr || x.after != magicptr { 972 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 973 } 974} 975 976func TestOrUintptrMethod(t *testing.T) { 977 var x struct { 978 before uintptr 979 i Uintptr 980 after uintptr 981 } 982 var m uint64 = magic64 983 magicptr := uintptr(m) 984 x.before = magicptr 985 x.after = magicptr 986 var j uintptr 987 for mask := uintptr(1); mask != 0; mask <<= 1 { 988 old := x.i.Load() 989 k := x.i.Or(mask) 990 j |= mask 991 if x.i.Load() != j || k != old { 992 t.Fatalf("mask=%d i=%d j=%d k=%d old=%d", mask, x.i.Load(), j, k, old) 993 } 994 } 995 if x.before != magicptr || x.after != magicptr { 996 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 997 } 998} 999 1000func TestCompareAndSwapInt32(t *testing.T) { 1001 var x struct { 1002 before int32 1003 i int32 1004 after int32 1005 } 1006 x.before = magic32 1007 x.after = magic32 1008 for val := int32(1); val+val > val; val += val { 1009 x.i = val 1010 if !CompareAndSwapInt32(&x.i, val, val+1) { 1011 t.Fatalf("should have swapped %#x %#x", val, val+1) 1012 } 1013 if x.i != val+1 { 1014 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) 1015 } 1016 x.i = val + 1 1017 if CompareAndSwapInt32(&x.i, val, val+2) { 1018 t.Fatalf("should not have swapped %#x %#x", val, val+2) 1019 } 1020 if x.i != val+1 { 1021 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) 1022 } 1023 } 1024 if x.before != magic32 || x.after != magic32 { 1025 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 1026 } 1027} 1028 1029func TestCompareAndSwapInt32Method(t *testing.T) { 1030 var x struct { 1031 before int32 1032 i Int32 1033 after int32 1034 } 1035 x.before = magic32 1036 x.after = magic32 1037 for val := int32(1); val+val > val; val += val { 1038 x.i.Store(val) 1039 if !x.i.CompareAndSwap(val, val+1) { 1040 t.Fatalf("should have swapped %#x %#x", val, val+1) 1041 } 1042 if x.i.Load() != val+1 { 1043 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) 1044 } 1045 x.i.Store(val + 1) 1046 if x.i.CompareAndSwap(val, val+2) { 1047 t.Fatalf("should not have swapped %#x %#x", val, val+2) 1048 } 1049 if x.i.Load() != val+1 { 1050 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) 1051 } 1052 } 1053 if x.before != magic32 || x.after != magic32 { 1054 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 1055 } 1056} 1057 1058func TestCompareAndSwapUint32(t *testing.T) { 1059 var x struct { 1060 before uint32 1061 i uint32 1062 after uint32 1063 } 1064 x.before = magic32 1065 x.after = magic32 1066 for val := uint32(1); val+val > val; val += val { 1067 x.i = val 1068 if !CompareAndSwapUint32(&x.i, val, val+1) { 1069 t.Fatalf("should have swapped %#x %#x", val, val+1) 1070 } 1071 if x.i != val+1 { 1072 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) 1073 } 1074 x.i = val + 1 1075 if CompareAndSwapUint32(&x.i, val, val+2) { 1076 t.Fatalf("should not have swapped %#x %#x", val, val+2) 1077 } 1078 if x.i != val+1 { 1079 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) 1080 } 1081 } 1082 if x.before != magic32 || x.after != magic32 { 1083 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 1084 } 1085} 1086 1087func TestCompareAndSwapUint32Method(t *testing.T) { 1088 var x struct { 1089 before uint32 1090 i Uint32 1091 after uint32 1092 } 1093 x.before = magic32 1094 x.after = magic32 1095 for val := uint32(1); val+val > val; val += val { 1096 x.i.Store(val) 1097 if !x.i.CompareAndSwap(val, val+1) { 1098 t.Fatalf("should have swapped %#x %#x", val, val+1) 1099 } 1100 if x.i.Load() != val+1 { 1101 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) 1102 } 1103 x.i.Store(val + 1) 1104 if x.i.CompareAndSwap(val, val+2) { 1105 t.Fatalf("should not have swapped %#x %#x", val, val+2) 1106 } 1107 if x.i.Load() != val+1 { 1108 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) 1109 } 1110 } 1111 if x.before != magic32 || x.after != magic32 { 1112 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 1113 } 1114} 1115 1116func TestCompareAndSwapInt64(t *testing.T) { 1117 var x struct { 1118 before int64 1119 i int64 1120 after int64 1121 } 1122 magic64 := int64(magic64) 1123 x.before = magic64 1124 x.after = magic64 1125 for val := int64(1); val+val > val; val += val { 1126 x.i = val 1127 if !CompareAndSwapInt64(&x.i, val, val+1) { 1128 t.Fatalf("should have swapped %#x %#x", val, val+1) 1129 } 1130 if x.i != val+1 { 1131 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) 1132 } 1133 x.i = val + 1 1134 if CompareAndSwapInt64(&x.i, val, val+2) { 1135 t.Fatalf("should not have swapped %#x %#x", val, val+2) 1136 } 1137 if x.i != val+1 { 1138 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) 1139 } 1140 } 1141 if x.before != magic64 || x.after != magic64 { 1142 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 1143 } 1144} 1145 1146func TestCompareAndSwapInt64Method(t *testing.T) { 1147 var x struct { 1148 before int64 1149 i Int64 1150 after int64 1151 } 1152 magic64 := int64(magic64) 1153 x.before = magic64 1154 x.after = magic64 1155 for val := int64(1); val+val > val; val += val { 1156 x.i.Store(val) 1157 if !x.i.CompareAndSwap(val, val+1) { 1158 t.Fatalf("should have swapped %#x %#x", val, val+1) 1159 } 1160 if x.i.Load() != val+1 { 1161 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) 1162 } 1163 x.i.Store(val + 1) 1164 if x.i.CompareAndSwap(val, val+2) { 1165 t.Fatalf("should not have swapped %#x %#x", val, val+2) 1166 } 1167 if x.i.Load() != val+1 { 1168 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) 1169 } 1170 } 1171 if x.before != magic64 || x.after != magic64 { 1172 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 1173 } 1174} 1175 1176func testCompareAndSwapUint64(t *testing.T, cas func(*uint64, uint64, uint64) bool) { 1177 var x struct { 1178 before uint64 1179 i uint64 1180 after uint64 1181 } 1182 magic64 := uint64(magic64) 1183 x.before = magic64 1184 x.after = magic64 1185 for val := uint64(1); val+val > val; val += val { 1186 x.i = val 1187 if !cas(&x.i, val, val+1) { 1188 t.Fatalf("should have swapped %#x %#x", val, val+1) 1189 } 1190 if x.i != val+1 { 1191 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) 1192 } 1193 x.i = val + 1 1194 if cas(&x.i, val, val+2) { 1195 t.Fatalf("should not have swapped %#x %#x", val, val+2) 1196 } 1197 if x.i != val+1 { 1198 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) 1199 } 1200 } 1201 if x.before != magic64 || x.after != magic64 { 1202 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 1203 } 1204} 1205 1206func TestCompareAndSwapUint64(t *testing.T) { 1207 testCompareAndSwapUint64(t, CompareAndSwapUint64) 1208} 1209 1210func TestCompareAndSwapUint64Method(t *testing.T) { 1211 var x struct { 1212 before uint64 1213 i Uint64 1214 after uint64 1215 } 1216 magic64 := uint64(magic64) 1217 x.before = magic64 1218 x.after = magic64 1219 for val := uint64(1); val+val > val; val += val { 1220 x.i.Store(val) 1221 if !x.i.CompareAndSwap(val, val+1) { 1222 t.Fatalf("should have swapped %#x %#x", val, val+1) 1223 } 1224 if x.i.Load() != val+1 { 1225 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) 1226 } 1227 x.i.Store(val + 1) 1228 if x.i.CompareAndSwap(val, val+2) { 1229 t.Fatalf("should not have swapped %#x %#x", val, val+2) 1230 } 1231 if x.i.Load() != val+1 { 1232 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) 1233 } 1234 } 1235 if x.before != magic64 || x.after != magic64 { 1236 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 1237 } 1238} 1239 1240func TestCompareAndSwapUintptr(t *testing.T) { 1241 var x struct { 1242 before uintptr 1243 i uintptr 1244 after uintptr 1245 } 1246 var m uint64 = magic64 1247 magicptr := uintptr(m) 1248 x.before = magicptr 1249 x.after = magicptr 1250 for val := uintptr(1); val+val > val; val += val { 1251 x.i = val 1252 if !CompareAndSwapUintptr(&x.i, val, val+1) { 1253 t.Fatalf("should have swapped %#x %#x", val, val+1) 1254 } 1255 if x.i != val+1 { 1256 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) 1257 } 1258 x.i = val + 1 1259 if CompareAndSwapUintptr(&x.i, val, val+2) { 1260 t.Fatalf("should not have swapped %#x %#x", val, val+2) 1261 } 1262 if x.i != val+1 { 1263 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) 1264 } 1265 } 1266 if x.before != magicptr || x.after != magicptr { 1267 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 1268 } 1269} 1270 1271func TestCompareAndSwapUintptrMethod(t *testing.T) { 1272 var x struct { 1273 before uintptr 1274 i Uintptr 1275 after uintptr 1276 } 1277 var m uint64 = magic64 1278 magicptr := uintptr(m) 1279 x.before = magicptr 1280 x.after = magicptr 1281 for val := uintptr(1); val+val > val; val += val { 1282 x.i.Store(val) 1283 if !x.i.CompareAndSwap(val, val+1) { 1284 t.Fatalf("should have swapped %#x %#x", val, val+1) 1285 } 1286 if x.i.Load() != val+1 { 1287 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) 1288 } 1289 x.i.Store(val + 1) 1290 if x.i.CompareAndSwap(val, val+2) { 1291 t.Fatalf("should not have swapped %#x %#x", val, val+2) 1292 } 1293 if x.i.Load() != val+1 { 1294 t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i.Load(), val+1) 1295 } 1296 } 1297 if x.before != magicptr || x.after != magicptr { 1298 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uintptr(magicptr), uintptr(magicptr)) 1299 } 1300} 1301 1302func TestCompareAndSwapPointer(t *testing.T) { 1303 var x struct { 1304 before uintptr 1305 i unsafe.Pointer 1306 after uintptr 1307 } 1308 var m uint64 = magic64 1309 magicptr := uintptr(m) 1310 x.before = magicptr 1311 x.after = magicptr 1312 q := unsafe.Pointer(new(byte)) 1313 for _, p := range testPointers() { 1314 x.i = p 1315 if !CompareAndSwapPointer(&x.i, p, q) { 1316 t.Fatalf("should have swapped %p %p", p, q) 1317 } 1318 if x.i != q { 1319 t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i, q) 1320 } 1321 if CompareAndSwapPointer(&x.i, p, nil) { 1322 t.Fatalf("should not have swapped %p nil", p) 1323 } 1324 if x.i != q { 1325 t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i, q) 1326 } 1327 } 1328 if x.before != magicptr || x.after != magicptr { 1329 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 1330 } 1331} 1332 1333func TestCompareAndSwapPointerMethod(t *testing.T) { 1334 var x struct { 1335 before uintptr 1336 i Pointer[byte] 1337 after uintptr 1338 } 1339 var m uint64 = magic64 1340 magicptr := uintptr(m) 1341 x.before = magicptr 1342 x.after = magicptr 1343 q := new(byte) 1344 for _, p := range testPointers() { 1345 p := (*byte)(p) 1346 x.i.Store(p) 1347 if !x.i.CompareAndSwap(p, q) { 1348 t.Fatalf("should have swapped %p %p", p, q) 1349 } 1350 if x.i.Load() != q { 1351 t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i.Load(), q) 1352 } 1353 if x.i.CompareAndSwap(p, nil) { 1354 t.Fatalf("should not have swapped %p nil", p) 1355 } 1356 if x.i.Load() != q { 1357 t.Fatalf("wrong x.i after swap: x.i=%p want %p", x.i.Load(), q) 1358 } 1359 } 1360 if x.before != magicptr || x.after != magicptr { 1361 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 1362 } 1363} 1364 1365func TestLoadInt32(t *testing.T) { 1366 var x struct { 1367 before int32 1368 i int32 1369 after int32 1370 } 1371 x.before = magic32 1372 x.after = magic32 1373 for delta := int32(1); delta+delta > delta; delta += delta { 1374 k := LoadInt32(&x.i) 1375 if k != x.i { 1376 t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) 1377 } 1378 x.i += delta 1379 } 1380 if x.before != magic32 || x.after != magic32 { 1381 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 1382 } 1383} 1384 1385func TestLoadInt32Method(t *testing.T) { 1386 var x struct { 1387 before int32 1388 i Int32 1389 after int32 1390 } 1391 x.before = magic32 1392 x.after = magic32 1393 want := int32(0) 1394 for delta := int32(1); delta+delta > delta; delta += delta { 1395 k := x.i.Load() 1396 if k != want { 1397 t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want) 1398 } 1399 x.i.Store(k + delta) 1400 want = k + delta 1401 } 1402 if x.before != magic32 || x.after != magic32 { 1403 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 1404 } 1405} 1406 1407func TestLoadUint32(t *testing.T) { 1408 var x struct { 1409 before uint32 1410 i uint32 1411 after uint32 1412 } 1413 x.before = magic32 1414 x.after = magic32 1415 for delta := uint32(1); delta+delta > delta; delta += delta { 1416 k := LoadUint32(&x.i) 1417 if k != x.i { 1418 t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) 1419 } 1420 x.i += delta 1421 } 1422 if x.before != magic32 || x.after != magic32 { 1423 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 1424 } 1425} 1426 1427func TestLoadUint32Method(t *testing.T) { 1428 var x struct { 1429 before uint32 1430 i Uint32 1431 after uint32 1432 } 1433 x.before = magic32 1434 x.after = magic32 1435 want := uint32(0) 1436 for delta := uint32(1); delta+delta > delta; delta += delta { 1437 k := x.i.Load() 1438 if k != want { 1439 t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want) 1440 } 1441 x.i.Store(k + delta) 1442 want = k + delta 1443 } 1444 if x.before != magic32 || x.after != magic32 { 1445 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 1446 } 1447} 1448 1449func TestLoadInt64(t *testing.T) { 1450 var x struct { 1451 before int64 1452 i int64 1453 after int64 1454 } 1455 magic64 := int64(magic64) 1456 x.before = magic64 1457 x.after = magic64 1458 for delta := int64(1); delta+delta > delta; delta += delta { 1459 k := LoadInt64(&x.i) 1460 if k != x.i { 1461 t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) 1462 } 1463 x.i += delta 1464 } 1465 if x.before != magic64 || x.after != magic64 { 1466 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 1467 } 1468} 1469 1470func TestLoadInt64Method(t *testing.T) { 1471 var x struct { 1472 before int64 1473 i Int64 1474 after int64 1475 } 1476 magic64 := int64(magic64) 1477 x.before = magic64 1478 x.after = magic64 1479 want := int64(0) 1480 for delta := int64(1); delta+delta > delta; delta += delta { 1481 k := x.i.Load() 1482 if k != want { 1483 t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want) 1484 } 1485 x.i.Store(k + delta) 1486 want = k + delta 1487 } 1488 if x.before != magic64 || x.after != magic64 { 1489 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 1490 } 1491} 1492 1493func TestLoadUint64(t *testing.T) { 1494 var x struct { 1495 before uint64 1496 i uint64 1497 after uint64 1498 } 1499 magic64 := uint64(magic64) 1500 x.before = magic64 1501 x.after = magic64 1502 for delta := uint64(1); delta+delta > delta; delta += delta { 1503 k := LoadUint64(&x.i) 1504 if k != x.i { 1505 t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) 1506 } 1507 x.i += delta 1508 } 1509 if x.before != magic64 || x.after != magic64 { 1510 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 1511 } 1512} 1513 1514func TestLoadUint64Method(t *testing.T) { 1515 var x struct { 1516 before uint64 1517 i Uint64 1518 after uint64 1519 } 1520 magic64 := uint64(magic64) 1521 x.before = magic64 1522 x.after = magic64 1523 want := uint64(0) 1524 for delta := uint64(1); delta+delta > delta; delta += delta { 1525 k := x.i.Load() 1526 if k != want { 1527 t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want) 1528 } 1529 x.i.Store(k + delta) 1530 want = k + delta 1531 } 1532 if x.before != magic64 || x.after != magic64 { 1533 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 1534 } 1535} 1536 1537func TestLoadUintptr(t *testing.T) { 1538 var x struct { 1539 before uintptr 1540 i uintptr 1541 after uintptr 1542 } 1543 var m uint64 = magic64 1544 magicptr := uintptr(m) 1545 x.before = magicptr 1546 x.after = magicptr 1547 for delta := uintptr(1); delta+delta > delta; delta += delta { 1548 k := LoadUintptr(&x.i) 1549 if k != x.i { 1550 t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) 1551 } 1552 x.i += delta 1553 } 1554 if x.before != magicptr || x.after != magicptr { 1555 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 1556 } 1557} 1558 1559func TestLoadUintptrMethod(t *testing.T) { 1560 var x struct { 1561 before uintptr 1562 i Uintptr 1563 after uintptr 1564 } 1565 var m uint64 = magic64 1566 magicptr := uintptr(m) 1567 x.before = magicptr 1568 x.after = magicptr 1569 want := uintptr(0) 1570 for delta := uintptr(1); delta+delta > delta; delta += delta { 1571 k := x.i.Load() 1572 if k != want { 1573 t.Fatalf("delta=%d i=%d k=%d want=%d", delta, x.i.Load(), k, want) 1574 } 1575 x.i.Store(k + delta) 1576 want = k + delta 1577 } 1578 if x.before != magicptr || x.after != magicptr { 1579 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 1580 } 1581} 1582 1583func TestLoadPointer(t *testing.T) { 1584 var x struct { 1585 before uintptr 1586 i unsafe.Pointer 1587 after uintptr 1588 } 1589 var m uint64 = magic64 1590 magicptr := uintptr(m) 1591 x.before = magicptr 1592 x.after = magicptr 1593 for _, p := range testPointers() { 1594 x.i = p 1595 k := LoadPointer(&x.i) 1596 if k != p { 1597 t.Fatalf("p=%x k=%x", p, k) 1598 } 1599 } 1600 if x.before != magicptr || x.after != magicptr { 1601 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 1602 } 1603} 1604 1605func TestLoadPointerMethod(t *testing.T) { 1606 var x struct { 1607 before uintptr 1608 i Pointer[byte] 1609 after uintptr 1610 } 1611 var m uint64 = magic64 1612 magicptr := uintptr(m) 1613 x.before = magicptr 1614 x.after = magicptr 1615 for _, p := range testPointers() { 1616 p := (*byte)(p) 1617 x.i.Store(p) 1618 k := x.i.Load() 1619 if k != p { 1620 t.Fatalf("p=%x k=%x", p, k) 1621 } 1622 } 1623 if x.before != magicptr || x.after != magicptr { 1624 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 1625 } 1626} 1627 1628func TestStoreInt32(t *testing.T) { 1629 var x struct { 1630 before int32 1631 i int32 1632 after int32 1633 } 1634 x.before = magic32 1635 x.after = magic32 1636 v := int32(0) 1637 for delta := int32(1); delta+delta > delta; delta += delta { 1638 StoreInt32(&x.i, v) 1639 if x.i != v { 1640 t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) 1641 } 1642 v += delta 1643 } 1644 if x.before != magic32 || x.after != magic32 { 1645 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 1646 } 1647} 1648 1649func TestStoreInt32Method(t *testing.T) { 1650 var x struct { 1651 before int32 1652 i Int32 1653 after int32 1654 } 1655 x.before = magic32 1656 x.after = magic32 1657 v := int32(0) 1658 for delta := int32(1); delta+delta > delta; delta += delta { 1659 x.i.Store(v) 1660 if x.i.Load() != v { 1661 t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v) 1662 } 1663 v += delta 1664 } 1665 if x.before != magic32 || x.after != magic32 { 1666 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 1667 } 1668} 1669 1670func TestStoreUint32(t *testing.T) { 1671 var x struct { 1672 before uint32 1673 i uint32 1674 after uint32 1675 } 1676 x.before = magic32 1677 x.after = magic32 1678 v := uint32(0) 1679 for delta := uint32(1); delta+delta > delta; delta += delta { 1680 StoreUint32(&x.i, v) 1681 if x.i != v { 1682 t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) 1683 } 1684 v += delta 1685 } 1686 if x.before != magic32 || x.after != magic32 { 1687 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 1688 } 1689} 1690 1691func TestStoreUint32Method(t *testing.T) { 1692 var x struct { 1693 before uint32 1694 i Uint32 1695 after uint32 1696 } 1697 x.before = magic32 1698 x.after = magic32 1699 v := uint32(0) 1700 for delta := uint32(1); delta+delta > delta; delta += delta { 1701 x.i.Store(v) 1702 if x.i.Load() != v { 1703 t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v) 1704 } 1705 v += delta 1706 } 1707 if x.before != magic32 || x.after != magic32 { 1708 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) 1709 } 1710} 1711 1712func TestStoreInt64(t *testing.T) { 1713 var x struct { 1714 before int64 1715 i int64 1716 after int64 1717 } 1718 magic64 := int64(magic64) 1719 x.before = magic64 1720 x.after = magic64 1721 v := int64(0) 1722 for delta := int64(1); delta+delta > delta; delta += delta { 1723 StoreInt64(&x.i, v) 1724 if x.i != v { 1725 t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) 1726 } 1727 v += delta 1728 } 1729 if x.before != magic64 || x.after != magic64 { 1730 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 1731 } 1732} 1733 1734func TestStoreInt64Method(t *testing.T) { 1735 var x struct { 1736 before int64 1737 i Int64 1738 after int64 1739 } 1740 magic64 := int64(magic64) 1741 x.before = magic64 1742 x.after = magic64 1743 v := int64(0) 1744 for delta := int64(1); delta+delta > delta; delta += delta { 1745 x.i.Store(v) 1746 if x.i.Load() != v { 1747 t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v) 1748 } 1749 v += delta 1750 } 1751 if x.before != magic64 || x.after != magic64 { 1752 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 1753 } 1754} 1755 1756func TestStoreUint64(t *testing.T) { 1757 var x struct { 1758 before uint64 1759 i uint64 1760 after uint64 1761 } 1762 magic64 := uint64(magic64) 1763 x.before = magic64 1764 x.after = magic64 1765 v := uint64(0) 1766 for delta := uint64(1); delta+delta > delta; delta += delta { 1767 StoreUint64(&x.i, v) 1768 if x.i != v { 1769 t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) 1770 } 1771 v += delta 1772 } 1773 if x.before != magic64 || x.after != magic64 { 1774 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 1775 } 1776} 1777 1778func TestStoreUint64Method(t *testing.T) { 1779 var x struct { 1780 before uint64 1781 i Uint64 1782 after uint64 1783 } 1784 magic64 := uint64(magic64) 1785 x.before = magic64 1786 x.after = magic64 1787 v := uint64(0) 1788 for delta := uint64(1); delta+delta > delta; delta += delta { 1789 x.i.Store(v) 1790 if x.i.Load() != v { 1791 t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v) 1792 } 1793 v += delta 1794 } 1795 if x.before != magic64 || x.after != magic64 { 1796 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic64, magic64) 1797 } 1798} 1799 1800func TestStoreUintptr(t *testing.T) { 1801 var x struct { 1802 before uintptr 1803 i uintptr 1804 after uintptr 1805 } 1806 var m uint64 = magic64 1807 magicptr := uintptr(m) 1808 x.before = magicptr 1809 x.after = magicptr 1810 v := uintptr(0) 1811 for delta := uintptr(1); delta+delta > delta; delta += delta { 1812 StoreUintptr(&x.i, v) 1813 if x.i != v { 1814 t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) 1815 } 1816 v += delta 1817 } 1818 if x.before != magicptr || x.after != magicptr { 1819 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 1820 } 1821} 1822 1823func TestStoreUintptrMethod(t *testing.T) { 1824 var x struct { 1825 before uintptr 1826 i Uintptr 1827 after uintptr 1828 } 1829 var m uint64 = magic64 1830 magicptr := uintptr(m) 1831 x.before = magicptr 1832 x.after = magicptr 1833 v := uintptr(0) 1834 for delta := uintptr(1); delta+delta > delta; delta += delta { 1835 x.i.Store(v) 1836 if x.i.Load() != v { 1837 t.Fatalf("delta=%d i=%d v=%d", delta, x.i.Load(), v) 1838 } 1839 v += delta 1840 } 1841 if x.before != magicptr || x.after != magicptr { 1842 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 1843 } 1844} 1845 1846func TestStorePointer(t *testing.T) { 1847 var x struct { 1848 before uintptr 1849 i unsafe.Pointer 1850 after uintptr 1851 } 1852 var m uint64 = magic64 1853 magicptr := uintptr(m) 1854 x.before = magicptr 1855 x.after = magicptr 1856 for _, p := range testPointers() { 1857 StorePointer(&x.i, p) 1858 if x.i != p { 1859 t.Fatalf("x.i=%p p=%p", x.i, p) 1860 } 1861 } 1862 if x.before != magicptr || x.after != magicptr { 1863 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 1864 } 1865} 1866 1867func TestStorePointerMethod(t *testing.T) { 1868 var x struct { 1869 before uintptr 1870 i Pointer[byte] 1871 after uintptr 1872 } 1873 var m uint64 = magic64 1874 magicptr := uintptr(m) 1875 x.before = magicptr 1876 x.after = magicptr 1877 for _, p := range testPointers() { 1878 p := (*byte)(p) 1879 x.i.Store(p) 1880 if x.i.Load() != p { 1881 t.Fatalf("x.i=%p p=%p", x.i.Load(), p) 1882 } 1883 } 1884 if x.before != magicptr || x.after != magicptr { 1885 t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) 1886 } 1887} 1888 1889// Tests of correct behavior, with contention. 1890// (Is the function atomic?) 1891// 1892// For each function, we write a "hammer" function that repeatedly 1893// uses the atomic operation to add 1 to a value. After running 1894// multiple hammers in parallel, check that we end with the correct 1895// total. 1896// Swap can't add 1, so it uses a different scheme. 1897// The functions repeatedly generate a pseudo-random number such that 1898// low bits are equal to high bits, swap, check that the old value 1899// has low and high bits equal. 1900 1901var hammer32 = map[string]func(*uint32, int){ 1902 "SwapInt32": hammerSwapInt32, 1903 "SwapUint32": hammerSwapUint32, 1904 "SwapUintptr": hammerSwapUintptr32, 1905 "AddInt32": hammerAddInt32, 1906 "AddUint32": hammerAddUint32, 1907 "AddUintptr": hammerAddUintptr32, 1908 "CompareAndSwapInt32": hammerCompareAndSwapInt32, 1909 "CompareAndSwapUint32": hammerCompareAndSwapUint32, 1910 "CompareAndSwapUintptr": hammerCompareAndSwapUintptr32, 1911 1912 "SwapInt32Method": hammerSwapInt32Method, 1913 "SwapUint32Method": hammerSwapUint32Method, 1914 "SwapUintptrMethod": hammerSwapUintptr32Method, 1915 "AddInt32Method": hammerAddInt32Method, 1916 "AddUint32Method": hammerAddUint32Method, 1917 "AddUintptrMethod": hammerAddUintptr32Method, 1918 "CompareAndSwapInt32Method": hammerCompareAndSwapInt32Method, 1919 "CompareAndSwapUint32Method": hammerCompareAndSwapUint32Method, 1920 "CompareAndSwapUintptrMethod": hammerCompareAndSwapUintptr32Method, 1921} 1922 1923func init() { 1924 var v uint64 = 1 << 50 1925 if uintptr(v) != 0 { 1926 // 64-bit system; clear uintptr tests 1927 delete(hammer32, "SwapUintptr") 1928 delete(hammer32, "AddUintptr") 1929 delete(hammer32, "CompareAndSwapUintptr") 1930 delete(hammer32, "SwapUintptrMethod") 1931 delete(hammer32, "AddUintptrMethod") 1932 delete(hammer32, "CompareAndSwapUintptrMethod") 1933 } 1934} 1935 1936func hammerSwapInt32(uaddr *uint32, count int) { 1937 addr := (*int32)(unsafe.Pointer(uaddr)) 1938 seed := int(uintptr(unsafe.Pointer(&count))) 1939 for i := 0; i < count; i++ { 1940 new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16 1941 old := uint32(SwapInt32(addr, int32(new))) 1942 if old>>16 != old<<16>>16 { 1943 panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old)) 1944 } 1945 } 1946} 1947 1948func hammerSwapInt32Method(uaddr *uint32, count int) { 1949 addr := (*Int32)(unsafe.Pointer(uaddr)) 1950 seed := int(uintptr(unsafe.Pointer(&count))) 1951 for i := 0; i < count; i++ { 1952 new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16 1953 old := uint32(addr.Swap(int32(new))) 1954 if old>>16 != old<<16>>16 { 1955 panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old)) 1956 } 1957 } 1958} 1959 1960func hammerSwapUint32(addr *uint32, count int) { 1961 seed := int(uintptr(unsafe.Pointer(&count))) 1962 for i := 0; i < count; i++ { 1963 new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16 1964 old := SwapUint32(addr, new) 1965 if old>>16 != old<<16>>16 { 1966 panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old)) 1967 } 1968 } 1969} 1970 1971func hammerSwapUint32Method(uaddr *uint32, count int) { 1972 addr := (*Uint32)(unsafe.Pointer(uaddr)) 1973 seed := int(uintptr(unsafe.Pointer(&count))) 1974 for i := 0; i < count; i++ { 1975 new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16 1976 old := addr.Swap(new) 1977 if old>>16 != old<<16>>16 { 1978 panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old)) 1979 } 1980 } 1981} 1982 1983func hammerSwapUintptr32(uaddr *uint32, count int) { 1984 // only safe when uintptr is 32-bit. 1985 // not called on 64-bit systems. 1986 addr := (*uintptr)(unsafe.Pointer(uaddr)) 1987 seed := int(uintptr(unsafe.Pointer(&count))) 1988 for i := 0; i < count; i++ { 1989 new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16 1990 old := SwapUintptr(addr, new) 1991 if old>>16 != old<<16>>16 { 1992 panic(fmt.Sprintf("SwapUintptr is not atomic: %#08x", old)) 1993 } 1994 } 1995} 1996 1997func hammerSwapUintptr32Method(uaddr *uint32, count int) { 1998 // only safe when uintptr is 32-bit. 1999 // not called on 64-bit systems. 2000 addr := (*Uintptr)(unsafe.Pointer(uaddr)) 2001 seed := int(uintptr(unsafe.Pointer(&count))) 2002 for i := 0; i < count; i++ { 2003 new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16 2004 old := addr.Swap(new) 2005 if old>>16 != old<<16>>16 { 2006 panic(fmt.Sprintf("Uintptr.Swap is not atomic: %#08x", old)) 2007 } 2008 } 2009} 2010 2011func hammerAddInt32(uaddr *uint32, count int) { 2012 addr := (*int32)(unsafe.Pointer(uaddr)) 2013 for i := 0; i < count; i++ { 2014 AddInt32(addr, 1) 2015 } 2016} 2017 2018func hammerAddInt32Method(uaddr *uint32, count int) { 2019 addr := (*Int32)(unsafe.Pointer(uaddr)) 2020 for i := 0; i < count; i++ { 2021 addr.Add(1) 2022 } 2023} 2024 2025func hammerAddUint32(addr *uint32, count int) { 2026 for i := 0; i < count; i++ { 2027 AddUint32(addr, 1) 2028 } 2029} 2030 2031func hammerAddUint32Method(uaddr *uint32, count int) { 2032 addr := (*Uint32)(unsafe.Pointer(uaddr)) 2033 for i := 0; i < count; i++ { 2034 addr.Add(1) 2035 } 2036} 2037 2038func hammerAddUintptr32(uaddr *uint32, count int) { 2039 // only safe when uintptr is 32-bit. 2040 // not called on 64-bit systems. 2041 addr := (*uintptr)(unsafe.Pointer(uaddr)) 2042 for i := 0; i < count; i++ { 2043 AddUintptr(addr, 1) 2044 } 2045} 2046 2047func hammerAddUintptr32Method(uaddr *uint32, count int) { 2048 // only safe when uintptr is 32-bit. 2049 // not called on 64-bit systems. 2050 addr := (*Uintptr)(unsafe.Pointer(uaddr)) 2051 for i := 0; i < count; i++ { 2052 addr.Add(1) 2053 } 2054} 2055 2056func hammerCompareAndSwapInt32(uaddr *uint32, count int) { 2057 addr := (*int32)(unsafe.Pointer(uaddr)) 2058 for i := 0; i < count; i++ { 2059 for { 2060 v := LoadInt32(addr) 2061 if CompareAndSwapInt32(addr, v, v+1) { 2062 break 2063 } 2064 } 2065 } 2066} 2067 2068func hammerCompareAndSwapInt32Method(uaddr *uint32, count int) { 2069 addr := (*Int32)(unsafe.Pointer(uaddr)) 2070 for i := 0; i < count; i++ { 2071 for { 2072 v := addr.Load() 2073 if addr.CompareAndSwap(v, v+1) { 2074 break 2075 } 2076 } 2077 } 2078} 2079 2080func hammerCompareAndSwapUint32(addr *uint32, count int) { 2081 for i := 0; i < count; i++ { 2082 for { 2083 v := LoadUint32(addr) 2084 if CompareAndSwapUint32(addr, v, v+1) { 2085 break 2086 } 2087 } 2088 } 2089} 2090 2091func hammerCompareAndSwapUint32Method(uaddr *uint32, count int) { 2092 addr := (*Uint32)(unsafe.Pointer(uaddr)) 2093 for i := 0; i < count; i++ { 2094 for { 2095 v := addr.Load() 2096 if addr.CompareAndSwap(v, v+1) { 2097 break 2098 } 2099 } 2100 } 2101} 2102 2103func hammerCompareAndSwapUintptr32(uaddr *uint32, count int) { 2104 // only safe when uintptr is 32-bit. 2105 // not called on 64-bit systems. 2106 addr := (*uintptr)(unsafe.Pointer(uaddr)) 2107 for i := 0; i < count; i++ { 2108 for { 2109 v := LoadUintptr(addr) 2110 if CompareAndSwapUintptr(addr, v, v+1) { 2111 break 2112 } 2113 } 2114 } 2115} 2116 2117func hammerCompareAndSwapUintptr32Method(uaddr *uint32, count int) { 2118 // only safe when uintptr is 32-bit. 2119 // not called on 64-bit systems. 2120 addr := (*Uintptr)(unsafe.Pointer(uaddr)) 2121 for i := 0; i < count; i++ { 2122 for { 2123 v := addr.Load() 2124 if addr.CompareAndSwap(v, v+1) { 2125 break 2126 } 2127 } 2128 } 2129} 2130 2131func TestHammer32(t *testing.T) { 2132 const p = 4 2133 n := 100000 2134 if testing.Short() { 2135 n = 1000 2136 } 2137 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p)) 2138 2139 for name, testf := range hammer32 { 2140 c := make(chan int) 2141 var val uint32 2142 for i := 0; i < p; i++ { 2143 go func() { 2144 defer func() { 2145 if err := recover(); err != nil { 2146 t.Error(err.(string)) 2147 } 2148 c <- 1 2149 }() 2150 testf(&val, n) 2151 }() 2152 } 2153 for i := 0; i < p; i++ { 2154 <-c 2155 } 2156 if !strings.HasPrefix(name, "Swap") && val != uint32(n)*p { 2157 t.Fatalf("%s: val=%d want %d", name, val, n*p) 2158 } 2159 } 2160} 2161 2162var hammer64 = map[string]func(*uint64, int){ 2163 "SwapInt64": hammerSwapInt64, 2164 "SwapUint64": hammerSwapUint64, 2165 "SwapUintptr": hammerSwapUintptr64, 2166 "AddInt64": hammerAddInt64, 2167 "AddUint64": hammerAddUint64, 2168 "AddUintptr": hammerAddUintptr64, 2169 "CompareAndSwapInt64": hammerCompareAndSwapInt64, 2170 "CompareAndSwapUint64": hammerCompareAndSwapUint64, 2171 "CompareAndSwapUintptr": hammerCompareAndSwapUintptr64, 2172 2173 "SwapInt64Method": hammerSwapInt64Method, 2174 "SwapUint64Method": hammerSwapUint64Method, 2175 "SwapUintptrMethod": hammerSwapUintptr64Method, 2176 "AddInt64Method": hammerAddInt64Method, 2177 "AddUint64Method": hammerAddUint64Method, 2178 "AddUintptrMethod": hammerAddUintptr64Method, 2179 "CompareAndSwapInt64Method": hammerCompareAndSwapInt64Method, 2180 "CompareAndSwapUint64Method": hammerCompareAndSwapUint64Method, 2181 "CompareAndSwapUintptrMethod": hammerCompareAndSwapUintptr64Method, 2182} 2183 2184func init() { 2185 var v uint64 = 1 << 50 2186 if uintptr(v) == 0 { 2187 // 32-bit system; clear uintptr tests 2188 delete(hammer64, "SwapUintptr") 2189 delete(hammer64, "SwapUintptrMethod") 2190 delete(hammer64, "AddUintptr") 2191 delete(hammer64, "AddUintptrMethod") 2192 delete(hammer64, "CompareAndSwapUintptr") 2193 delete(hammer64, "CompareAndSwapUintptrMethod") 2194 } 2195} 2196 2197func hammerSwapInt64(uaddr *uint64, count int) { 2198 addr := (*int64)(unsafe.Pointer(uaddr)) 2199 seed := int(uintptr(unsafe.Pointer(&count))) 2200 for i := 0; i < count; i++ { 2201 new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32 2202 old := uint64(SwapInt64(addr, int64(new))) 2203 if old>>32 != old<<32>>32 { 2204 panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old)) 2205 } 2206 } 2207} 2208 2209func hammerSwapInt64Method(uaddr *uint64, count int) { 2210 addr := (*Int64)(unsafe.Pointer(uaddr)) 2211 seed := int(uintptr(unsafe.Pointer(&count))) 2212 for i := 0; i < count; i++ { 2213 new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32 2214 old := uint64(addr.Swap(int64(new))) 2215 if old>>32 != old<<32>>32 { 2216 panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old)) 2217 } 2218 } 2219} 2220 2221func hammerSwapUint64(addr *uint64, count int) { 2222 seed := int(uintptr(unsafe.Pointer(&count))) 2223 for i := 0; i < count; i++ { 2224 new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32 2225 old := SwapUint64(addr, new) 2226 if old>>32 != old<<32>>32 { 2227 panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old)) 2228 } 2229 } 2230} 2231 2232func hammerSwapUint64Method(uaddr *uint64, count int) { 2233 addr := (*Uint64)(unsafe.Pointer(uaddr)) 2234 seed := int(uintptr(unsafe.Pointer(&count))) 2235 for i := 0; i < count; i++ { 2236 new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32 2237 old := addr.Swap(new) 2238 if old>>32 != old<<32>>32 { 2239 panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old)) 2240 } 2241 } 2242} 2243 2244const arch32 = unsafe.Sizeof(uintptr(0)) == 4 2245 2246func hammerSwapUintptr64(uaddr *uint64, count int) { 2247 // only safe when uintptr is 64-bit. 2248 // not called on 32-bit systems. 2249 if !arch32 { 2250 addr := (*uintptr)(unsafe.Pointer(uaddr)) 2251 seed := int(uintptr(unsafe.Pointer(&count))) 2252 for i := 0; i < count; i++ { 2253 new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32 2254 old := SwapUintptr(addr, new) 2255 if old>>32 != old<<32>>32 { 2256 panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old)) 2257 } 2258 } 2259 } 2260} 2261 2262func hammerSwapUintptr64Method(uaddr *uint64, count int) { 2263 // only safe when uintptr is 64-bit. 2264 // not called on 32-bit systems. 2265 if !arch32 { 2266 addr := (*Uintptr)(unsafe.Pointer(uaddr)) 2267 seed := int(uintptr(unsafe.Pointer(&count))) 2268 for i := 0; i < count; i++ { 2269 new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32 2270 old := addr.Swap(new) 2271 if old>>32 != old<<32>>32 { 2272 panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old)) 2273 } 2274 } 2275 } 2276} 2277 2278func hammerAddInt64(uaddr *uint64, count int) { 2279 addr := (*int64)(unsafe.Pointer(uaddr)) 2280 for i := 0; i < count; i++ { 2281 AddInt64(addr, 1) 2282 } 2283} 2284 2285func hammerAddInt64Method(uaddr *uint64, count int) { 2286 addr := (*Int64)(unsafe.Pointer(uaddr)) 2287 for i := 0; i < count; i++ { 2288 addr.Add(1) 2289 } 2290} 2291 2292func hammerAddUint64(addr *uint64, count int) { 2293 for i := 0; i < count; i++ { 2294 AddUint64(addr, 1) 2295 } 2296} 2297 2298func hammerAddUint64Method(uaddr *uint64, count int) { 2299 addr := (*Uint64)(unsafe.Pointer(uaddr)) 2300 for i := 0; i < count; i++ { 2301 addr.Add(1) 2302 } 2303} 2304 2305func hammerAddUintptr64(uaddr *uint64, count int) { 2306 // only safe when uintptr is 64-bit. 2307 // not called on 32-bit systems. 2308 addr := (*uintptr)(unsafe.Pointer(uaddr)) 2309 for i := 0; i < count; i++ { 2310 AddUintptr(addr, 1) 2311 } 2312} 2313 2314func hammerAddUintptr64Method(uaddr *uint64, count int) { 2315 // only safe when uintptr is 64-bit. 2316 // not called on 32-bit systems. 2317 addr := (*Uintptr)(unsafe.Pointer(uaddr)) 2318 for i := 0; i < count; i++ { 2319 addr.Add(1) 2320 } 2321} 2322 2323func hammerCompareAndSwapInt64(uaddr *uint64, count int) { 2324 addr := (*int64)(unsafe.Pointer(uaddr)) 2325 for i := 0; i < count; i++ { 2326 for { 2327 v := LoadInt64(addr) 2328 if CompareAndSwapInt64(addr, v, v+1) { 2329 break 2330 } 2331 } 2332 } 2333} 2334 2335func hammerCompareAndSwapInt64Method(uaddr *uint64, count int) { 2336 addr := (*Int64)(unsafe.Pointer(uaddr)) 2337 for i := 0; i < count; i++ { 2338 for { 2339 v := addr.Load() 2340 if addr.CompareAndSwap(v, v+1) { 2341 break 2342 } 2343 } 2344 } 2345} 2346 2347func hammerCompareAndSwapUint64(addr *uint64, count int) { 2348 for i := 0; i < count; i++ { 2349 for { 2350 v := LoadUint64(addr) 2351 if CompareAndSwapUint64(addr, v, v+1) { 2352 break 2353 } 2354 } 2355 } 2356} 2357 2358func hammerCompareAndSwapUint64Method(uaddr *uint64, count int) { 2359 addr := (*Uint64)(unsafe.Pointer(uaddr)) 2360 for i := 0; i < count; i++ { 2361 for { 2362 v := addr.Load() 2363 if addr.CompareAndSwap(v, v+1) { 2364 break 2365 } 2366 } 2367 } 2368} 2369 2370func hammerCompareAndSwapUintptr64(uaddr *uint64, count int) { 2371 // only safe when uintptr is 64-bit. 2372 // not called on 32-bit systems. 2373 addr := (*uintptr)(unsafe.Pointer(uaddr)) 2374 for i := 0; i < count; i++ { 2375 for { 2376 v := LoadUintptr(addr) 2377 if CompareAndSwapUintptr(addr, v, v+1) { 2378 break 2379 } 2380 } 2381 } 2382} 2383 2384func hammerCompareAndSwapUintptr64Method(uaddr *uint64, count int) { 2385 // only safe when uintptr is 64-bit. 2386 // not called on 32-bit systems. 2387 addr := (*Uintptr)(unsafe.Pointer(uaddr)) 2388 for i := 0; i < count; i++ { 2389 for { 2390 v := addr.Load() 2391 if addr.CompareAndSwap(v, v+1) { 2392 break 2393 } 2394 } 2395 } 2396} 2397 2398func TestHammer64(t *testing.T) { 2399 const p = 4 2400 n := 100000 2401 if testing.Short() { 2402 n = 1000 2403 } 2404 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p)) 2405 2406 for name, testf := range hammer64 { 2407 c := make(chan int) 2408 var val uint64 2409 for i := 0; i < p; i++ { 2410 go func() { 2411 defer func() { 2412 if err := recover(); err != nil { 2413 t.Error(err.(string)) 2414 } 2415 c <- 1 2416 }() 2417 testf(&val, n) 2418 }() 2419 } 2420 for i := 0; i < p; i++ { 2421 <-c 2422 } 2423 if !strings.HasPrefix(name, "Swap") && val != uint64(n)*p { 2424 t.Fatalf("%s: val=%d want %d", name, val, n*p) 2425 } 2426 } 2427} 2428 2429func hammerStoreLoadInt32(t *testing.T, paddr unsafe.Pointer) { 2430 addr := (*int32)(paddr) 2431 v := LoadInt32(addr) 2432 vlo := v & ((1 << 16) - 1) 2433 vhi := v >> 16 2434 if vlo != vhi { 2435 t.Fatalf("Int32: %#x != %#x", vlo, vhi) 2436 } 2437 new := v + 1 + 1<<16 2438 if vlo == 1e4 { 2439 new = 0 2440 } 2441 StoreInt32(addr, new) 2442} 2443 2444func hammerStoreLoadInt32Method(t *testing.T, paddr unsafe.Pointer) { 2445 addr := (*int32)(paddr) 2446 v := LoadInt32(addr) 2447 vlo := v & ((1 << 16) - 1) 2448 vhi := v >> 16 2449 if vlo != vhi { 2450 t.Fatalf("Int32: %#x != %#x", vlo, vhi) 2451 } 2452 new := v + 1 + 1<<16 2453 if vlo == 1e4 { 2454 new = 0 2455 } 2456 StoreInt32(addr, new) 2457} 2458 2459func hammerStoreLoadUint32(t *testing.T, paddr unsafe.Pointer) { 2460 addr := (*uint32)(paddr) 2461 v := LoadUint32(addr) 2462 vlo := v & ((1 << 16) - 1) 2463 vhi := v >> 16 2464 if vlo != vhi { 2465 t.Fatalf("Uint32: %#x != %#x", vlo, vhi) 2466 } 2467 new := v + 1 + 1<<16 2468 if vlo == 1e4 { 2469 new = 0 2470 } 2471 StoreUint32(addr, new) 2472} 2473 2474func hammerStoreLoadUint32Method(t *testing.T, paddr unsafe.Pointer) { 2475 addr := (*Uint32)(paddr) 2476 v := addr.Load() 2477 vlo := v & ((1 << 16) - 1) 2478 vhi := v >> 16 2479 if vlo != vhi { 2480 t.Fatalf("Uint32: %#x != %#x", vlo, vhi) 2481 } 2482 new := v + 1 + 1<<16 2483 if vlo == 1e4 { 2484 new = 0 2485 } 2486 addr.Store(new) 2487} 2488 2489func hammerStoreLoadInt64(t *testing.T, paddr unsafe.Pointer) { 2490 addr := (*int64)(paddr) 2491 v := LoadInt64(addr) 2492 vlo := v & ((1 << 32) - 1) 2493 vhi := v >> 32 2494 if vlo != vhi { 2495 t.Fatalf("Int64: %#x != %#x", vlo, vhi) 2496 } 2497 new := v + 1 + 1<<32 2498 StoreInt64(addr, new) 2499} 2500 2501func hammerStoreLoadInt64Method(t *testing.T, paddr unsafe.Pointer) { 2502 addr := (*Int64)(paddr) 2503 v := addr.Load() 2504 vlo := v & ((1 << 32) - 1) 2505 vhi := v >> 32 2506 if vlo != vhi { 2507 t.Fatalf("Int64: %#x != %#x", vlo, vhi) 2508 } 2509 new := v + 1 + 1<<32 2510 addr.Store(new) 2511} 2512 2513func hammerStoreLoadUint64(t *testing.T, paddr unsafe.Pointer) { 2514 addr := (*uint64)(paddr) 2515 v := LoadUint64(addr) 2516 vlo := v & ((1 << 32) - 1) 2517 vhi := v >> 32 2518 if vlo != vhi { 2519 t.Fatalf("Uint64: %#x != %#x", vlo, vhi) 2520 } 2521 new := v + 1 + 1<<32 2522 StoreUint64(addr, new) 2523} 2524 2525func hammerStoreLoadUint64Method(t *testing.T, paddr unsafe.Pointer) { 2526 addr := (*Uint64)(paddr) 2527 v := addr.Load() 2528 vlo := v & ((1 << 32) - 1) 2529 vhi := v >> 32 2530 if vlo != vhi { 2531 t.Fatalf("Uint64: %#x != %#x", vlo, vhi) 2532 } 2533 new := v + 1 + 1<<32 2534 addr.Store(new) 2535} 2536 2537func hammerStoreLoadUintptr(t *testing.T, paddr unsafe.Pointer) { 2538 addr := (*uintptr)(paddr) 2539 v := LoadUintptr(addr) 2540 new := v 2541 if arch32 { 2542 vlo := v & ((1 << 16) - 1) 2543 vhi := v >> 16 2544 if vlo != vhi { 2545 t.Fatalf("Uintptr: %#x != %#x", vlo, vhi) 2546 } 2547 new = v + 1 + 1<<16 2548 if vlo == 1e4 { 2549 new = 0 2550 } 2551 } else { 2552 vlo := v & ((1 << 32) - 1) 2553 vhi := v >> 32 2554 if vlo != vhi { 2555 t.Fatalf("Uintptr: %#x != %#x", vlo, vhi) 2556 } 2557 inc := uint64(1 + 1<<32) 2558 new = v + uintptr(inc) 2559 } 2560 StoreUintptr(addr, new) 2561} 2562 2563//go:nocheckptr 2564func hammerStoreLoadUintptrMethod(t *testing.T, paddr unsafe.Pointer) { 2565 addr := (*Uintptr)(paddr) 2566 v := addr.Load() 2567 new := v 2568 if arch32 { 2569 vlo := v & ((1 << 16) - 1) 2570 vhi := v >> 16 2571 if vlo != vhi { 2572 t.Fatalf("Uintptr: %#x != %#x", vlo, vhi) 2573 } 2574 new = v + 1 + 1<<16 2575 if vlo == 1e4 { 2576 new = 0 2577 } 2578 } else { 2579 vlo := v & ((1 << 32) - 1) 2580 vhi := v >> 32 2581 if vlo != vhi { 2582 t.Fatalf("Uintptr: %#x != %#x", vlo, vhi) 2583 } 2584 inc := uint64(1 + 1<<32) 2585 new = v + uintptr(inc) 2586 } 2587 addr.Store(new) 2588} 2589 2590// This code is just testing that LoadPointer/StorePointer operate 2591// atomically; it's not actually calculating pointers. 2592// 2593//go:nocheckptr 2594func hammerStoreLoadPointer(t *testing.T, paddr unsafe.Pointer) { 2595 addr := (*unsafe.Pointer)(paddr) 2596 v := uintptr(LoadPointer(addr)) 2597 new := v 2598 if arch32 { 2599 vlo := v & ((1 << 16) - 1) 2600 vhi := v >> 16 2601 if vlo != vhi { 2602 t.Fatalf("Pointer: %#x != %#x", vlo, vhi) 2603 } 2604 new = v + 1 + 1<<16 2605 if vlo == 1e4 { 2606 new = 0 2607 } 2608 } else { 2609 vlo := v & ((1 << 32) - 1) 2610 vhi := v >> 32 2611 if vlo != vhi { 2612 t.Fatalf("Pointer: %#x != %#x", vlo, vhi) 2613 } 2614 inc := uint64(1 + 1<<32) 2615 new = v + uintptr(inc) 2616 } 2617 StorePointer(addr, unsafe.Pointer(new)) 2618} 2619 2620// This code is just testing that LoadPointer/StorePointer operate 2621// atomically; it's not actually calculating pointers. 2622// 2623//go:nocheckptr 2624func hammerStoreLoadPointerMethod(t *testing.T, paddr unsafe.Pointer) { 2625 addr := (*Pointer[byte])(paddr) 2626 v := uintptr(unsafe.Pointer(addr.Load())) 2627 new := v 2628 if arch32 { 2629 vlo := v & ((1 << 16) - 1) 2630 vhi := v >> 16 2631 if vlo != vhi { 2632 t.Fatalf("Pointer: %#x != %#x", vlo, vhi) 2633 } 2634 new = v + 1 + 1<<16 2635 if vlo == 1e4 { 2636 new = 0 2637 } 2638 } else { 2639 vlo := v & ((1 << 32) - 1) 2640 vhi := v >> 32 2641 if vlo != vhi { 2642 t.Fatalf("Pointer: %#x != %#x", vlo, vhi) 2643 } 2644 inc := uint64(1 + 1<<32) 2645 new = v + uintptr(inc) 2646 } 2647 addr.Store((*byte)(unsafe.Pointer(new))) 2648} 2649 2650func TestHammerStoreLoad(t *testing.T) { 2651 tests := []func(*testing.T, unsafe.Pointer){ 2652 hammerStoreLoadInt32, hammerStoreLoadUint32, 2653 hammerStoreLoadUintptr, hammerStoreLoadPointer, 2654 hammerStoreLoadInt32Method, hammerStoreLoadUint32Method, 2655 hammerStoreLoadUintptrMethod, hammerStoreLoadPointerMethod, 2656 hammerStoreLoadInt64, hammerStoreLoadUint64, 2657 hammerStoreLoadInt64Method, hammerStoreLoadUint64Method, 2658 } 2659 n := int(1e6) 2660 if testing.Short() { 2661 n = int(1e4) 2662 } 2663 const procs = 8 2664 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(procs)) 2665 // Disable the GC because hammerStoreLoadPointer invokes 2666 // write barriers on values that aren't real pointers. 2667 defer debug.SetGCPercent(debug.SetGCPercent(-1)) 2668 // Ensure any in-progress GC is finished. 2669 runtime.GC() 2670 for _, tt := range tests { 2671 c := make(chan int) 2672 var val uint64 2673 for p := 0; p < procs; p++ { 2674 go func() { 2675 for i := 0; i < n; i++ { 2676 tt(t, unsafe.Pointer(&val)) 2677 } 2678 c <- 1 2679 }() 2680 } 2681 for p := 0; p < procs; p++ { 2682 <-c 2683 } 2684 } 2685} 2686 2687func TestStoreLoadSeqCst32(t *testing.T) { 2688 if runtime.NumCPU() == 1 { 2689 t.Skipf("Skipping test on %v processor machine", runtime.NumCPU()) 2690 } 2691 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) 2692 N := int32(1e3) 2693 if testing.Short() { 2694 N = int32(1e2) 2695 } 2696 c := make(chan bool, 2) 2697 X := [2]int32{} 2698 ack := [2][3]int32{{-1, -1, -1}, {-1, -1, -1}} 2699 for p := 0; p < 2; p++ { 2700 go func(me int) { 2701 he := 1 - me 2702 for i := int32(1); i < N; i++ { 2703 StoreInt32(&X[me], i) 2704 my := LoadInt32(&X[he]) 2705 StoreInt32(&ack[me][i%3], my) 2706 for w := 1; LoadInt32(&ack[he][i%3]) == -1; w++ { 2707 if w%1000 == 0 { 2708 runtime.Gosched() 2709 } 2710 } 2711 his := LoadInt32(&ack[he][i%3]) 2712 if (my != i && my != i-1) || (his != i && his != i-1) { 2713 t.Errorf("invalid values: %d/%d (%d)", my, his, i) 2714 break 2715 } 2716 if my != i && his != i { 2717 t.Errorf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i) 2718 break 2719 } 2720 StoreInt32(&ack[me][(i-1)%3], -1) 2721 } 2722 c <- true 2723 }(p) 2724 } 2725 <-c 2726 <-c 2727} 2728 2729func TestStoreLoadSeqCst64(t *testing.T) { 2730 if runtime.NumCPU() == 1 { 2731 t.Skipf("Skipping test on %v processor machine", runtime.NumCPU()) 2732 } 2733 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) 2734 N := int64(1e3) 2735 if testing.Short() { 2736 N = int64(1e2) 2737 } 2738 c := make(chan bool, 2) 2739 X := [2]int64{} 2740 ack := [2][3]int64{{-1, -1, -1}, {-1, -1, -1}} 2741 for p := 0; p < 2; p++ { 2742 go func(me int) { 2743 he := 1 - me 2744 for i := int64(1); i < N; i++ { 2745 StoreInt64(&X[me], i) 2746 my := LoadInt64(&X[he]) 2747 StoreInt64(&ack[me][i%3], my) 2748 for w := 1; LoadInt64(&ack[he][i%3]) == -1; w++ { 2749 if w%1000 == 0 { 2750 runtime.Gosched() 2751 } 2752 } 2753 his := LoadInt64(&ack[he][i%3]) 2754 if (my != i && my != i-1) || (his != i && his != i-1) { 2755 t.Errorf("invalid values: %d/%d (%d)", my, his, i) 2756 break 2757 } 2758 if my != i && his != i { 2759 t.Errorf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i) 2760 break 2761 } 2762 StoreInt64(&ack[me][(i-1)%3], -1) 2763 } 2764 c <- true 2765 }(p) 2766 } 2767 <-c 2768 <-c 2769} 2770 2771func TestStoreLoadRelAcq32(t *testing.T) { 2772 if runtime.NumCPU() == 1 { 2773 t.Skipf("Skipping test on %v processor machine", runtime.NumCPU()) 2774 } 2775 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) 2776 N := int32(1e3) 2777 if testing.Short() { 2778 N = int32(1e2) 2779 } 2780 c := make(chan bool, 2) 2781 type Data struct { 2782 signal int32 2783 pad1 [128]int8 2784 data1 int32 2785 pad2 [128]int8 2786 data2 float32 2787 } 2788 var X Data 2789 for p := int32(0); p < 2; p++ { 2790 go func(p int32) { 2791 for i := int32(1); i < N; i++ { 2792 if (i+p)%2 == 0 { 2793 X.data1 = i 2794 X.data2 = float32(i) 2795 StoreInt32(&X.signal, i) 2796 } else { 2797 for w := 1; LoadInt32(&X.signal) != i; w++ { 2798 if w%1000 == 0 { 2799 runtime.Gosched() 2800 } 2801 } 2802 d1 := X.data1 2803 d2 := X.data2 2804 if d1 != i || d2 != float32(i) { 2805 t.Errorf("incorrect data: %d/%g (%d)", d1, d2, i) 2806 break 2807 } 2808 } 2809 } 2810 c <- true 2811 }(p) 2812 } 2813 <-c 2814 <-c 2815} 2816 2817func TestStoreLoadRelAcq64(t *testing.T) { 2818 if runtime.NumCPU() == 1 { 2819 t.Skipf("Skipping test on %v processor machine", runtime.NumCPU()) 2820 } 2821 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) 2822 N := int64(1e3) 2823 if testing.Short() { 2824 N = int64(1e2) 2825 } 2826 c := make(chan bool, 2) 2827 type Data struct { 2828 signal int64 2829 pad1 [128]int8 2830 data1 int64 2831 pad2 [128]int8 2832 data2 float64 2833 } 2834 var X Data 2835 for p := int64(0); p < 2; p++ { 2836 go func(p int64) { 2837 for i := int64(1); i < N; i++ { 2838 if (i+p)%2 == 0 { 2839 X.data1 = i 2840 X.data2 = float64(i) 2841 StoreInt64(&X.signal, i) 2842 } else { 2843 for w := 1; LoadInt64(&X.signal) != i; w++ { 2844 if w%1000 == 0 { 2845 runtime.Gosched() 2846 } 2847 } 2848 d1 := X.data1 2849 d2 := X.data2 2850 if d1 != i || d2 != float64(i) { 2851 t.Errorf("incorrect data: %d/%g (%d)", d1, d2, i) 2852 break 2853 } 2854 } 2855 } 2856 c <- true 2857 }(p) 2858 } 2859 <-c 2860 <-c 2861} 2862 2863func shouldPanic(t *testing.T, name string, f func()) { 2864 defer func() { 2865 // Check that all GC maps are sane. 2866 runtime.GC() 2867 2868 err := recover() 2869 want := "unaligned 64-bit atomic operation" 2870 if err == nil { 2871 t.Errorf("%s did not panic", name) 2872 } else if s, _ := err.(string); s != want { 2873 t.Errorf("%s: wanted panic %q, got %q", name, want, err) 2874 } 2875 }() 2876 f() 2877} 2878 2879func TestUnaligned64(t *testing.T) { 2880 // Unaligned 64-bit atomics on 32-bit systems are 2881 // a continual source of pain. Test that on 32-bit systems they crash 2882 // instead of failing silently. 2883 if !arch32 { 2884 t.Skip("test only runs on 32-bit systems") 2885 } 2886 2887 x := make([]uint32, 4) 2888 p := (*uint64)(unsafe.Pointer(&x[1])) // misaligned 2889 2890 shouldPanic(t, "LoadUint64", func() { LoadUint64(p) }) 2891 shouldPanic(t, "LoadUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).Load() }) 2892 shouldPanic(t, "StoreUint64", func() { StoreUint64(p, 1) }) 2893 shouldPanic(t, "StoreUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).Store(1) }) 2894 shouldPanic(t, "CompareAndSwapUint64", func() { CompareAndSwapUint64(p, 1, 2) }) 2895 shouldPanic(t, "CompareAndSwapUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).CompareAndSwap(1, 2) }) 2896 shouldPanic(t, "AddUint64", func() { AddUint64(p, 3) }) 2897 shouldPanic(t, "AddUint64Method", func() { (*Uint64)(unsafe.Pointer(p)).Add(3) }) 2898} 2899 2900func TestAutoAligned64(t *testing.T) { 2901 var signed struct { 2902 _ uint32 2903 i Int64 2904 } 2905 if o := reflect.TypeOf(&signed).Elem().Field(1).Offset; o != 8 { 2906 t.Fatalf("Int64 offset = %d, want 8", o) 2907 } 2908 if p := reflect.ValueOf(&signed).Elem().Field(1).Addr().Pointer(); p&7 != 0 { 2909 t.Fatalf("Int64 pointer = %#x, want 8-aligned", p) 2910 } 2911 2912 var unsigned struct { 2913 _ uint32 2914 i Uint64 2915 } 2916 if o := reflect.TypeOf(&unsigned).Elem().Field(1).Offset; o != 8 { 2917 t.Fatalf("Uint64 offset = %d, want 8", o) 2918 } 2919 if p := reflect.ValueOf(&unsigned).Elem().Field(1).Addr().Pointer(); p&7 != 0 { 2920 t.Fatalf("Int64 pointer = %#x, want 8-aligned", p) 2921 } 2922} 2923 2924func TestNilDeref(t *testing.T) { 2925 funcs := [...]func(){ 2926 func() { CompareAndSwapInt32(nil, 0, 0) }, 2927 func() { (*Int32)(nil).CompareAndSwap(0, 0) }, 2928 func() { CompareAndSwapInt64(nil, 0, 0) }, 2929 func() { (*Int64)(nil).CompareAndSwap(0, 0) }, 2930 func() { CompareAndSwapUint32(nil, 0, 0) }, 2931 func() { (*Uint32)(nil).CompareAndSwap(0, 0) }, 2932 func() { CompareAndSwapUint64(nil, 0, 0) }, 2933 func() { (*Uint64)(nil).CompareAndSwap(0, 0) }, 2934 func() { CompareAndSwapUintptr(nil, 0, 0) }, 2935 func() { (*Uintptr)(nil).CompareAndSwap(0, 0) }, 2936 func() { CompareAndSwapPointer(nil, nil, nil) }, 2937 func() { (*Pointer[byte])(nil).CompareAndSwap(nil, nil) }, 2938 func() { SwapInt32(nil, 0) }, 2939 func() { (*Int32)(nil).Swap(0) }, 2940 func() { SwapUint32(nil, 0) }, 2941 func() { (*Uint32)(nil).Swap(0) }, 2942 func() { SwapInt64(nil, 0) }, 2943 func() { (*Int64)(nil).Swap(0) }, 2944 func() { SwapUint64(nil, 0) }, 2945 func() { (*Uint64)(nil).Swap(0) }, 2946 func() { SwapUintptr(nil, 0) }, 2947 func() { (*Uintptr)(nil).Swap(0) }, 2948 func() { SwapPointer(nil, nil) }, 2949 func() { (*Pointer[byte])(nil).Swap(nil) }, 2950 func() { AddInt32(nil, 0) }, 2951 func() { (*Int32)(nil).Add(0) }, 2952 func() { AddUint32(nil, 0) }, 2953 func() { (*Uint32)(nil).Add(0) }, 2954 func() { AddInt64(nil, 0) }, 2955 func() { (*Int64)(nil).Add(0) }, 2956 func() { AddUint64(nil, 0) }, 2957 func() { (*Uint64)(nil).Add(0) }, 2958 func() { AddUintptr(nil, 0) }, 2959 func() { (*Uintptr)(nil).Add(0) }, 2960 func() { LoadInt32(nil) }, 2961 func() { (*Int32)(nil).Load() }, 2962 func() { LoadInt64(nil) }, 2963 func() { (*Int64)(nil).Load() }, 2964 func() { LoadUint32(nil) }, 2965 func() { (*Uint32)(nil).Load() }, 2966 func() { LoadUint64(nil) }, 2967 func() { (*Uint64)(nil).Load() }, 2968 func() { LoadUintptr(nil) }, 2969 func() { (*Uintptr)(nil).Load() }, 2970 func() { LoadPointer(nil) }, 2971 func() { (*Pointer[byte])(nil).Load() }, 2972 func() { StoreInt32(nil, 0) }, 2973 func() { (*Int32)(nil).Store(0) }, 2974 func() { StoreInt64(nil, 0) }, 2975 func() { (*Int64)(nil).Store(0) }, 2976 func() { StoreUint32(nil, 0) }, 2977 func() { (*Uint32)(nil).Store(0) }, 2978 func() { StoreUint64(nil, 0) }, 2979 func() { (*Uint64)(nil).Store(0) }, 2980 func() { StoreUintptr(nil, 0) }, 2981 func() { (*Uintptr)(nil).Store(0) }, 2982 func() { StorePointer(nil, nil) }, 2983 func() { (*Pointer[byte])(nil).Store(nil) }, 2984 } 2985 for _, f := range funcs { 2986 func() { 2987 defer func() { 2988 runtime.GC() 2989 recover() 2990 }() 2991 f() 2992 }() 2993 } 2994} 2995 2996// Test that this compiles. 2997// When atomic.Pointer used _ [0]T, it did not. 2998type List struct { 2999 Next Pointer[List] 3000} 3001