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 }