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