...
Run Format

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

Documentation: runtime/race/testdata

  // 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)
  }
  

View as plain text