"unsafe"
)
+// We use runtime.RaceRead() inside of atomic operations to catch races
+// between atomic and non-atomic operations. It will also catch races
+// between Mutex.Lock() and mutex overwrite (mu = Mutex{}). Since we use
+// only RaceRead() we won't catch races with non-atomic loads.
+// Otherwise (if we use RaceWrite()) we will report races
+// between atomic operations (false positives).
+
var mtx uint32 = 1 // same for all
func CompareAndSwapInt32(val *int32, old, new int32) bool {
func CompareAndSwapUint32(val *uint32, old, new uint32) (swapped bool) {
swapped = false
runtime.RaceSemacquire(&mtx)
+ runtime.RaceRead(unsafe.Pointer(val))
runtime.RaceAcquire(unsafe.Pointer(val))
if *val == old {
*val = new
func CompareAndSwapUint64(val *uint64, old, new uint64) (swapped bool) {
swapped = false
runtime.RaceSemacquire(&mtx)
+ runtime.RaceRead(unsafe.Pointer(val))
runtime.RaceAcquire(unsafe.Pointer(val))
if *val == old {
*val = new
func CompareAndSwapPointer(val *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool) {
swapped = false
runtime.RaceSemacquire(&mtx)
+ runtime.RaceRead(unsafe.Pointer(val))
runtime.RaceAcquire(unsafe.Pointer(val))
if *val == old {
*val = new
func CompareAndSwapUintptr(val *uintptr, old, new uintptr) (swapped bool) {
swapped = false
runtime.RaceSemacquire(&mtx)
+ runtime.RaceRead(unsafe.Pointer(val))
runtime.RaceAcquire(unsafe.Pointer(val))
if *val == old {
*val = new
func AddUint32(val *uint32, delta uint32) (new uint32) {
runtime.RaceSemacquire(&mtx)
+ runtime.RaceRead(unsafe.Pointer(val))
runtime.RaceAcquire(unsafe.Pointer(val))
*val = *val + delta
new = *val
func AddUint64(val *uint64, delta uint64) (new uint64) {
runtime.RaceSemacquire(&mtx)
+ runtime.RaceRead(unsafe.Pointer(val))
runtime.RaceAcquire(unsafe.Pointer(val))
*val = *val + delta
new = *val
func AddUintptr(val *uintptr, delta uintptr) (new uintptr) {
runtime.RaceSemacquire(&mtx)
+ runtime.RaceRead(unsafe.Pointer(val))
runtime.RaceAcquire(unsafe.Pointer(val))
*val = *val + delta
new = *val
func LoadUint32(addr *uint32) (val uint32) {
runtime.RaceSemacquire(&mtx)
+ runtime.RaceRead(unsafe.Pointer(addr))
runtime.RaceAcquire(unsafe.Pointer(addr))
val = *addr
runtime.RaceSemrelease(&mtx)
func LoadUint64(addr *uint64) (val uint64) {
runtime.RaceSemacquire(&mtx)
+ runtime.RaceRead(unsafe.Pointer(addr))
runtime.RaceAcquire(unsafe.Pointer(addr))
val = *addr
runtime.RaceSemrelease(&mtx)
func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer) {
runtime.RaceSemacquire(&mtx)
+ runtime.RaceRead(unsafe.Pointer(addr))
runtime.RaceAcquire(unsafe.Pointer(addr))
val = *addr
runtime.RaceSemrelease(&mtx)
func LoadUintptr(addr *uintptr) (val uintptr) {
runtime.RaceSemacquire(&mtx)
+ runtime.RaceRead(unsafe.Pointer(val))
runtime.RaceAcquire(unsafe.Pointer(addr))
val = *addr
runtime.RaceSemrelease(&mtx)
func StoreUint32(addr *uint32, val uint32) {
runtime.RaceSemacquire(&mtx)
+ runtime.RaceRead(unsafe.Pointer(addr))
*addr = val
runtime.RaceRelease(unsafe.Pointer(addr))
runtime.RaceSemrelease(&mtx)
func StoreUint64(addr *uint64, val uint64) {
runtime.RaceSemacquire(&mtx)
+ runtime.RaceRead(unsafe.Pointer(addr))
*addr = val
runtime.RaceRelease(unsafe.Pointer(addr))
runtime.RaceSemrelease(&mtx)
func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer) {
runtime.RaceSemacquire(&mtx)
+ runtime.RaceRead(unsafe.Pointer(val))
*addr = val
runtime.RaceRelease(unsafe.Pointer(addr))
runtime.RaceSemrelease(&mtx)
func StoreUintptr(addr *uintptr, val uintptr) {
runtime.RaceSemacquire(&mtx)
+ runtime.RaceRead(unsafe.Pointer(val))
*addr = val
runtime.RaceRelease(unsafe.Pointer(addr))
runtime.RaceSemrelease(&mtx)