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 func TestRaceAtomicStoreLoad(t *testing.T) { 229 c := make(chan bool) 230 var a uint64 231 go func() { 232 atomic.StoreUint64(&a, 1) 233 c <- true 234 }() 235 _ = a 236 <-c 237 } 238 239 func TestRaceAtomicLoadStore(t *testing.T) { 240 c := make(chan bool) 241 var a uint64 242 go func() { 243 _ = atomic.LoadUint64(&a) 244 c <- true 245 }() 246 a = 1 247 <-c 248 } 249 250 func TestRaceAtomicAddLoad(t *testing.T) { 251 c := make(chan bool) 252 var a uint64 253 go func() { 254 atomic.AddUint64(&a, 1) 255 c <- true 256 }() 257 _ = a 258 <-c 259 } 260 261 func TestRaceAtomicAddStore(t *testing.T) { 262 c := make(chan bool) 263 var a uint64 264 go func() { 265 atomic.AddUint64(&a, 1) 266 c <- true 267 }() 268 a = 42 269 <-c 270 } 271 272 // A nil pointer in an atomic operation should not deadlock 273 // the rest of the program. Used to hang indefinitely. 274 func TestNoRaceAtomicCrash(t *testing.T) { 275 var mutex sync.Mutex 276 var nilptr *int32 277 panics := 0 278 defer func() { 279 if x := recover(); x != nil { 280 mutex.Lock() 281 panics++ 282 mutex.Unlock() 283 } else { 284 panic("no panic") 285 } 286 }() 287 atomic.AddInt32(nilptr, 1) 288 } 289