1
2
3
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 _ = x1 + x2
18 var s int64
19 ch := make(chan bool, 2)
20 go func() {
21 x1 = 1
22 if atomic.AddInt64(&s, 1) == 2 {
23 x2 = 1
24 }
25 ch <- true
26 }()
27 go func() {
28 x2 = 1
29 if atomic.AddInt64(&s, 1) == 2 {
30 x1 = 1
31 }
32 ch <- true
33 }()
34 <-ch
35 <-ch
36 }
37
38 func TestRaceAtomicAddInt64(t *testing.T) {
39 var x1, x2 int8
40 _ = x1 + x2
41 var s int64
42 ch := make(chan bool, 2)
43 go func() {
44 x1 = 1
45 if atomic.AddInt64(&s, 1) == 1 {
46 x2 = 1
47 }
48 ch <- true
49 }()
50 go func() {
51 x2 = 1
52 if atomic.AddInt64(&s, 1) == 1 {
53 x1 = 1
54 }
55 ch <- true
56 }()
57 <-ch
58 <-ch
59 }
60
61 func TestNoRaceAtomicAddInt32(t *testing.T) {
62 var x1, x2 int8
63 _ = x1 + x2
64 var s int32
65 ch := make(chan bool, 2)
66 go func() {
67 x1 = 1
68 if atomic.AddInt32(&s, 1) == 2 {
69 x2 = 1
70 }
71 ch <- true
72 }()
73 go func() {
74 x2 = 1
75 if atomic.AddInt32(&s, 1) == 2 {
76 x1 = 1
77 }
78 ch <- true
79 }()
80 <-ch
81 <-ch
82 }
83
84 func TestNoRaceAtomicLoadAddInt32(t *testing.T) {
85 var x int64
86 _ = x
87 var s int32
88 go func() {
89 x = 2
90 atomic.AddInt32(&s, 1)
91 }()
92 for atomic.LoadInt32(&s) != 1 {
93 runtime.Gosched()
94 }
95 x = 1
96 }
97
98 func TestNoRaceAtomicLoadStoreInt32(t *testing.T) {
99 var x int64
100 _ = x
101 var s int32
102 go func() {
103 x = 2
104 atomic.StoreInt32(&s, 1)
105 }()
106 for atomic.LoadInt32(&s) != 1 {
107 runtime.Gosched()
108 }
109 x = 1
110 }
111
112 func TestNoRaceAtomicStoreCASInt32(t *testing.T) {
113 var x int64
114 _ = x
115 var s int32
116 go func() {
117 x = 2
118 atomic.StoreInt32(&s, 1)
119 }()
120 for !atomic.CompareAndSwapInt32(&s, 1, 0) {
121 runtime.Gosched()
122 }
123 x = 1
124 }
125
126 func TestNoRaceAtomicCASLoadInt32(t *testing.T) {
127 var x int64
128 _ = x
129 var s int32
130 go func() {
131 x = 2
132 if !atomic.CompareAndSwapInt32(&s, 0, 1) {
133 panic("")
134 }
135 }()
136 for atomic.LoadInt32(&s) != 1 {
137 runtime.Gosched()
138 }
139 x = 1
140 }
141
142 func TestNoRaceAtomicCASCASInt32(t *testing.T) {
143 var x int64
144 _ = x
145 var s int32
146 go func() {
147 x = 2
148 if !atomic.CompareAndSwapInt32(&s, 0, 1) {
149 panic("")
150 }
151 }()
152 for !atomic.CompareAndSwapInt32(&s, 1, 0) {
153 runtime.Gosched()
154 }
155 x = 1
156 }
157
158 func TestNoRaceAtomicCASCASInt32_2(t *testing.T) {
159 var x1, x2 int8
160 _ = x1 + x2
161 var s int32
162 ch := make(chan bool, 2)
163 go func() {
164 x1 = 1
165 if !atomic.CompareAndSwapInt32(&s, 0, 1) {
166 x2 = 1
167 }
168 ch <- true
169 }()
170 go func() {
171 x2 = 1
172 if !atomic.CompareAndSwapInt32(&s, 0, 1) {
173 x1 = 1
174 }
175 ch <- true
176 }()
177 <-ch
178 <-ch
179 }
180
181 func TestNoRaceAtomicLoadInt64(t *testing.T) {
182 var x int32
183 _ = x
184 var s int64
185 go func() {
186 x = 2
187 atomic.AddInt64(&s, 1)
188 }()
189 for atomic.LoadInt64(&s) != 1 {
190 runtime.Gosched()
191 }
192 x = 1
193 }
194
195 func TestNoRaceAtomicCASCASUInt64(t *testing.T) {
196 var x int64
197 _ = x
198 var s uint64
199 go func() {
200 x = 2
201 if !atomic.CompareAndSwapUint64(&s, 0, 1) {
202 panic("")
203 }
204 }()
205 for !atomic.CompareAndSwapUint64(&s, 1, 0) {
206 runtime.Gosched()
207 }
208 x = 1
209 }
210
211 func TestNoRaceAtomicLoadStorePointer(t *testing.T) {
212 var x int64
213 _ = x
214 var s unsafe.Pointer
215 var y int = 2
216 var p unsafe.Pointer = unsafe.Pointer(&y)
217 go func() {
218 x = 2
219 atomic.StorePointer(&s, p)
220 }()
221 for atomic.LoadPointer(&s) != p {
222 runtime.Gosched()
223 }
224 x = 1
225 }
226
227 func TestNoRaceAtomicStoreCASUint64(t *testing.T) {
228 var x int64
229 _ = x
230 var s uint64
231 go func() {
232 x = 2
233 atomic.StoreUint64(&s, 1)
234 }()
235 for !atomic.CompareAndSwapUint64(&s, 1, 0) {
236 runtime.Gosched()
237 }
238 x = 1
239 }
240
241 func TestRaceAtomicStoreLoad(t *testing.T) {
242 c := make(chan bool)
243 var a uint64
244 go func() {
245 atomic.StoreUint64(&a, 1)
246 c <- true
247 }()
248 _ = a
249 <-c
250 }
251
252 func TestRaceAtomicLoadStore(t *testing.T) {
253 c := make(chan bool)
254 var a uint64
255 go func() {
256 _ = atomic.LoadUint64(&a)
257 c <- true
258 }()
259 a = 1
260 <-c
261 }
262
263 func TestRaceAtomicAddLoad(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
271 <-c
272 }
273
274 func TestRaceAtomicAddStore(t *testing.T) {
275 c := make(chan bool)
276 var a uint64
277 go func() {
278 atomic.AddUint64(&a, 1)
279 c <- true
280 }()
281 a = 42
282 <-c
283 }
284
285
286
287 func TestNoRaceAtomicCrash(t *testing.T) {
288 var mutex sync.Mutex
289 var nilptr *int32
290 panics := 0
291 defer func() {
292 if x := recover(); x != nil {
293 mutex.Lock()
294 panics++
295 mutex.Unlock()
296 } else {
297 panic("no panic")
298 }
299 }()
300 atomic.AddInt32(nilptr, 1)
301 }
302
303 func TestNoRaceDeferAtomicStore(t *testing.T) {
304
305
306 type foo struct {
307 bar int64
308 }
309
310 var doFork func(f *foo, depth int)
311 doFork = func(f *foo, depth int) {
312 atomic.StoreInt64(&f.bar, 1)
313 defer atomic.StoreInt64(&f.bar, 0)
314 if depth > 0 {
315 for i := 0; i < 2; i++ {
316 f2 := &foo{}
317 go doFork(f2, depth-1)
318 }
319 }
320 runtime.GC()
321 }
322
323 f := &foo{}
324 doFork(f, 11)
325 }
326
View as plain text