Source file
src/runtime/lockrank_on.go
Documentation: runtime
1
2
3
4
5
6
7 package runtime
8
9 import (
10 "internal/runtime/atomic"
11 "unsafe"
12 )
13
14 const staticLockRanking = true
15
16
17
18 var worldIsStopped atomic.Uint32
19
20
21 type lockRankStruct struct {
22
23 rank lockRank
24 }
25
26
27
28
29 func lockInit(l *mutex, rank lockRank) {
30 l.rank = rank
31 }
32
33 func getLockRank(l *mutex) lockRank {
34 return l.rank
35 }
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 func lockWithRank(l *mutex, rank lockRank) {
51 if l == &debuglock || l == &paniclk || l == &raceFiniLock {
52
53
54
55
56
57
58
59
60
61
62
63
64
65 lock2(l)
66 return
67 }
68 if rank == 0 {
69 rank = lockRankLeafRank
70 }
71 gp := getg()
72
73 systemstack(func() {
74 i := gp.m.locksHeldLen
75 if i >= len(gp.m.locksHeld) {
76 throw("too many locks held concurrently for rank checking")
77 }
78 gp.m.locksHeld[i].rank = rank
79 gp.m.locksHeld[i].lockAddr = uintptr(unsafe.Pointer(l))
80 gp.m.locksHeldLen++
81
82
83 if i > 0 {
84 checkRanks(gp, gp.m.locksHeld[i-1].rank, rank)
85 }
86 lock2(l)
87 })
88 }
89
90
91
92
93 func printHeldLocks(gp *g) {
94 if gp.m.locksHeldLen == 0 {
95 println("<none>")
96 return
97 }
98
99 for j, held := range gp.m.locksHeld[:gp.m.locksHeldLen] {
100 println(j, ":", held.rank.String(), held.rank, unsafe.Pointer(gp.m.locksHeld[j].lockAddr))
101 }
102 }
103
104
105
106
107
108
109
110
111
112 func acquireLockRankAndM(rank lockRank) {
113 mp := acquirem()
114 mp.locks += mutexMLocksDelta
115
116 gp := getg()
117
118 systemstack(func() {
119 i := gp.m.locksHeldLen
120 if i >= len(gp.m.locksHeld) {
121 throw("too many locks held concurrently for rank checking")
122 }
123 gp.m.locksHeld[i].rank = rank
124 gp.m.locksHeld[i].lockAddr = 0
125 gp.m.locksHeldLen++
126
127
128 if i > 0 {
129 checkRanks(gp, gp.m.locksHeld[i-1].rank, rank)
130 }
131 })
132 }
133
134
135
136
137
138 func checkRanks(gp *g, prevRank, rank lockRank) {
139 rankOK := false
140 if rank < prevRank {
141
142 rankOK = false
143 } else if rank == lockRankLeafRank {
144
145
146 rankOK = prevRank < lockRankLeafRank
147 } else {
148
149
150
151
152
153 list := lockPartialOrder[rank]
154 for _, entry := range list {
155 if entry == prevRank {
156 rankOK = true
157 break
158 }
159 }
160 }
161 if !rankOK {
162 printlock()
163 println(gp.m.procid, " ======")
164 printHeldLocks(gp)
165 throw("lock ordering problem")
166 }
167 }
168
169
170 func unlockWithRank(l *mutex) {
171 if l == &debuglock || l == &paniclk || l == &raceFiniLock {
172
173 unlock2(l)
174 return
175 }
176 gp := getg()
177 systemstack(func() {
178 found := false
179 for i := gp.m.locksHeldLen - 1; i >= 0; i-- {
180 if gp.m.locksHeld[i].lockAddr == uintptr(unsafe.Pointer(l)) {
181 found = true
182 copy(gp.m.locksHeld[i:gp.m.locksHeldLen-1], gp.m.locksHeld[i+1:gp.m.locksHeldLen])
183 gp.m.locksHeldLen--
184 break
185 }
186 }
187 if !found {
188 println(gp.m.procid, ":", l.rank.String(), l.rank, l)
189 throw("unlock without matching lock acquire")
190 }
191 unlock2(l)
192 })
193 }
194
195
196
197
198
199
200
201
202 func releaseLockRankAndM(rank lockRank) {
203 gp := getg()
204 systemstack(func() {
205 found := false
206 for i := gp.m.locksHeldLen - 1; i >= 0; i-- {
207 if gp.m.locksHeld[i].rank == rank && gp.m.locksHeld[i].lockAddr == 0 {
208 found = true
209 copy(gp.m.locksHeld[i:gp.m.locksHeldLen-1], gp.m.locksHeld[i+1:gp.m.locksHeldLen])
210 gp.m.locksHeldLen--
211 break
212 }
213 }
214 if !found {
215 println(gp.m.procid, ":", rank.String(), rank)
216 throw("lockRank release without matching lockRank acquire")
217 }
218 })
219
220 mp := getg().m
221 mp.locks -= mutexMLocksDelta
222 releasem(mp)
223 }
224
225
226
227
228 func lockWithRankMayAcquire(l *mutex, rank lockRank) {
229 gp := getg()
230 if gp.m.locksHeldLen == 0 {
231
232 return
233 }
234
235 systemstack(func() {
236 i := gp.m.locksHeldLen
237 if i >= len(gp.m.locksHeld) {
238 throw("too many locks held concurrently for rank checking")
239 }
240
241
242
243 gp.m.locksHeld[i].rank = rank
244 gp.m.locksHeld[i].lockAddr = uintptr(unsafe.Pointer(l))
245 gp.m.locksHeldLen++
246 checkRanks(gp, gp.m.locksHeld[i-1].rank, rank)
247 gp.m.locksHeldLen--
248 })
249 }
250
251
252
253
254 func checkLockHeld(gp *g, l *mutex) bool {
255 for i := gp.m.locksHeldLen - 1; i >= 0; i-- {
256 if gp.m.locksHeld[i].lockAddr == uintptr(unsafe.Pointer(l)) {
257 return true
258 }
259 }
260 return false
261 }
262
263
264
265
266
267
268 func assertLockHeld(l *mutex) {
269 gp := getg()
270
271 held := checkLockHeld(gp, l)
272 if held {
273 return
274 }
275
276
277
278 systemstack(func() {
279 printlock()
280 print("caller requires lock ", l, " (rank ", l.rank.String(), "), holding:\n")
281 printHeldLocks(gp)
282 throw("not holding required lock!")
283 })
284 }
285
286
287
288
289
290
291
292
293
294 func assertRankHeld(r lockRank) {
295 gp := getg()
296
297 for i := gp.m.locksHeldLen - 1; i >= 0; i-- {
298 if gp.m.locksHeld[i].rank == r {
299 return
300 }
301 }
302
303
304
305 systemstack(func() {
306 printlock()
307 print("caller requires lock with rank ", r.String(), "), holding:\n")
308 printHeldLocks(gp)
309 throw("not holding required lock!")
310 })
311 }
312
313
314
315
316
317
318
319
320 func worldStopped() {
321 if stopped := worldIsStopped.Add(1); stopped != 1 {
322 systemstack(func() {
323 print("world stop count=", stopped, "\n")
324 throw("recursive world stop")
325 })
326 }
327 }
328
329
330
331
332
333
334
335
336 func worldStarted() {
337 if stopped := worldIsStopped.Add(-1); stopped != 0 {
338 systemstack(func() {
339 print("world stop count=", stopped, "\n")
340 throw("released non-stopped world stop")
341 })
342 }
343 }
344
345
346
347
348 func checkWorldStopped() bool {
349 stopped := worldIsStopped.Load()
350 if stopped > 1 {
351 systemstack(func() {
352 print("inconsistent world stop count=", stopped, "\n")
353 throw("inconsistent world stop count")
354 })
355 }
356
357 return stopped == 1
358 }
359
360
361
362
363
364
365
366 func assertWorldStopped() {
367 if checkWorldStopped() {
368 return
369 }
370
371 throw("world not stopped")
372 }
373
374
375
376
377
378
379
380 func assertWorldStoppedOrLockHeld(l *mutex) {
381 if checkWorldStopped() {
382 return
383 }
384
385 gp := getg()
386 held := checkLockHeld(gp, l)
387 if held {
388 return
389 }
390
391
392
393 systemstack(func() {
394 printlock()
395 print("caller requires world stop or lock ", l, " (rank ", l.rank.String(), "), holding:\n")
396 println("<no world stop>")
397 printHeldLocks(gp)
398 throw("no world stop or required lock!")
399 })
400 }
401
View as plain text