diff options
Diffstat (limited to 'src/pkg/sync/atomic/atomic_test.go')
-rw-r--r-- | src/pkg/sync/atomic/atomic_test.go | 1509 |
1 files changed, 0 insertions, 1509 deletions
diff --git a/src/pkg/sync/atomic/atomic_test.go b/src/pkg/sync/atomic/atomic_test.go deleted file mode 100644 index a5f44f70d..000000000 --- a/src/pkg/sync/atomic/atomic_test.go +++ /dev/null @@ -1,1509 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package atomic_test - -import ( - "fmt" - "runtime" - "strings" - . "sync/atomic" - "testing" - "unsafe" -) - -// Tests of correct behavior, without contention. -// (Does the function work as advertised?) -// -// Test that the Add functions add correctly. -// Test that the CompareAndSwap functions actually -// do the comparison and the swap correctly. -// -// The loop over power-of-two values is meant to -// ensure that the operations apply to the full word size. -// The struct fields x.before and x.after check that the -// operations do not extend past the full word size. - -const ( - magic32 = 0xdedbeef - magic64 = 0xdeddeadbeefbeef -) - -// Do the 64-bit functions panic? If so, don't bother testing. -var test64err = func() (err interface{}) { - defer func() { - err = recover() - }() - var x int64 - AddInt64(&x, 1) - return nil -}() - -func TestSwapInt32(t *testing.T) { - var x struct { - before int32 - i int32 - after int32 - } - x.before = magic32 - x.after = magic32 - var j int32 - for delta := int32(1); delta+delta > delta; delta += delta { - k := SwapInt32(&x.i, delta) - if x.i != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - j = delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestSwapUint32(t *testing.T) { - var x struct { - before uint32 - i uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - var j uint32 - for delta := uint32(1); delta+delta > delta; delta += delta { - k := SwapUint32(&x.i, delta) - if x.i != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - j = delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestSwapInt64(t *testing.T) { - if test64err != nil { - t.Skipf("Skipping 64-bit tests: %v", test64err) - } - var x struct { - before int64 - i int64 - after int64 - } - x.before = magic64 - x.after = magic64 - var j int64 - for delta := int64(1); delta+delta > delta; delta += delta { - k := SwapInt64(&x.i, delta) - if x.i != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - j = delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64)) - } -} - -func TestSwapUint64(t *testing.T) { - if test64err != nil { - t.Skipf("Skipping 64-bit tests: %v", test64err) - } - var x struct { - before uint64 - i uint64 - after uint64 - } - x.before = magic64 - x.after = magic64 - var j uint64 - for delta := uint64(1); delta+delta > delta; delta += delta { - k := SwapUint64(&x.i, delta) - if x.i != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - j = delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64)) - } -} - -func TestSwapUintptr(t *testing.T) { - var x struct { - before uintptr - i uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - var j uintptr - for delta := uintptr(1); delta+delta > delta; delta += delta { - k := SwapUintptr(&x.i, delta) - if x.i != delta || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - j = delta - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestSwapPointer(t *testing.T) { - var x struct { - before uintptr - i unsafe.Pointer - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - var j uintptr - for delta := uintptr(1); delta+delta > delta; delta += delta { - k := SwapPointer(&x.i, unsafe.Pointer(delta)) - if uintptr(x.i) != delta || uintptr(k) != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - j = delta - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestAddInt32(t *testing.T) { - var x struct { - before int32 - i int32 - after int32 - } - x.before = magic32 - x.after = magic32 - var j int32 - for delta := int32(1); delta+delta > delta; delta += delta { - k := AddInt32(&x.i, delta) - j += delta - if x.i != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestAddUint32(t *testing.T) { - var x struct { - before uint32 - i uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - var j uint32 - for delta := uint32(1); delta+delta > delta; delta += delta { - k := AddUint32(&x.i, delta) - j += delta - if x.i != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestAddInt64(t *testing.T) { - if test64err != nil { - t.Skipf("Skipping 64-bit tests: %v", test64err) - } - var x struct { - before int64 - i int64 - after int64 - } - x.before = magic64 - x.after = magic64 - var j int64 - for delta := int64(1); delta+delta > delta; delta += delta { - k := AddInt64(&x.i, delta) - j += delta - if x.i != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, int64(magic64), int64(magic64)) - } -} - -func TestAddUint64(t *testing.T) { - if test64err != nil { - t.Skipf("Skipping 64-bit tests: %v", test64err) - } - var x struct { - before uint64 - i uint64 - after uint64 - } - x.before = magic64 - x.after = magic64 - var j uint64 - for delta := uint64(1); delta+delta > delta; delta += delta { - k := AddUint64(&x.i, delta) - j += delta - if x.i != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64)) - } -} - -func TestAddUintptr(t *testing.T) { - var x struct { - before uintptr - i uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - var j uintptr - for delta := uintptr(1); delta+delta > delta; delta += delta { - k := AddUintptr(&x.i, delta) - j += delta - if x.i != j || k != j { - t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestCompareAndSwapInt32(t *testing.T) { - var x struct { - before int32 - i int32 - after int32 - } - x.before = magic32 - x.after = magic32 - for val := int32(1); val+val > val; val += val { - x.i = val - if !CompareAndSwapInt32(&x.i, val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - x.i = val + 1 - if CompareAndSwapInt32(&x.i, val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestCompareAndSwapUint32(t *testing.T) { - var x struct { - before uint32 - i uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - for val := uint32(1); val+val > val; val += val { - x.i = val - if !CompareAndSwapUint32(&x.i, val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - x.i = val + 1 - if CompareAndSwapUint32(&x.i, val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestCompareAndSwapInt64(t *testing.T) { - if test64err != nil { - t.Skipf("Skipping 64-bit tests: %v", test64err) - } - var x struct { - before int64 - i int64 - after int64 - } - x.before = magic64 - x.after = magic64 - for val := int64(1); val+val > val; val += val { - x.i = val - if !CompareAndSwapInt64(&x.i, val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - x.i = val + 1 - if CompareAndSwapInt64(&x.i, val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64)) - } -} - -func testCompareAndSwapUint64(t *testing.T, cas func(*uint64, uint64, uint64) bool) { - if test64err != nil { - t.Skipf("Skipping 64-bit tests: %v", test64err) - } - var x struct { - before uint64 - i uint64 - after uint64 - } - x.before = magic64 - x.after = magic64 - for val := uint64(1); val+val > val; val += val { - x.i = val - if !cas(&x.i, val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - x.i = val + 1 - if cas(&x.i, val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64)) - } -} - -func TestCompareAndSwapUint64(t *testing.T) { - testCompareAndSwapUint64(t, CompareAndSwapUint64) -} - -func TestCompareAndSwapUintptr(t *testing.T) { - var x struct { - before uintptr - i uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - for val := uintptr(1); val+val > val; val += val { - x.i = val - if !CompareAndSwapUintptr(&x.i, val, val+1) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - x.i = val + 1 - if CompareAndSwapUintptr(&x.i, val, val+2) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i != val+1 { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestCompareAndSwapPointer(t *testing.T) { - var x struct { - before uintptr - i unsafe.Pointer - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - for val := uintptr(1); val+val > val; val += val { - x.i = unsafe.Pointer(val) - if !CompareAndSwapPointer(&x.i, unsafe.Pointer(val), unsafe.Pointer(val+1)) { - t.Fatalf("should have swapped %#x %#x", val, val+1) - } - if x.i != unsafe.Pointer(val+1) { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - x.i = unsafe.Pointer(val + 1) - if CompareAndSwapPointer(&x.i, unsafe.Pointer(val), unsafe.Pointer(val+2)) { - t.Fatalf("should not have swapped %#x %#x", val, val+2) - } - if x.i != unsafe.Pointer(val+1) { - t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1) - } - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestLoadInt32(t *testing.T) { - var x struct { - before int32 - i int32 - after int32 - } - x.before = magic32 - x.after = magic32 - for delta := int32(1); delta+delta > delta; delta += delta { - k := LoadInt32(&x.i) - if k != x.i { - t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) - } - x.i += delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestLoadUint32(t *testing.T) { - var x struct { - before uint32 - i uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - for delta := uint32(1); delta+delta > delta; delta += delta { - k := LoadUint32(&x.i) - if k != x.i { - t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) - } - x.i += delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestLoadInt64(t *testing.T) { - if test64err != nil { - t.Skipf("Skipping 64-bit tests: %v", test64err) - } - var x struct { - before int64 - i int64 - after int64 - } - x.before = magic64 - x.after = magic64 - for delta := int64(1); delta+delta > delta; delta += delta { - k := LoadInt64(&x.i) - if k != x.i { - t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) - } - x.i += delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64)) - } -} - -func TestLoadUint64(t *testing.T) { - if test64err != nil { - t.Skipf("Skipping 64-bit tests: %v", test64err) - } - var x struct { - before uint64 - i uint64 - after uint64 - } - x.before = magic64 - x.after = magic64 - for delta := uint64(1); delta+delta > delta; delta += delta { - k := LoadUint64(&x.i) - if k != x.i { - t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) - } - x.i += delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64)) - } -} - -func TestLoadUintptr(t *testing.T) { - var x struct { - before uintptr - i uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - for delta := uintptr(1); delta+delta > delta; delta += delta { - k := LoadUintptr(&x.i) - if k != x.i { - t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) - } - x.i += delta - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestLoadPointer(t *testing.T) { - var x struct { - before uintptr - i unsafe.Pointer - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - for delta := uintptr(1); delta+delta > delta; delta += delta { - k := LoadPointer(&x.i) - if k != x.i { - t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k) - } - x.i = unsafe.Pointer(uintptr(x.i) + delta) - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestStoreInt32(t *testing.T) { - var x struct { - before int32 - i int32 - after int32 - } - x.before = magic32 - x.after = magic32 - v := int32(0) - for delta := int32(1); delta+delta > delta; delta += delta { - StoreInt32(&x.i, v) - if x.i != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) - } - v += delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestStoreUint32(t *testing.T) { - var x struct { - before uint32 - i uint32 - after uint32 - } - x.before = magic32 - x.after = magic32 - v := uint32(0) - for delta := uint32(1); delta+delta > delta; delta += delta { - StoreUint32(&x.i, v) - if x.i != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) - } - v += delta - } - if x.before != magic32 || x.after != magic32 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32) - } -} - -func TestStoreInt64(t *testing.T) { - if test64err != nil { - t.Skipf("Skipping 64-bit tests: %v", test64err) - } - var x struct { - before int64 - i int64 - after int64 - } - x.before = magic64 - x.after = magic64 - v := int64(0) - for delta := int64(1); delta+delta > delta; delta += delta { - StoreInt64(&x.i, v) - if x.i != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) - } - v += delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64)) - } -} - -func TestStoreUint64(t *testing.T) { - if test64err != nil { - t.Skipf("Skipping 64-bit tests: %v", test64err) - } - var x struct { - before uint64 - i uint64 - after uint64 - } - x.before = magic64 - x.after = magic64 - v := uint64(0) - for delta := uint64(1); delta+delta > delta; delta += delta { - StoreUint64(&x.i, v) - if x.i != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) - } - v += delta - } - if x.before != magic64 || x.after != magic64 { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64)) - } -} - -func TestStoreUintptr(t *testing.T) { - var x struct { - before uintptr - i uintptr - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - v := uintptr(0) - for delta := uintptr(1); delta+delta > delta; delta += delta { - StoreUintptr(&x.i, v) - if x.i != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) - } - v += delta - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -func TestStorePointer(t *testing.T) { - var x struct { - before uintptr - i unsafe.Pointer - after uintptr - } - var m uint64 = magic64 - magicptr := uintptr(m) - x.before = magicptr - x.after = magicptr - v := unsafe.Pointer(uintptr(0)) - for delta := uintptr(1); delta+delta > delta; delta += delta { - StorePointer(&x.i, unsafe.Pointer(v)) - if x.i != v { - t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v) - } - v = unsafe.Pointer(uintptr(v) + delta) - } - if x.before != magicptr || x.after != magicptr { - t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr) - } -} - -// Tests of correct behavior, with contention. -// (Is the function atomic?) -// -// For each function, we write a "hammer" function that repeatedly -// uses the atomic operation to add 1 to a value. After running -// multiple hammers in parallel, check that we end with the correct -// total. -// Swap can't add 1, so it uses a different scheme. -// The functions repeatedly generate a pseudo-random number such that -// low bits are equal to high bits, swap, check that the old value -// has low and high bits equal. - -var hammer32 = map[string]func(*uint32, int){ - "SwapInt32": hammerSwapInt32, - "SwapUint32": hammerSwapUint32, - "SwapUintptr": hammerSwapUintptr32, - "SwapPointer": hammerSwapPointer32, - "AddInt32": hammerAddInt32, - "AddUint32": hammerAddUint32, - "AddUintptr": hammerAddUintptr32, - "CompareAndSwapInt32": hammerCompareAndSwapInt32, - "CompareAndSwapUint32": hammerCompareAndSwapUint32, - "CompareAndSwapUintptr": hammerCompareAndSwapUintptr32, - "CompareAndSwapPointer": hammerCompareAndSwapPointer32, -} - -func init() { - var v uint64 = 1 << 50 - if uintptr(v) != 0 { - // 64-bit system; clear uintptr tests - delete(hammer32, "SwapUintptr") - delete(hammer32, "SwapPointer") - delete(hammer32, "AddUintptr") - delete(hammer32, "CompareAndSwapUintptr") - delete(hammer32, "CompareAndSwapPointer") - } -} - -func hammerSwapInt32(uaddr *uint32, count int) { - addr := (*int32)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16 - old := uint32(SwapInt32(addr, int32(new))) - if old>>16 != old<<16>>16 { - panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old)) - } - } -} - -func hammerSwapUint32(addr *uint32, count int) { - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16 - old := SwapUint32(addr, new) - if old>>16 != old<<16>>16 { - panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old)) - } - } -} - -func hammerSwapUintptr32(uaddr *uint32, count int) { - // only safe when uintptr is 32-bit. - // not called on 64-bit systems. - addr := (*uintptr)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16 - old := SwapUintptr(addr, new) - if old>>16 != old<<16>>16 { - panic(fmt.Sprintf("SwapUintptr is not atomic: %#08x", old)) - } - } -} - -func hammerSwapPointer32(uaddr *uint32, count int) { - // only safe when uintptr is 32-bit. - // not called on 64-bit systems. - addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16 - old := uintptr(SwapPointer(addr, unsafe.Pointer(new))) - if old>>16 != old<<16>>16 { - panic(fmt.Sprintf("SwapPointer is not atomic: %#08x", old)) - } - } -} - -func hammerAddInt32(uaddr *uint32, count int) { - addr := (*int32)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - AddInt32(addr, 1) - } -} - -func hammerAddUint32(addr *uint32, count int) { - for i := 0; i < count; i++ { - AddUint32(addr, 1) - } -} - -func hammerAddUintptr32(uaddr *uint32, count int) { - // only safe when uintptr is 32-bit. - // not called on 64-bit systems. - addr := (*uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - AddUintptr(addr, 1) - } -} - -func hammerCompareAndSwapInt32(uaddr *uint32, count int) { - addr := (*int32)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := *addr - if CompareAndSwapInt32(addr, v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUint32(addr *uint32, count int) { - for i := 0; i < count; i++ { - for { - v := *addr - if CompareAndSwapUint32(addr, v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUintptr32(uaddr *uint32, count int) { - // only safe when uintptr is 32-bit. - // not called on 64-bit systems. - addr := (*uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := *addr - if CompareAndSwapUintptr(addr, v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapPointer32(uaddr *uint32, count int) { - // only safe when uintptr is 32-bit. - // not called on 64-bit systems. - addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := *addr - if CompareAndSwapPointer(addr, v, unsafe.Pointer(uintptr(v)+1)) { - break - } - } - } -} - -func TestHammer32(t *testing.T) { - const p = 4 - n := 100000 - if testing.Short() { - n = 1000 - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p)) - - for name, testf := range hammer32 { - c := make(chan int) - var val uint32 - for i := 0; i < p; i++ { - go func() { - defer func() { - if err := recover(); err != nil { - t.Error(err.(string)) - } - c <- 1 - }() - testf(&val, n) - }() - } - for i := 0; i < p; i++ { - <-c - } - if !strings.HasPrefix(name, "Swap") && val != uint32(n)*p { - t.Fatalf("%s: val=%d want %d", name, val, n*p) - } - } -} - -var hammer64 = map[string]func(*uint64, int){ - "SwapInt64": hammerSwapInt64, - "SwapUint64": hammerSwapUint64, - "SwapUintptr": hammerSwapUintptr64, - "SwapPointer": hammerSwapPointer64, - "AddInt64": hammerAddInt64, - "AddUint64": hammerAddUint64, - "AddUintptr": hammerAddUintptr64, - "CompareAndSwapInt64": hammerCompareAndSwapInt64, - "CompareAndSwapUint64": hammerCompareAndSwapUint64, - "CompareAndSwapUintptr": hammerCompareAndSwapUintptr64, - "CompareAndSwapPointer": hammerCompareAndSwapPointer64, -} - -func init() { - var v uint64 = 1 << 50 - if uintptr(v) == 0 { - // 32-bit system; clear uintptr tests - delete(hammer64, "SwapUintptr") - delete(hammer64, "SwapPointer") - delete(hammer64, "AddUintptr") - delete(hammer64, "CompareAndSwapUintptr") - delete(hammer64, "CompareAndSwapPointer") - } -} - -func hammerSwapInt64(uaddr *uint64, count int) { - addr := (*int64)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32 - old := uint64(SwapInt64(addr, int64(new))) - if old>>32 != old<<32>>32 { - panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old)) - } - } -} - -func hammerSwapUint64(addr *uint64, count int) { - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32 - old := SwapUint64(addr, new) - if old>>32 != old<<32>>32 { - panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old)) - } - } -} - -func hammerSwapUintptr64(uaddr *uint64, count int) { - // only safe when uintptr is 64-bit. - // not called on 32-bit systems. - addr := (*uintptr)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32 - old := SwapUintptr(addr, new) - if old>>32 != old<<32>>32 { - panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old)) - } - } -} - -func hammerSwapPointer64(uaddr *uint64, count int) { - // only safe when uintptr is 64-bit. - // not called on 32-bit systems. - addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr)) - seed := int(uintptr(unsafe.Pointer(&count))) - for i := 0; i < count; i++ { - new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32 - old := uintptr(SwapPointer(addr, unsafe.Pointer(new))) - if old>>32 != old<<32>>32 { - panic(fmt.Sprintf("SwapPointer is not atomic: %v", old)) - } - } -} - -func hammerAddInt64(uaddr *uint64, count int) { - addr := (*int64)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - AddInt64(addr, 1) - } -} - -func hammerAddUint64(addr *uint64, count int) { - for i := 0; i < count; i++ { - AddUint64(addr, 1) - } -} - -func hammerAddUintptr64(uaddr *uint64, count int) { - // only safe when uintptr is 64-bit. - // not called on 32-bit systems. - addr := (*uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - AddUintptr(addr, 1) - } -} - -func hammerCompareAndSwapInt64(uaddr *uint64, count int) { - addr := (*int64)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := *addr - if CompareAndSwapInt64(addr, v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUint64(addr *uint64, count int) { - for i := 0; i < count; i++ { - for { - v := *addr - if CompareAndSwapUint64(addr, v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapUintptr64(uaddr *uint64, count int) { - // only safe when uintptr is 64-bit. - // not called on 32-bit systems. - addr := (*uintptr)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := *addr - if CompareAndSwapUintptr(addr, v, v+1) { - break - } - } - } -} - -func hammerCompareAndSwapPointer64(uaddr *uint64, count int) { - // only safe when uintptr is 64-bit. - // not called on 32-bit systems. - addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr)) - for i := 0; i < count; i++ { - for { - v := *addr - if CompareAndSwapPointer(addr, v, unsafe.Pointer(uintptr(v)+1)) { - break - } - } - } -} - -func TestHammer64(t *testing.T) { - if test64err != nil { - t.Skipf("Skipping 64-bit tests: %v", test64err) - } - const p = 4 - n := 100000 - if testing.Short() { - n = 1000 - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p)) - - for name, testf := range hammer64 { - c := make(chan int) - var val uint64 - for i := 0; i < p; i++ { - go func() { - defer func() { - if err := recover(); err != nil { - t.Error(err.(string)) - } - c <- 1 - }() - testf(&val, n) - }() - } - for i := 0; i < p; i++ { - <-c - } - if !strings.HasPrefix(name, "Swap") && val != uint64(n)*p { - t.Fatalf("%s: val=%d want %d", name, val, n*p) - } - } -} - -func hammerStoreLoadInt32(t *testing.T, paddr unsafe.Pointer) { - addr := (*int32)(paddr) - v := LoadInt32(addr) - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Int32: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - StoreInt32(addr, new) -} - -func hammerStoreLoadUint32(t *testing.T, paddr unsafe.Pointer) { - addr := (*uint32)(paddr) - v := LoadUint32(addr) - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Uint32: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - StoreUint32(addr, new) -} - -func hammerStoreLoadInt64(t *testing.T, paddr unsafe.Pointer) { - addr := (*int64)(paddr) - v := LoadInt64(addr) - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Int64: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<32 - StoreInt64(addr, new) -} - -func hammerStoreLoadUint64(t *testing.T, paddr unsafe.Pointer) { - addr := (*uint64)(paddr) - v := LoadUint64(addr) - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Uint64: %#x != %#x", vlo, vhi) - } - new := v + 1 + 1<<32 - StoreUint64(addr, new) -} - -func hammerStoreLoadUintptr(t *testing.T, paddr unsafe.Pointer) { - addr := (*uintptr)(paddr) - var test64 uint64 = 1 << 50 - arch32 := uintptr(test64) == 0 - v := LoadUintptr(addr) - new := v - if arch32 { - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Uintptr: %#x != %#x", vlo, vhi) - } - new = v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - } else { - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Uintptr: %#x != %#x", vlo, vhi) - } - inc := uint64(1 + 1<<32) - new = v + uintptr(inc) - } - StoreUintptr(addr, new) -} - -func hammerStoreLoadPointer(t *testing.T, paddr unsafe.Pointer) { - addr := (*unsafe.Pointer)(paddr) - var test64 uint64 = 1 << 50 - arch32 := uintptr(test64) == 0 - v := uintptr(LoadPointer(addr)) - new := v - if arch32 { - vlo := v & ((1 << 16) - 1) - vhi := v >> 16 - if vlo != vhi { - t.Fatalf("Pointer: %#x != %#x", vlo, vhi) - } - new = v + 1 + 1<<16 - if vlo == 1e4 { - new = 0 - } - } else { - vlo := v & ((1 << 32) - 1) - vhi := v >> 32 - if vlo != vhi { - t.Fatalf("Pointer: %#x != %#x", vlo, vhi) - } - inc := uint64(1 + 1<<32) - new = v + uintptr(inc) - } - StorePointer(addr, unsafe.Pointer(new)) -} - -func TestHammerStoreLoad(t *testing.T) { - var tests []func(*testing.T, unsafe.Pointer) - tests = append(tests, hammerStoreLoadInt32, hammerStoreLoadUint32, - hammerStoreLoadUintptr, hammerStoreLoadPointer) - if test64err == nil { - tests = append(tests, hammerStoreLoadInt64, hammerStoreLoadUint64) - } - n := int(1e6) - if testing.Short() { - n = int(1e4) - } - const procs = 8 - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(procs)) - for _, tt := range tests { - c := make(chan int) - var val uint64 - for p := 0; p < procs; p++ { - go func() { - for i := 0; i < n; i++ { - tt(t, unsafe.Pointer(&val)) - } - c <- 1 - }() - } - for p := 0; p < procs; p++ { - <-c - } - } -} - -func TestStoreLoadSeqCst32(t *testing.T) { - if runtime.NumCPU() == 1 { - t.Skipf("Skipping test on %v processor machine", runtime.NumCPU()) - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) - N := int32(1e3) - if testing.Short() { - N = int32(1e2) - } - c := make(chan bool, 2) - X := [2]int32{} - ack := [2][3]int32{{-1, -1, -1}, {-1, -1, -1}} - for p := 0; p < 2; p++ { - go func(me int) { - he := 1 - me - for i := int32(1); i < N; i++ { - StoreInt32(&X[me], i) - my := LoadInt32(&X[he]) - StoreInt32(&ack[me][i%3], my) - for w := 1; LoadInt32(&ack[he][i%3]) == -1; w++ { - if w%1000 == 0 { - runtime.Gosched() - } - } - his := LoadInt32(&ack[he][i%3]) - if (my != i && my != i-1) || (his != i && his != i-1) { - t.Fatalf("invalid values: %d/%d (%d)", my, his, i) - } - if my != i && his != i { - t.Fatalf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i) - } - StoreInt32(&ack[me][(i-1)%3], -1) - } - c <- true - }(p) - } - <-c - <-c -} - -func TestStoreLoadSeqCst64(t *testing.T) { - if runtime.NumCPU() == 1 { - t.Skipf("Skipping test on %v processor machine", runtime.NumCPU()) - } - if test64err != nil { - t.Skipf("Skipping 64-bit tests: %v", test64err) - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) - N := int64(1e3) - if testing.Short() { - N = int64(1e2) - } - c := make(chan bool, 2) - X := [2]int64{} - ack := [2][3]int64{{-1, -1, -1}, {-1, -1, -1}} - for p := 0; p < 2; p++ { - go func(me int) { - he := 1 - me - for i := int64(1); i < N; i++ { - StoreInt64(&X[me], i) - my := LoadInt64(&X[he]) - StoreInt64(&ack[me][i%3], my) - for w := 1; LoadInt64(&ack[he][i%3]) == -1; w++ { - if w%1000 == 0 { - runtime.Gosched() - } - } - his := LoadInt64(&ack[he][i%3]) - if (my != i && my != i-1) || (his != i && his != i-1) { - t.Fatalf("invalid values: %d/%d (%d)", my, his, i) - } - if my != i && his != i { - t.Fatalf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i) - } - StoreInt64(&ack[me][(i-1)%3], -1) - } - c <- true - }(p) - } - <-c - <-c -} - -func TestStoreLoadRelAcq32(t *testing.T) { - if runtime.NumCPU() == 1 { - t.Skipf("Skipping test on %v processor machine", runtime.NumCPU()) - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) - N := int32(1e3) - if testing.Short() { - N = int32(1e2) - } - c := make(chan bool, 2) - type Data struct { - signal int32 - pad1 [128]int8 - data1 int32 - pad2 [128]int8 - data2 float32 - } - var X Data - for p := int32(0); p < 2; p++ { - go func(p int32) { - for i := int32(1); i < N; i++ { - if (i+p)%2 == 0 { - X.data1 = i - X.data2 = float32(i) - StoreInt32(&X.signal, i) - } else { - for w := 1; LoadInt32(&X.signal) != i; w++ { - if w%1000 == 0 { - runtime.Gosched() - } - } - d1 := X.data1 - d2 := X.data2 - if d1 != i || d2 != float32(i) { - t.Fatalf("incorrect data: %d/%g (%d)", d1, d2, i) - } - } - } - c <- true - }(p) - } - <-c - <-c -} - -func TestStoreLoadRelAcq64(t *testing.T) { - if runtime.NumCPU() == 1 { - t.Skipf("Skipping test on %v processor machine", runtime.NumCPU()) - } - if test64err != nil { - t.Skipf("Skipping 64-bit tests: %v", test64err) - } - defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) - N := int64(1e3) - if testing.Short() { - N = int64(1e2) - } - c := make(chan bool, 2) - type Data struct { - signal int64 - pad1 [128]int8 - data1 int64 - pad2 [128]int8 - data2 float64 - } - var X Data - for p := int64(0); p < 2; p++ { - go func(p int64) { - for i := int64(1); i < N; i++ { - if (i+p)%2 == 0 { - X.data1 = i - X.data2 = float64(i) - StoreInt64(&X.signal, i) - } else { - for w := 1; LoadInt64(&X.signal) != i; w++ { - if w%1000 == 0 { - runtime.Gosched() - } - } - d1 := X.data1 - d2 := X.data2 - if d1 != i || d2 != float64(i) { - t.Fatalf("incorrect data: %d/%g (%d)", d1, d2, i) - } - } - } - c <- true - }(p) - } - <-c - <-c -} - -func shouldPanic(t *testing.T, name string, f func()) { - defer func() { - if recover() == nil { - t.Errorf("%s did not panic", name) - } - }() - f() -} - -func TestUnaligned64(t *testing.T) { - // Unaligned 64-bit atomics on 32-bit systems are - // a continual source of pain. Test that on 32-bit systems they crash - // instead of failing silently. - if unsafe.Sizeof(int(0)) != 4 { - t.Skip("test only runs on 32-bit systems") - } - - x := make([]uint32, 4) - p := (*uint64)(unsafe.Pointer(&x[1])) // misaligned - - shouldPanic(t, "LoadUint64", func() { LoadUint64(p) }) - shouldPanic(t, "StoreUint64", func() { StoreUint64(p, 1) }) - shouldPanic(t, "CompareAndSwapUint64", func() { CompareAndSwapUint64(p, 1, 2) }) - shouldPanic(t, "AddUint64", func() { AddUint64(p, 3) }) -} - -func TestNilDeref(t *testing.T) { - if p := runtime.GOOS + "/" + runtime.GOARCH; p == "freebsd/arm" || p == "netbsd/arm" { - t.Skipf("issue 7338: skipping test on %q", p) - } - funcs := [...]func(){ - func() { CompareAndSwapInt32(nil, 0, 0) }, - func() { CompareAndSwapInt64(nil, 0, 0) }, - func() { CompareAndSwapUint32(nil, 0, 0) }, - func() { CompareAndSwapUint64(nil, 0, 0) }, - func() { CompareAndSwapUintptr(nil, 0, 0) }, - func() { CompareAndSwapPointer(nil, nil, nil) }, - func() { SwapInt32(nil, 0) }, - func() { SwapUint32(nil, 0) }, - func() { SwapInt64(nil, 0) }, - func() { SwapUint64(nil, 0) }, - func() { SwapUintptr(nil, 0) }, - func() { SwapPointer(nil, nil) }, - func() { AddInt32(nil, 0) }, - func() { AddUint32(nil, 0) }, - func() { AddInt64(nil, 0) }, - func() { AddUint64(nil, 0) }, - func() { AddUintptr(nil, 0) }, - func() { LoadInt32(nil) }, - func() { LoadInt64(nil) }, - func() { LoadUint32(nil) }, - func() { LoadUint64(nil) }, - func() { LoadUintptr(nil) }, - func() { LoadPointer(nil) }, - func() { StoreInt32(nil, 0) }, - func() { StoreInt64(nil, 0) }, - func() { StoreUint32(nil, 0) }, - func() { StoreUint64(nil, 0) }, - func() { StoreUintptr(nil, 0) }, - func() { StorePointer(nil, nil) }, - } - for _, f := range funcs { - func() { - defer func() { - runtime.GC() - recover() - }() - f() - }() - } -} |