summaryrefslogtreecommitdiff
path: root/src/runtime/race/testdata/atomic_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/race/testdata/atomic_test.go')
-rw-r--r--src/runtime/race/testdata/atomic_test.go288
1 files changed, 288 insertions, 0 deletions
diff --git a/src/runtime/race/testdata/atomic_test.go b/src/runtime/race/testdata/atomic_test.go
new file mode 100644
index 000000000..232744b3d
--- /dev/null
+++ b/src/runtime/race/testdata/atomic_test.go
@@ -0,0 +1,288 @@
+// 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 race_test
+
+import (
+ "runtime"
+ "sync"
+ "sync/atomic"
+ "testing"
+ "unsafe"
+)
+
+func TestNoRaceAtomicAddInt64(t *testing.T) {
+ var x1, x2 int8
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+}
+
+// A nil pointer in an atomic operation should not deadlock
+// the rest of the program. Used to hang indefinitely.
+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)
+}