github.com/sean-/go@v0.0.0-20151219100004-97f854cd7bb6/src/runtime/race/testdata/atomic_test.go (about)

     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  
     5  package race_test
     6  
     7  import (
     8  	"runtime"
     9  	"sync"
    10  	"sync/atomic"
    11  	"testing"
    12  	"unsafe"
    13  )
    14  
    15  func TestNoRaceAtomicAddInt64(t *testing.T) {
    16  	var x1, x2 int8
    17  	var s int64
    18  	ch := make(chan bool, 2)
    19  	go func() {
    20  		x1 = 1
    21  		if atomic.AddInt64(&s, 1) == 2 {
    22  			x2 = 1
    23  		}
    24  		ch <- true
    25  	}()
    26  	go func() {
    27  		x2 = 1
    28  		if atomic.AddInt64(&s, 1) == 2 {
    29  			x1 = 1
    30  		}
    31  		ch <- true
    32  	}()
    33  	<-ch
    34  	<-ch
    35  }
    36  
    37  func TestRaceAtomicAddInt64(t *testing.T) {
    38  	var x1, x2 int8
    39  	var s int64
    40  	ch := make(chan bool, 2)
    41  	go func() {
    42  		x1 = 1
    43  		if atomic.AddInt64(&s, 1) == 1 {
    44  			x2 = 1
    45  		}
    46  		ch <- true
    47  	}()
    48  	go func() {
    49  		x2 = 1
    50  		if atomic.AddInt64(&s, 1) == 1 {
    51  			x1 = 1
    52  		}
    53  		ch <- true
    54  	}()
    55  	<-ch
    56  	<-ch
    57  }
    58  
    59  func TestNoRaceAtomicAddInt32(t *testing.T) {
    60  	var x1, x2 int8
    61  	var s int32
    62  	ch := make(chan bool, 2)
    63  	go func() {
    64  		x1 = 1
    65  		if atomic.AddInt32(&s, 1) == 2 {
    66  			x2 = 1
    67  		}
    68  		ch <- true
    69  	}()
    70  	go func() {
    71  		x2 = 1
    72  		if atomic.AddInt32(&s, 1) == 2 {
    73  			x1 = 1
    74  		}
    75  		ch <- true
    76  	}()
    77  	<-ch
    78  	<-ch
    79  }
    80  
    81  func TestNoRaceAtomicLoadAddInt32(t *testing.T) {
    82  	var x int64
    83  	var s int32
    84  	go func() {
    85  		x = 2
    86  		atomic.AddInt32(&s, 1)
    87  	}()
    88  	for atomic.LoadInt32(&s) != 1 {
    89  		runtime.Gosched()
    90  	}
    91  	x = 1
    92  }
    93  
    94  func TestNoRaceAtomicLoadStoreInt32(t *testing.T) {
    95  	var x int64
    96  	var s int32
    97  	go func() {
    98  		x = 2
    99  		atomic.StoreInt32(&s, 1)
   100  	}()
   101  	for atomic.LoadInt32(&s) != 1 {
   102  		runtime.Gosched()
   103  	}
   104  	x = 1
   105  }
   106  
   107  func TestNoRaceAtomicStoreCASInt32(t *testing.T) {
   108  	var x int64
   109  	var s int32
   110  	go func() {
   111  		x = 2
   112  		atomic.StoreInt32(&s, 1)
   113  	}()
   114  	for !atomic.CompareAndSwapInt32(&s, 1, 0) {
   115  		runtime.Gosched()
   116  	}
   117  	x = 1
   118  }
   119  
   120  func TestNoRaceAtomicCASLoadInt32(t *testing.T) {
   121  	var x int64
   122  	var s int32
   123  	go func() {
   124  		x = 2
   125  		if !atomic.CompareAndSwapInt32(&s, 0, 1) {
   126  			panic("")
   127  		}
   128  	}()
   129  	for atomic.LoadInt32(&s) != 1 {
   130  		runtime.Gosched()
   131  	}
   132  	x = 1
   133  }
   134  
   135  func TestNoRaceAtomicCASCASInt32(t *testing.T) {
   136  	var x int64
   137  	var s int32
   138  	go func() {
   139  		x = 2
   140  		if !atomic.CompareAndSwapInt32(&s, 0, 1) {
   141  			panic("")
   142  		}
   143  	}()
   144  	for !atomic.CompareAndSwapInt32(&s, 1, 0) {
   145  		runtime.Gosched()
   146  	}
   147  	x = 1
   148  }
   149  
   150  func TestNoRaceAtomicCASCASInt32_2(t *testing.T) {
   151  	var x1, x2 int8
   152  	var s int32
   153  	ch := make(chan bool, 2)
   154  	go func() {
   155  		x1 = 1
   156  		if !atomic.CompareAndSwapInt32(&s, 0, 1) {
   157  			x2 = 1
   158  		}
   159  		ch <- true
   160  	}()
   161  	go func() {
   162  		x2 = 1
   163  		if !atomic.CompareAndSwapInt32(&s, 0, 1) {
   164  			x1 = 1
   165  		}
   166  		ch <- true
   167  	}()
   168  	<-ch
   169  	<-ch
   170  }
   171  
   172  func TestNoRaceAtomicLoadInt64(t *testing.T) {
   173  	var x int32
   174  	var s int64
   175  	go func() {
   176  		x = 2
   177  		atomic.AddInt64(&s, 1)
   178  	}()
   179  	for atomic.LoadInt64(&s) != 1 {
   180  		runtime.Gosched()
   181  	}
   182  	x = 1
   183  }
   184  
   185  func TestNoRaceAtomicCASCASUInt64(t *testing.T) {
   186  	var x int64
   187  	var s uint64
   188  	go func() {
   189  		x = 2
   190  		if !atomic.CompareAndSwapUint64(&s, 0, 1) {
   191  			panic("")
   192  		}
   193  	}()
   194  	for !atomic.CompareAndSwapUint64(&s, 1, 0) {
   195  		runtime.Gosched()
   196  	}
   197  	x = 1
   198  }
   199  
   200  func TestNoRaceAtomicLoadStorePointer(t *testing.T) {
   201  	var x int64
   202  	var s unsafe.Pointer
   203  	var y int = 2
   204  	var p unsafe.Pointer = unsafe.Pointer(&y)
   205  	go func() {
   206  		x = 2
   207  		atomic.StorePointer(&s, p)
   208  	}()
   209  	for atomic.LoadPointer(&s) != p {
   210  		runtime.Gosched()
   211  	}
   212  	x = 1
   213  }
   214  
   215  func TestNoRaceAtomicStoreCASUint64(t *testing.T) {
   216  	var x int64
   217  	var s uint64
   218  	go func() {
   219  		x = 2
   220  		atomic.StoreUint64(&s, 1)
   221  	}()
   222  	for !atomic.CompareAndSwapUint64(&s, 1, 0) {
   223  		runtime.Gosched()
   224  	}
   225  	x = 1
   226  }
   227  
   228  func TestRaceAtomicStoreLoad(t *testing.T) {
   229  	c := make(chan bool)
   230  	var a uint64
   231  	go func() {
   232  		atomic.StoreUint64(&a, 1)
   233  		c <- true
   234  	}()
   235  	_ = a
   236  	<-c
   237  }
   238  
   239  func TestRaceAtomicLoadStore(t *testing.T) {
   240  	c := make(chan bool)
   241  	var a uint64
   242  	go func() {
   243  		_ = atomic.LoadUint64(&a)
   244  		c <- true
   245  	}()
   246  	a = 1
   247  	<-c
   248  }
   249  
   250  func TestRaceAtomicAddLoad(t *testing.T) {
   251  	c := make(chan bool)
   252  	var a uint64
   253  	go func() {
   254  		atomic.AddUint64(&a, 1)
   255  		c <- true
   256  	}()
   257  	_ = a
   258  	<-c
   259  }
   260  
   261  func TestRaceAtomicAddStore(t *testing.T) {
   262  	c := make(chan bool)
   263  	var a uint64
   264  	go func() {
   265  		atomic.AddUint64(&a, 1)
   266  		c <- true
   267  	}()
   268  	a = 42
   269  	<-c
   270  }
   271  
   272  // A nil pointer in an atomic operation should not deadlock
   273  // the rest of the program. Used to hang indefinitely.
   274  func TestNoRaceAtomicCrash(t *testing.T) {
   275  	var mutex sync.Mutex
   276  	var nilptr *int32
   277  	panics := 0
   278  	defer func() {
   279  		if x := recover(); x != nil {
   280  			mutex.Lock()
   281  			panics++
   282  			mutex.Unlock()
   283  		} else {
   284  			panic("no panic")
   285  		}
   286  	}()
   287  	atomic.AddInt32(nilptr, 1)
   288  }