| | |
| | |
| | |
| |
|
| | package race_test |
| |
|
| | import ( |
| | "runtime" |
| | "sync" |
| | "sync/atomic" |
| | "testing" |
| | "unsafe" |
| | ) |
| |
|
| | func TestNoRaceAtomicAddInt64(t *testing.T) { |
| | var x1, x2 int8 |
| | _ = x1 + x2 |
| | var s int64 |
| | ch := make(chan bool, 2) |
| | go func() { |
| | x1 = 1 |
| | if atomic.AddInt64(&s, 1) == 2 { |
| | x2 = 1 |
| | } |
| | ch <- true |
| | }() |
| | go func() { |
| | x2 = 1 |
| | if atomic.AddInt64(&s, 1) == 2 { |
| | x1 = 1 |
| | } |
| | ch <- true |
| | }() |
| | <-ch |
| | <-ch |
| | } |
| |
|
| | func TestRaceAtomicAddInt64(t *testing.T) { |
| | var x1, x2 int8 |
| | _ = x1 + x2 |
| | var s int64 |
| | ch := make(chan bool, 2) |
| | go func() { |
| | x1 = 1 |
| | if atomic.AddInt64(&s, 1) == 1 { |
| | x2 = 1 |
| | } |
| | ch <- true |
| | }() |
| | go func() { |
| | x2 = 1 |
| | if atomic.AddInt64(&s, 1) == 1 { |
| | x1 = 1 |
| | } |
| | ch <- true |
| | }() |
| | <-ch |
| | <-ch |
| | } |
| |
|
| | func TestNoRaceAtomicAddInt32(t *testing.T) { |
| | var x1, x2 int8 |
| | _ = x1 + x2 |
| | var s int32 |
| | ch := make(chan bool, 2) |
| | go func() { |
| | x1 = 1 |
| | if atomic.AddInt32(&s, 1) == 2 { |
| | x2 = 1 |
| | } |
| | ch <- true |
| | }() |
| | go func() { |
| | x2 = 1 |
| | if atomic.AddInt32(&s, 1) == 2 { |
| | x1 = 1 |
| | } |
| | ch <- true |
| | }() |
| | <-ch |
| | <-ch |
| | } |
| |
|
| | func TestNoRaceAtomicLoadAddInt32(t *testing.T) { |
| | var x int64 |
| | _ = x |
| | var s int32 |
| | go func() { |
| | x = 2 |
| | atomic.AddInt32(&s, 1) |
| | }() |
| | for atomic.LoadInt32(&s) != 1 { |
| | runtime.Gosched() |
| | } |
| | x = 1 |
| | } |
| |
|
| | func TestNoRaceAtomicLoadStoreInt32(t *testing.T) { |
| | var x int64 |
| | _ = x |
| | var s int32 |
| | go func() { |
| | x = 2 |
| | atomic.StoreInt32(&s, 1) |
| | }() |
| | for atomic.LoadInt32(&s) != 1 { |
| | runtime.Gosched() |
| | } |
| | x = 1 |
| | } |
| |
|
| | func TestNoRaceAtomicStoreCASInt32(t *testing.T) { |
| | var x int64 |
| | _ = x |
| | var s int32 |
| | go func() { |
| | x = 2 |
| | atomic.StoreInt32(&s, 1) |
| | }() |
| | for !atomic.CompareAndSwapInt32(&s, 1, 0) { |
| | runtime.Gosched() |
| | } |
| | x = 1 |
| | } |
| |
|
| | func TestNoRaceAtomicCASLoadInt32(t *testing.T) { |
| | var x int64 |
| | _ = x |
| | var s int32 |
| | go func() { |
| | x = 2 |
| | if !atomic.CompareAndSwapInt32(&s, 0, 1) { |
| | panic("") |
| | } |
| | }() |
| | for atomic.LoadInt32(&s) != 1 { |
| | runtime.Gosched() |
| | } |
| | x = 1 |
| | } |
| |
|
| | func TestNoRaceAtomicCASCASInt32(t *testing.T) { |
| | var x int64 |
| | _ = x |
| | var s int32 |
| | go func() { |
| | x = 2 |
| | if !atomic.CompareAndSwapInt32(&s, 0, 1) { |
| | panic("") |
| | } |
| | }() |
| | for !atomic.CompareAndSwapInt32(&s, 1, 0) { |
| | runtime.Gosched() |
| | } |
| | x = 1 |
| | } |
| |
|
| | func TestNoRaceAtomicCASCASInt32_2(t *testing.T) { |
| | var x1, x2 int8 |
| | _ = x1 + x2 |
| | var s int32 |
| | ch := make(chan bool, 2) |
| | go func() { |
| | x1 = 1 |
| | if !atomic.CompareAndSwapInt32(&s, 0, 1) { |
| | x2 = 1 |
| | } |
| | ch <- true |
| | }() |
| | go func() { |
| | x2 = 1 |
| | if !atomic.CompareAndSwapInt32(&s, 0, 1) { |
| | x1 = 1 |
| | } |
| | ch <- true |
| | }() |
| | <-ch |
| | <-ch |
| | } |
| |
|
| | func TestNoRaceAtomicLoadInt64(t *testing.T) { |
| | var x int32 |
| | _ = x |
| | var s int64 |
| | go func() { |
| | x = 2 |
| | atomic.AddInt64(&s, 1) |
| | }() |
| | for atomic.LoadInt64(&s) != 1 { |
| | runtime.Gosched() |
| | } |
| | x = 1 |
| | } |
| |
|
| | func TestNoRaceAtomicCASCASUInt64(t *testing.T) { |
| | var x int64 |
| | _ = x |
| | var s uint64 |
| | go func() { |
| | x = 2 |
| | if !atomic.CompareAndSwapUint64(&s, 0, 1) { |
| | panic("") |
| | } |
| | }() |
| | for !atomic.CompareAndSwapUint64(&s, 1, 0) { |
| | runtime.Gosched() |
| | } |
| | x = 1 |
| | } |
| |
|
| | func TestNoRaceAtomicLoadStorePointer(t *testing.T) { |
| | var x int64 |
| | _ = x |
| | var s unsafe.Pointer |
| | var y int = 2 |
| | var p unsafe.Pointer = unsafe.Pointer(&y) |
| | go func() { |
| | x = 2 |
| | atomic.StorePointer(&s, p) |
| | }() |
| | for atomic.LoadPointer(&s) != p { |
| | runtime.Gosched() |
| | } |
| | x = 1 |
| | } |
| |
|
| | func TestNoRaceAtomicStoreCASUint64(t *testing.T) { |
| | var x int64 |
| | _ = x |
| | var s uint64 |
| | go func() { |
| | x = 2 |
| | atomic.StoreUint64(&s, 1) |
| | }() |
| | for !atomic.CompareAndSwapUint64(&s, 1, 0) { |
| | runtime.Gosched() |
| | } |
| | x = 1 |
| | } |
| |
|
| | func TestRaceAtomicStoreLoad(t *testing.T) { |
| | c := make(chan bool) |
| | var a uint64 |
| | go func() { |
| | atomic.StoreUint64(&a, 1) |
| | c <- true |
| | }() |
| | _ = a |
| | <-c |
| | } |
| |
|
| | func TestRaceAtomicLoadStore(t *testing.T) { |
| | c := make(chan bool) |
| | var a uint64 |
| | go func() { |
| | _ = atomic.LoadUint64(&a) |
| | c <- true |
| | }() |
| | a = 1 |
| | <-c |
| | } |
| |
|
| | func TestRaceAtomicAddLoad(t *testing.T) { |
| | c := make(chan bool) |
| | var a uint64 |
| | go func() { |
| | atomic.AddUint64(&a, 1) |
| | c <- true |
| | }() |
| | _ = a |
| | <-c |
| | } |
| |
|
| | func TestRaceAtomicAddStore(t *testing.T) { |
| | c := make(chan bool) |
| | var a uint64 |
| | go func() { |
| | atomic.AddUint64(&a, 1) |
| | c <- true |
| | }() |
| | a = 42 |
| | <-c |
| | } |
| |
|
| | |
| | |
| | func TestNoRaceAtomicCrash(t *testing.T) { |
| | var mutex sync.Mutex |
| | var nilptr *int32 |
| | panics := 0 |
| | defer func() { |
| | if x := recover(); x != nil { |
| | mutex.Lock() |
| | panics++ |
| | mutex.Unlock() |
| | } else { |
| | panic("no panic") |
| | } |
| | }() |
| | atomic.AddInt32(nilptr, 1) |
| | } |
| |
|
| | func TestNoRaceDeferAtomicStore(t *testing.T) { |
| | |
| | |
| | type foo struct { |
| | bar int64 |
| | } |
| |
|
| | var doFork func(f *foo, depth int) |
| | doFork = func(f *foo, depth int) { |
| | atomic.StoreInt64(&f.bar, 1) |
| | defer atomic.StoreInt64(&f.bar, 0) |
| | if depth > 0 { |
| | for i := 0; i < 2; i++ { |
| | f2 := &foo{} |
| | go doFork(f2, depth-1) |
| | } |
| | } |
| | runtime.GC() |
| | } |
| |
|
| | f := &foo{} |
| | doFork(f, 11) |
| | } |
| |
|