github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/pkg/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  // Races with non-atomic loads are not detected.
   229  func TestRaceFailingAtomicStoreLoad(t *testing.T) {
   230  	c := make(chan bool)
   231  	var a uint64
   232  	go func() {
   233  		atomic.StoreUint64(&a, 1)
   234  		c <- true
   235  	}()
   236  	_ = a
   237  	<-c
   238  }
   239  
   240  func TestRaceAtomicLoadStore(t *testing.T) {
   241  	c := make(chan bool)
   242  	var a uint64
   243  	go func() {
   244  		_ = atomic.LoadUint64(&a)
   245  		c <- true
   246  	}()
   247  	a = 1
   248  	<-c
   249  }
   250  
   251  // Races with non-atomic loads are not detected.
   252  func TestRaceFailingAtomicAddLoad(t *testing.T) {
   253  	c := make(chan bool)
   254  	var a uint64
   255  	go func() {
   256  		atomic.AddUint64(&a, 1)
   257  		c <- true
   258  	}()
   259  	_ = a
   260  	<-c
   261  }
   262  
   263  func TestRaceAtomicAddStore(t *testing.T) {
   264  	c := make(chan bool)
   265  	var a uint64
   266  	go func() {
   267  		atomic.AddUint64(&a, 1)
   268  		c <- true
   269  	}()
   270  	a = 42
   271  	<-c
   272  }
   273  
   274  // A nil pointer in an atomic operation should not deadlock
   275  // the rest of the program. Used to hang indefinitely.
   276  func TestNoRaceAtomicCrash(t *testing.T) {
   277  	var mutex sync.Mutex
   278  	var nilptr *int32
   279  	panics := 0
   280  	defer func() {
   281  		if x := recover(); x != nil {
   282  			mutex.Lock()
   283  			panics++
   284  			mutex.Unlock()
   285  		} else {
   286  			panic("no panic")
   287  		}
   288  	}()
   289  	atomic.AddInt32(nilptr, 1)
   290  }