Source file src/runtime/race/testdata/atomic_test.go

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

View as plain text