github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/sync/atomic/race.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  // +build race
     6  
     7  package atomic
     8  
     9  import (
    10  	"runtime"
    11  	"unsafe"
    12  )
    13  
    14  // We use runtime.RaceRead() inside of atomic operations to catch races
    15  // between atomic and non-atomic operations.  It will also catch races
    16  // between Mutex.Lock() and mutex overwrite (mu = Mutex{}).  Since we use
    17  // only RaceRead() we won't catch races with non-atomic loads.
    18  // Otherwise (if we use RaceWrite()) we will report races
    19  // between atomic operations (false positives).
    20  
    21  var mtx uint32 = 1 // same for all
    22  
    23  func CompareAndSwapInt32(val *int32, old, new int32) bool {
    24  	return CompareAndSwapUint32((*uint32)(unsafe.Pointer(val)), uint32(old), uint32(new))
    25  }
    26  
    27  func CompareAndSwapUint32(val *uint32, old, new uint32) (swapped bool) {
    28  	_ = *val
    29  	swapped = false
    30  	runtime.RaceSemacquire(&mtx)
    31  	runtime.RaceRead(unsafe.Pointer(val))
    32  	runtime.RaceAcquire(unsafe.Pointer(val))
    33  	if *val == old {
    34  		*val = new
    35  		swapped = true
    36  		runtime.RaceReleaseMerge(unsafe.Pointer(val))
    37  	}
    38  	runtime.RaceSemrelease(&mtx)
    39  	return
    40  }
    41  
    42  func CompareAndSwapInt64(val *int64, old, new int64) bool {
    43  	return CompareAndSwapUint64((*uint64)(unsafe.Pointer(val)), uint64(old), uint64(new))
    44  }
    45  
    46  func CompareAndSwapUint64(val *uint64, old, new uint64) (swapped bool) {
    47  	_ = *val
    48  	swapped = false
    49  	runtime.RaceSemacquire(&mtx)
    50  	runtime.RaceRead(unsafe.Pointer(val))
    51  	runtime.RaceAcquire(unsafe.Pointer(val))
    52  	if *val == old {
    53  		*val = new
    54  		swapped = true
    55  		runtime.RaceReleaseMerge(unsafe.Pointer(val))
    56  	}
    57  	runtime.RaceSemrelease(&mtx)
    58  	return
    59  }
    60  
    61  func CompareAndSwapPointer(val *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool) {
    62  	_ = *val
    63  	swapped = false
    64  	runtime.RaceSemacquire(&mtx)
    65  	runtime.RaceRead(unsafe.Pointer(val))
    66  	runtime.RaceAcquire(unsafe.Pointer(val))
    67  	if *val == old {
    68  		*val = new
    69  		swapped = true
    70  		runtime.RaceReleaseMerge(unsafe.Pointer(val))
    71  	}
    72  	runtime.RaceSemrelease(&mtx)
    73  	return
    74  }
    75  
    76  func CompareAndSwapUintptr(val *uintptr, old, new uintptr) (swapped bool) {
    77  	_ = *val
    78  	swapped = false
    79  	runtime.RaceSemacquire(&mtx)
    80  	runtime.RaceRead(unsafe.Pointer(val))
    81  	runtime.RaceAcquire(unsafe.Pointer(val))
    82  	if *val == old {
    83  		*val = new
    84  		swapped = true
    85  		runtime.RaceReleaseMerge(unsafe.Pointer(val))
    86  	}
    87  	runtime.RaceSemrelease(&mtx)
    88  	return
    89  }
    90  
    91  func AddInt32(val *int32, delta int32) int32 {
    92  	return int32(AddUint32((*uint32)(unsafe.Pointer(val)), uint32(delta)))
    93  }
    94  
    95  func AddUint32(val *uint32, delta uint32) (new uint32) {
    96  	_ = *val
    97  	runtime.RaceSemacquire(&mtx)
    98  	runtime.RaceRead(unsafe.Pointer(val))
    99  	runtime.RaceAcquire(unsafe.Pointer(val))
   100  	*val = *val + delta
   101  	new = *val
   102  	runtime.RaceReleaseMerge(unsafe.Pointer(val))
   103  	runtime.RaceSemrelease(&mtx)
   104  
   105  	return
   106  }
   107  
   108  func AddInt64(val *int64, delta int64) int64 {
   109  	return int64(AddUint64((*uint64)(unsafe.Pointer(val)), uint64(delta)))
   110  }
   111  
   112  func AddUint64(val *uint64, delta uint64) (new uint64) {
   113  	_ = *val
   114  	runtime.RaceSemacquire(&mtx)
   115  	runtime.RaceRead(unsafe.Pointer(val))
   116  	runtime.RaceAcquire(unsafe.Pointer(val))
   117  	*val = *val + delta
   118  	new = *val
   119  	runtime.RaceReleaseMerge(unsafe.Pointer(val))
   120  	runtime.RaceSemrelease(&mtx)
   121  
   122  	return
   123  }
   124  
   125  func AddUintptr(val *uintptr, delta uintptr) (new uintptr) {
   126  	_ = *val
   127  	runtime.RaceSemacquire(&mtx)
   128  	runtime.RaceRead(unsafe.Pointer(val))
   129  	runtime.RaceAcquire(unsafe.Pointer(val))
   130  	*val = *val + delta
   131  	new = *val
   132  	runtime.RaceReleaseMerge(unsafe.Pointer(val))
   133  	runtime.RaceSemrelease(&mtx)
   134  
   135  	return
   136  }
   137  
   138  func LoadInt32(addr *int32) int32 {
   139  	return int32(LoadUint32((*uint32)(unsafe.Pointer(addr))))
   140  }
   141  
   142  func LoadUint32(addr *uint32) (val uint32) {
   143  	_ = *addr
   144  	runtime.RaceSemacquire(&mtx)
   145  	runtime.RaceRead(unsafe.Pointer(addr))
   146  	runtime.RaceAcquire(unsafe.Pointer(addr))
   147  	val = *addr
   148  	runtime.RaceSemrelease(&mtx)
   149  	return
   150  }
   151  
   152  func LoadInt64(addr *int64) int64 {
   153  	return int64(LoadUint64((*uint64)(unsafe.Pointer(addr))))
   154  }
   155  
   156  func LoadUint64(addr *uint64) (val uint64) {
   157  	_ = *addr
   158  	runtime.RaceSemacquire(&mtx)
   159  	runtime.RaceRead(unsafe.Pointer(addr))
   160  	runtime.RaceAcquire(unsafe.Pointer(addr))
   161  	val = *addr
   162  	runtime.RaceSemrelease(&mtx)
   163  	return
   164  }
   165  
   166  func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer) {
   167  	_ = *addr
   168  	runtime.RaceSemacquire(&mtx)
   169  	runtime.RaceRead(unsafe.Pointer(addr))
   170  	runtime.RaceAcquire(unsafe.Pointer(addr))
   171  	val = *addr
   172  	runtime.RaceSemrelease(&mtx)
   173  	return
   174  }
   175  
   176  func LoadUintptr(addr *uintptr) (val uintptr) {
   177  	_ = *addr
   178  	runtime.RaceSemacquire(&mtx)
   179  	runtime.RaceRead(unsafe.Pointer(addr))
   180  	runtime.RaceAcquire(unsafe.Pointer(addr))
   181  	val = *addr
   182  	runtime.RaceSemrelease(&mtx)
   183  	return
   184  }
   185  
   186  func StoreInt32(addr *int32, val int32) {
   187  	StoreUint32((*uint32)(unsafe.Pointer(addr)), uint32(val))
   188  }
   189  
   190  func StoreUint32(addr *uint32, val uint32) {
   191  	_ = *addr
   192  	runtime.RaceSemacquire(&mtx)
   193  	runtime.RaceRead(unsafe.Pointer(addr))
   194  	*addr = val
   195  	runtime.RaceRelease(unsafe.Pointer(addr))
   196  	runtime.RaceSemrelease(&mtx)
   197  }
   198  
   199  func StoreInt64(addr *int64, val int64) {
   200  	StoreUint64((*uint64)(unsafe.Pointer(addr)), uint64(val))
   201  }
   202  
   203  func StoreUint64(addr *uint64, val uint64) {
   204  	_ = *addr
   205  	runtime.RaceSemacquire(&mtx)
   206  	runtime.RaceRead(unsafe.Pointer(addr))
   207  	*addr = val
   208  	runtime.RaceRelease(unsafe.Pointer(addr))
   209  	runtime.RaceSemrelease(&mtx)
   210  }
   211  
   212  func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer) {
   213  	_ = *addr
   214  	runtime.RaceSemacquire(&mtx)
   215  	runtime.RaceRead(unsafe.Pointer(addr))
   216  	*addr = val
   217  	runtime.RaceRelease(unsafe.Pointer(addr))
   218  	runtime.RaceSemrelease(&mtx)
   219  }
   220  
   221  func StoreUintptr(addr *uintptr, val uintptr) {
   222  	_ = *addr
   223  	runtime.RaceSemacquire(&mtx)
   224  	runtime.RaceRead(unsafe.Pointer(addr))
   225  	*addr = val
   226  	runtime.RaceRelease(unsafe.Pointer(addr))
   227  	runtime.RaceSemrelease(&mtx)
   228  }