URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [sync/] [atomic/] [atomic_test.go] - Rev 747
Compare with Previous | Blame | View Log
// 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_testimport ("runtime". "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 = 0xdedbeefmagic64 = 0xdeddeadbeefbeef)// Do the 64-bit functions panic? If so, don't bother testing.var test64err = func() (err interface{}) {defer func() {err = recover()}()var x int64AddInt64(&x, 1)return nil}()func TestAddInt32(t *testing.T) {var x struct {before int32i int32after int32}x.before = magic32x.after = magic32var j int32for delta := int32(1); delta+delta > delta; delta += delta {k := AddInt32(&x.i, delta)j += deltaif 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 uint32i uint32after uint32}x.before = magic32x.after = magic32var j uint32for delta := uint32(1); delta+delta > delta; delta += delta {k := AddUint32(&x.i, delta)j += deltaif 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.Logf("Skipping 64-bit tests: %v", test64err)return}var x struct {before int64i int64after int64}x.before = magic64x.after = magic64var j int64for delta := int64(1); delta+delta > delta; delta += delta {k := AddInt64(&x.i, delta)j += deltaif 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.Logf("Skipping 64-bit tests: %v", test64err)return}var x struct {before uint64i uint64after uint64}x.before = magic64x.after = magic64var j uint64for delta := uint64(1); delta+delta > delta; delta += delta {k := AddUint64(&x.i, delta)j += deltaif 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 uintptri uintptrafter uintptr}var m uint64 = magic64magicptr := uintptr(m)x.before = magicptrx.after = magicptrvar j uintptrfor delta := uintptr(1); delta+delta > delta; delta += delta {k := AddUintptr(&x.i, delta)j += deltaif 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 int32i int32after int32}x.before = magic32x.after = magic32for val := int32(1); val+val > val; val += val {x.i = valif !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 + 1if 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 uint32i uint32after uint32}x.before = magic32x.after = magic32for val := uint32(1); val+val > val; val += val {x.i = valif !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 + 1if 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.Logf("Skipping 64-bit tests: %v", test64err)return}var x struct {before int64i int64after int64}x.before = magic64x.after = magic64for val := int64(1); val+val > val; val += val {x.i = valif !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 + 1if 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) {if test64err != nil {t.Logf("Skipping 64-bit tests: %v", test64err)return}var x struct {before uint64i uint64after uint64}x.before = magic64x.after = magic64for val := uint64(1); val+val > val; val += val {x.i = valif !CompareAndSwapUint64(&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 + 1if CompareAndSwapUint64(&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 TestCompareAndSwapUintptr(t *testing.T) {var x struct {before uintptri uintptrafter uintptr}var m uint64 = magic64magicptr := uintptr(m)x.before = magicptrx.after = magicptrfor val := uintptr(1); val+val > val; val += val {x.i = valif !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 + 1if 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 uintptri unsafe.Pointerafter uintptr}var m uint64 = magic64magicptr := uintptr(m)x.before = magicptrx.after = magicptrfor 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 int32i int32after int32}x.before = magic32x.after = magic32for 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 uint32i uint32after uint32}x.before = magic32x.after = magic32for 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.Logf("Skipping 64-bit tests: %v", test64err)return}var x struct {before int64i int64after int64}x.before = magic64x.after = magic64for 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.Logf("Skipping 64-bit tests: %v", test64err)return}var x struct {before uint64i uint64after uint64}x.before = magic64x.after = magic64for 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 uintptri uintptrafter uintptr}var m uint64 = magic64magicptr := uintptr(m)x.before = magicptrx.after = magicptrfor 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 uintptri unsafe.Pointerafter uintptr}var m uint64 = magic64magicptr := uintptr(m)x.before = magicptrx.after = magicptrfor 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 int32i int32after int32}x.before = magic32x.after = magic32v := 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 uint32i uint32after uint32}x.before = magic32x.after = magic32v := 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.Logf("Skipping 64-bit tests: %v", test64err)return}var x struct {before int64i int64after int64}x.before = magic64x.after = magic64v := 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.Logf("Skipping 64-bit tests: %v", test64err)return}var x struct {before uint64i uint64after uint64}x.before = magic64x.after = magic64v := 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 uintptri uintptrafter uintptr}var m uint64 = magic64magicptr := uintptr(m)x.before = magicptrx.after = magicptrv := 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 uintptri unsafe.Pointerafter uintptr}var m uint64 = magic64magicptr := uintptr(m)x.before = magicptrx.after = magicptrv := 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.var hammer32 = []struct {name stringf func(*uint32, int)}{{"AddInt32", hammerAddInt32},{"AddUint32", hammerAddUint32},{"AddUintptr", hammerAddUintptr32},{"CompareAndSwapInt32", hammerCompareAndSwapInt32},{"CompareAndSwapUint32", hammerCompareAndSwapUint32},{"CompareAndSwapUintptr", hammerCompareAndSwapUintptr32},{"CompareAndSwapPointer", hammerCompareAndSwapPointer32},}func init() {var v uint64 = 1 << 50if uintptr(v) != 0 {// 64-bit system; clear uintptr testshammer32[2].f = nilhammer32[5].f = nilhammer32[6].f = nil}}func hammerAddInt32(uval *uint32, count int) {val := (*int32)(unsafe.Pointer(uval))for i := 0; i < count; i++ {AddInt32(val, 1)}}func hammerAddUint32(val *uint32, count int) {for i := 0; i < count; i++ {AddUint32(val, 1)}}func hammerAddUintptr32(uval *uint32, count int) {// only safe when uintptr is 32-bit.// not called on 64-bit systems.val := (*uintptr)(unsafe.Pointer(uval))for i := 0; i < count; i++ {AddUintptr(val, 1)}}func hammerCompareAndSwapInt32(uval *uint32, count int) {val := (*int32)(unsafe.Pointer(uval))for i := 0; i < count; i++ {for {v := *valif CompareAndSwapInt32(val, v, v+1) {break}}}}func hammerCompareAndSwapUint32(val *uint32, count int) {for i := 0; i < count; i++ {for {v := *valif CompareAndSwapUint32(val, v, v+1) {break}}}}func hammerCompareAndSwapUintptr32(uval *uint32, count int) {// only safe when uintptr is 32-bit.// not called on 64-bit systems.val := (*uintptr)(unsafe.Pointer(uval))for i := 0; i < count; i++ {for {v := *valif CompareAndSwapUintptr(val, v, v+1) {break}}}}func hammerCompareAndSwapPointer32(uval *uint32, count int) {// only safe when uintptr is 32-bit.// not called on 64-bit systems.val := (*unsafe.Pointer)(unsafe.Pointer(uval))for i := 0; i < count; i++ {for {v := *valif CompareAndSwapPointer(val, v, unsafe.Pointer(uintptr(v)+1)) {break}}}}func TestHammer32(t *testing.T) {const p = 4n := 100000if testing.Short() {n = 1000}defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))for _, tt := range hammer32 {if tt.f == nil {continue}c := make(chan int)var val uint32for i := 0; i < p; i++ {go func() {tt.f(&val, n)c <- 1}()}for i := 0; i < p; i++ {<-c}if val != uint32(n)*p {t.Fatalf("%s: val=%d want %d", tt.name, val, n*p)}}}var hammer64 = []struct {name stringf func(*uint64, int)}{{"AddInt64", hammerAddInt64},{"AddUint64", hammerAddUint64},{"AddUintptr", hammerAddUintptr64},{"CompareAndSwapInt64", hammerCompareAndSwapInt64},{"CompareAndSwapUint64", hammerCompareAndSwapUint64},{"CompareAndSwapUintptr", hammerCompareAndSwapUintptr64},{"CompareAndSwapPointer", hammerCompareAndSwapPointer64},}func init() {var v uint64 = 1 << 50if uintptr(v) == 0 {// 32-bit system; clear uintptr testshammer64[2].f = nilhammer64[5].f = nilhammer64[6].f = nil}}func hammerAddInt64(uval *uint64, count int) {val := (*int64)(unsafe.Pointer(uval))for i := 0; i < count; i++ {AddInt64(val, 1)}}func hammerAddUint64(val *uint64, count int) {for i := 0; i < count; i++ {AddUint64(val, 1)}}func hammerAddUintptr64(uval *uint64, count int) {// only safe when uintptr is 64-bit.// not called on 32-bit systems.val := (*uintptr)(unsafe.Pointer(uval))for i := 0; i < count; i++ {AddUintptr(val, 1)}}func hammerCompareAndSwapInt64(uval *uint64, count int) {val := (*int64)(unsafe.Pointer(uval))for i := 0; i < count; i++ {for {v := *valif CompareAndSwapInt64(val, v, v+1) {break}}}}func hammerCompareAndSwapUint64(val *uint64, count int) {for i := 0; i < count; i++ {for {v := *valif CompareAndSwapUint64(val, v, v+1) {break}}}}func hammerCompareAndSwapUintptr64(uval *uint64, count int) {// only safe when uintptr is 64-bit.// not called on 32-bit systems.val := (*uintptr)(unsafe.Pointer(uval))for i := 0; i < count; i++ {for {v := *valif CompareAndSwapUintptr(val, v, v+1) {break}}}}func hammerCompareAndSwapPointer64(uval *uint64, count int) {// only safe when uintptr is 64-bit.// not called on 32-bit systems.val := (*unsafe.Pointer)(unsafe.Pointer(uval))for i := 0; i < count; i++ {for {v := *valif CompareAndSwapPointer(val, v, unsafe.Pointer(uintptr(v)+1)) {break}}}}func TestHammer64(t *testing.T) {if test64err != nil {t.Logf("Skipping 64-bit tests: %v", test64err)return}const p = 4n := 100000if testing.Short() {n = 1000}defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))for _, tt := range hammer64 {if tt.f == nil {continue}c := make(chan int)var val uint64for i := 0; i < p; i++ {go func() {tt.f(&val, n)c <- 1}()}for i := 0; i < p; i++ {<-c}if val != uint64(n)*p {t.Fatalf("%s: val=%d want %d", tt.name, val, n*p)}}}func hammerStoreLoadInt32(t *testing.T, valp unsafe.Pointer) {val := (*int32)(valp)v := LoadInt32(val)vlo := v & ((1 << 16) - 1)vhi := v >> 16if vlo != vhi {t.Fatalf("Int32: %#x != %#x", vlo, vhi)}new := v + 1 + 1<<16if vlo == 1e4 {new = 0}StoreInt32(val, new)}func hammerStoreLoadUint32(t *testing.T, valp unsafe.Pointer) {val := (*uint32)(valp)v := LoadUint32(val)vlo := v & ((1 << 16) - 1)vhi := v >> 16if vlo != vhi {t.Fatalf("Uint32: %#x != %#x", vlo, vhi)}new := v + 1 + 1<<16if vlo == 1e4 {new = 0}StoreUint32(val, new)}func hammerStoreLoadInt64(t *testing.T, valp unsafe.Pointer) {val := (*int64)(valp)v := LoadInt64(val)vlo := v & ((1 << 32) - 1)vhi := v >> 32if vlo != vhi {t.Fatalf("Int64: %#x != %#x", vlo, vhi)}new := v + 1 + 1<<32StoreInt64(val, new)}func hammerStoreLoadUint64(t *testing.T, valp unsafe.Pointer) {val := (*uint64)(valp)v := LoadUint64(val)vlo := v & ((1 << 32) - 1)vhi := v >> 32if vlo != vhi {t.Fatalf("Uint64: %#x != %#x", vlo, vhi)}new := v + 1 + 1<<32StoreUint64(val, new)}func hammerStoreLoadUintptr(t *testing.T, valp unsafe.Pointer) {val := (*uintptr)(valp)var test64 uint64 = 1 << 50arch32 := uintptr(test64) == 0v := LoadUintptr(val)new := vif arch32 {vlo := v & ((1 << 16) - 1)vhi := v >> 16if vlo != vhi {t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)}new = v + 1 + 1<<16if vlo == 1e4 {new = 0}} else {vlo := v & ((1 << 32) - 1)vhi := v >> 32if vlo != vhi {t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)}inc := uint64(1 + 1<<32)new = v + uintptr(inc)}StoreUintptr(val, new)}func hammerStoreLoadPointer(t *testing.T, valp unsafe.Pointer) {val := (*unsafe.Pointer)(valp)var test64 uint64 = 1 << 50arch32 := uintptr(test64) == 0v := uintptr(LoadPointer(val))new := vif arch32 {vlo := v & ((1 << 16) - 1)vhi := v >> 16if vlo != vhi {t.Fatalf("Pointer: %#x != %#x", vlo, vhi)}new = v + 1 + 1<<16if vlo == 1e4 {new = 0}} else {vlo := v & ((1 << 32) - 1)vhi := v >> 32if vlo != vhi {t.Fatalf("Pointer: %#x != %#x", vlo, vhi)}inc := uint64(1 + 1<<32)new = v + uintptr(inc)}StorePointer(val, 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 = 8defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(procs))for _, tt := range tests {c := make(chan int)var val uint64for 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) {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 - mefor 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 test64err != nil {t.Logf("Skipping 64-bit tests: %v", test64err)return}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 - mefor 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) {defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))N := int32(1e3)if testing.Short() {N = int32(1e2)}c := make(chan bool, 2)type Data struct {signal int32pad1 [128]int8data1 int32pad2 [128]int8data2 float32}var X Datafor p := int32(0); p < 2; p++ {go func(p int32) {for i := int32(1); i < N; i++ {if (i+p)%2 == 0 {X.data1 = iX.data2 = float32(i)StoreInt32(&X.signal, i)} else {for w := 1; LoadInt32(&X.signal) != i; w++ {if w%1000 == 0 {runtime.Gosched()}}d1 := X.data1d2 := X.data2if d1 != i || d2 != float32(i) {t.Fatalf("incorrect data: %d/%d (%d)", d1, d2, i)}}}c <- true}(p)}<-c<-c}func TestStoreLoadRelAcq64(t *testing.T) {if test64err != nil {t.Logf("Skipping 64-bit tests: %v", test64err)return}defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))N := int64(1e3)if testing.Short() {N = int64(1e2)}c := make(chan bool, 2)type Data struct {signal int64pad1 [128]int8data1 int64pad2 [128]int8data2 float64}var X Datafor p := int64(0); p < 2; p++ {go func(p int64) {for i := int64(1); i < N; i++ {if (i+p)%2 == 0 {X.data1 = iX.data2 = float64(i)StoreInt64(&X.signal, i)} else {for w := 1; LoadInt64(&X.signal) != i; w++ {if w%1000 == 0 {runtime.Gosched()}}d1 := X.data1d2 := X.data2if d1 != i || d2 != float64(i) {t.Fatalf("incorrect data: %d/%d (%d)", d1, d2, i)}}}c <- true}(p)}<-c<-c}
