1 // Copyright 2020 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.
5 // This file records the static ranks of the locks in the runtime. If a lock
6 // is not given a rank, then it is assumed to be a leaf lock, which means no other
7 // lock can be acquired while it is held. Therefore, leaf locks do not need to be
8 // given an explicit rank. We list all of the architecture-independent leaf locks
9 // for documentation purposes, but don't list any of the architecture-dependent
10 // locks (which are all leaf locks). debugLock is ignored for ranking, since it is used
11 // when printing out lock ranking errors.
13 // lockInit(l *mutex, rank int) is used to set the rank of lock before it is used.
14 // If there is no clear place to initialize a lock, then the rank of a lock can be
15 // specified during the lock call itself via lockWithrank(l *mutex, rank int).
17 // Besides the static lock ranking (which is a total ordering of the locks), we
18 // also represent and enforce the actual partial order among the locks in the
19 // arcs[] array below. That is, if it is possible that lock B can be acquired when
20 // lock A is the previous acquired lock that is still held, then there should be
21 // an entry for A in arcs[B][]. We will currently fail not only if the total order
22 // (the lock ranking) is violated, but also if there is a missing entry in the
29 // Constants representing the lock rank of the architecture-independent locks in
30 // the runtime. Locks with lower rank must be taken before locks with higher
33 lockRankDummy lockRank
= iota
35 // Locks held above sched
50 lockRankTimers
// Multiple timers locked simultaneously in destroy()
53 lockRankHchan
// Multiple hchans acquired in lock order in syncadjustsudogs()
76 // Memory-related non-leaf locks
81 // Memory-related leaf locks
87 // Generally, hchan must be acquired before gscan. But in one specific
88 // case (in syncadjustsudogs from markroot after the g has been suspended
89 // by suspendG), we allow gscan to be acquired, and then an hchan lock. To
90 // allow this case, we get this lockRankHchanLeaf rank in
91 // syncadjustsudogs(), rather than lockRankHchan. By using this special
92 // rank, we don't allow any further locks to be acquired other than more
97 // Leaf locks with no dependencies, so these constants are not actually used anywhere.
98 // There are other architecture-dependent leaf locks as well.
101 lockRankFaketimeState
108 // lockRankLeafRank is the rank of lock that does not have a declared rank, and hence is
110 const lockRankLeafRank lockRank
= 1000
112 // lockNames gives the names associated with each of the above ranks
113 var lockNames
= []string{
116 lockRankSysmon
: "sysmon",
117 lockRankScavenge
: "scavenge",
118 lockRankForcegc
: "forcegc",
119 lockRankSweepWaiters
: "sweepWaiters",
120 lockRankAssistQueue
: "assistQueue",
121 lockRankCpuprof
: "cpuprof",
122 lockRankSweep
: "sweep",
124 lockRankPollDesc
: "pollDesc",
125 lockRankSched
: "sched",
126 lockRankDeadlock
: "deadlock",
127 lockRankAllg
: "allg",
128 lockRankAllp
: "allp",
130 lockRankTimers
: "timers",
131 lockRankItab
: "itab",
132 lockRankReflectOffs
: "reflectOffs",
134 lockRankHchan
: "hchan",
135 lockRankTraceBuf
: "traceBuf",
137 lockRankNotifyList
: "notifyList",
138 lockRankTraceStrings
: "traceStrings",
139 lockRankMspanSpecial
: "mspanSpecial",
140 lockRankProf
: "prof",
141 lockRankGcBitsArenas
: "gcBitsArenas",
142 lockRankRoot
: "root",
143 lockRankTrace
: "trace",
144 lockRankTraceStackTab
: "traceStackTab",
145 lockRankNetpollInit
: "netpollInit",
147 lockRankRwmutexW
: "rwmutexW",
148 lockRankRwmutexR
: "rwmutexR",
150 lockRankSpanSetSpine
: "spanSetSpine",
151 lockRankGscan
: "gscan",
152 lockRankStackpool
: "stackpool",
153 lockRankStackLarge
: "stackLarge",
154 lockRankDefer
: "defer",
155 lockRankSudog
: "sudog",
157 lockRankWbufSpans
: "wbufSpans",
158 lockRankMheap
: "mheap",
159 lockRankMheapSpecial
: "mheapSpecial",
161 lockRankGlobalAlloc
: "globalAlloc.mutex",
162 lockRankPageAllocScav
: "pageAlloc.scav.lock",
164 lockRankGFree
: "gFree",
165 lockRankHchanLeaf
: "hchanLeaf",
166 lockRankPanic
: "panic",
168 lockRankNewmHandoff
: "newmHandoff.lock",
169 lockRankDebugPtrmask
: "debugPtrmask.lock",
170 lockRankFaketimeState
: "faketimeState.lock",
171 lockRankTicks
: "ticks.lock",
172 lockRankRaceFini
: "raceFiniLock",
173 lockRankPollCache
: "pollCache.lock",
174 lockRankDebug
: "debugLock",
177 func (rank lockRank
) String() string {
181 if rank
== lockRankLeafRank
{
184 return lockNames
[rank
]
187 // lockPartialOrder is a partial order among the various lock types, listing the
188 // immediate ordering that has actually been observed in the runtime. Each entry
189 // (which corresponds to a particular lock rank) specifies the list of locks
190 // that can already be held immediately "above" it.
192 // So, for example, the lockRankSched entry shows that all the locks preceding
193 // it in rank can actually be held. The allp lock shows that only the sysmon or
194 // sched lock can be held immediately above it when it is acquired.
195 var lockPartialOrder
[][]lockRank
= [][]lockRank
{
198 lockRankScavenge
: {lockRankSysmon
},
199 lockRankForcegc
: {lockRankSysmon
},
200 lockRankSweepWaiters
: {},
201 lockRankAssistQueue
: {},
204 lockRankPollDesc
: {},
205 lockRankSched
: {lockRankSysmon
, lockRankScavenge
, lockRankForcegc
, lockRankSweepWaiters
, lockRankAssistQueue
, lockRankCpuprof
, lockRankSweep
, lockRankPollDesc
},
206 lockRankDeadlock
: {lockRankDeadlock
},
207 lockRankAllg
: {lockRankSysmon
, lockRankSched
},
208 lockRankAllp
: {lockRankSysmon
, lockRankSched
},
209 lockRankTimers
: {lockRankSysmon
, lockRankScavenge
, lockRankPollDesc
, lockRankSched
, lockRankAllp
, lockRankTimers
},
211 lockRankReflectOffs
: {lockRankItab
},
212 lockRankHchan
: {lockRankScavenge
, lockRankSweep
, lockRankHchan
},
213 lockRankTraceBuf
: {lockRankSysmon
, lockRankScavenge
},
214 lockRankFin
: {lockRankSysmon
, lockRankScavenge
, lockRankSched
, lockRankAllg
, lockRankTimers
, lockRankReflectOffs
, lockRankHchan
, lockRankTraceBuf
},
215 lockRankNotifyList
: {},
216 lockRankTraceStrings
: {lockRankTraceBuf
},
217 lockRankMspanSpecial
: {lockRankSysmon
, lockRankScavenge
, lockRankAssistQueue
, lockRankCpuprof
, lockRankSweep
, lockRankSched
, lockRankAllg
, lockRankAllp
, lockRankTimers
, lockRankItab
, lockRankReflectOffs
, lockRankHchan
, lockRankTraceBuf
, lockRankNotifyList
, lockRankTraceStrings
},
218 lockRankProf
: {lockRankSysmon
, lockRankScavenge
, lockRankAssistQueue
, lockRankCpuprof
, lockRankSweep
, lockRankSched
, lockRankAllg
, lockRankAllp
, lockRankTimers
, lockRankItab
, lockRankReflectOffs
, lockRankHchan
, lockRankTraceBuf
, lockRankNotifyList
, lockRankTraceStrings
},
219 lockRankGcBitsArenas
: {lockRankSysmon
, lockRankScavenge
, lockRankAssistQueue
, lockRankCpuprof
, lockRankSched
, lockRankAllg
, lockRankTimers
, lockRankItab
, lockRankReflectOffs
, lockRankHchan
, lockRankTraceBuf
, lockRankNotifyList
, lockRankTraceStrings
},
221 lockRankTrace
: {lockRankSysmon
, lockRankScavenge
, lockRankForcegc
, lockRankAssistQueue
, lockRankSweep
, lockRankSched
, lockRankHchan
, lockRankTraceBuf
, lockRankTraceStrings
, lockRankRoot
},
222 lockRankTraceStackTab
: {lockRankScavenge
, lockRankForcegc
, lockRankSweepWaiters
, lockRankAssistQueue
, lockRankSweep
, lockRankSched
, lockRankAllg
, lockRankTimers
, lockRankHchan
, lockRankTraceBuf
, lockRankFin
, lockRankNotifyList
, lockRankTraceStrings
, lockRankRoot
, lockRankTrace
},
223 lockRankNetpollInit
: {lockRankTimers
},
225 lockRankRwmutexW
: {},
226 lockRankRwmutexR
: {lockRankSysmon
, lockRankRwmutexW
},
228 lockRankSpanSetSpine
: {lockRankSysmon
, lockRankScavenge
, lockRankForcegc
, lockRankAssistQueue
, lockRankCpuprof
, lockRankSweep
, lockRankPollDesc
, lockRankSched
, lockRankAllg
, lockRankAllp
, lockRankTimers
, lockRankItab
, lockRankReflectOffs
, lockRankHchan
, lockRankTraceBuf
, lockRankNotifyList
, lockRankTraceStrings
},
229 lockRankGscan
: {lockRankSysmon
, lockRankScavenge
, lockRankForcegc
, lockRankSweepWaiters
, lockRankAssistQueue
, lockRankCpuprof
, lockRankSweep
, lockRankPollDesc
, lockRankSched
, lockRankTimers
, lockRankItab
, lockRankReflectOffs
, lockRankHchan
, lockRankTraceBuf
, lockRankFin
, lockRankNotifyList
, lockRankTraceStrings
, lockRankProf
, lockRankGcBitsArenas
, lockRankRoot
, lockRankTrace
, lockRankTraceStackTab
, lockRankNetpollInit
, lockRankSpanSetSpine
},
230 lockRankStackpool
: {lockRankSysmon
, lockRankScavenge
, lockRankSweepWaiters
, lockRankAssistQueue
, lockRankCpuprof
, lockRankSweep
, lockRankPollDesc
, lockRankSched
, lockRankTimers
, lockRankItab
, lockRankReflectOffs
, lockRankHchan
, lockRankTraceBuf
, lockRankFin
, lockRankNotifyList
, lockRankTraceStrings
, lockRankProf
, lockRankGcBitsArenas
, lockRankRoot
, lockRankTrace
, lockRankTraceStackTab
, lockRankNetpollInit
, lockRankRwmutexR
, lockRankSpanSetSpine
, lockRankGscan
},
231 lockRankStackLarge
: {lockRankSysmon
, lockRankAssistQueue
, lockRankSched
, lockRankItab
, lockRankHchan
, lockRankProf
, lockRankGcBitsArenas
, lockRankRoot
, lockRankSpanSetSpine
, lockRankGscan
},
233 lockRankSudog
: {lockRankHchan
, lockRankNotifyList
},
234 lockRankWbufSpans
: {lockRankSysmon
, lockRankScavenge
, lockRankSweepWaiters
, lockRankAssistQueue
, lockRankSweep
, lockRankPollDesc
, lockRankSched
, lockRankAllg
, lockRankTimers
, lockRankItab
, lockRankReflectOffs
, lockRankHchan
, lockRankFin
, lockRankNotifyList
, lockRankTraceStrings
, lockRankMspanSpecial
, lockRankProf
, lockRankRoot
, lockRankGscan
, lockRankDefer
, lockRankSudog
},
235 lockRankMheap
: {lockRankSysmon
, lockRankScavenge
, lockRankSweepWaiters
, lockRankAssistQueue
, lockRankCpuprof
, lockRankSweep
, lockRankPollDesc
, lockRankSched
, lockRankAllg
, lockRankAllp
, lockRankTimers
, lockRankItab
, lockRankReflectOffs
, lockRankHchan
, lockRankTraceBuf
, lockRankFin
, lockRankNotifyList
, lockRankTraceStrings
, lockRankMspanSpecial
, lockRankProf
, lockRankGcBitsArenas
, lockRankRoot
, lockRankSpanSetSpine
, lockRankGscan
, lockRankStackpool
, lockRankStackLarge
, lockRankDefer
, lockRankSudog
, lockRankWbufSpans
},
236 lockRankMheapSpecial
: {lockRankSysmon
, lockRankScavenge
, lockRankAssistQueue
, lockRankCpuprof
, lockRankSweep
, lockRankPollDesc
, lockRankSched
, lockRankAllg
, lockRankAllp
, lockRankTimers
, lockRankItab
, lockRankReflectOffs
, lockRankHchan
, lockRankTraceBuf
, lockRankNotifyList
, lockRankTraceStrings
},
237 lockRankGlobalAlloc
: {lockRankProf
, lockRankSpanSetSpine
, lockRankMheap
, lockRankMheapSpecial
},
238 lockRankPageAllocScav
: {lockRankMheap
},
240 lockRankGFree
: {lockRankSched
},
241 lockRankHchanLeaf
: {lockRankGscan
, lockRankHchanLeaf
},
242 lockRankPanic
: {lockRankDeadlock
}, // plus any other lock held on throw.
244 lockRankNewmHandoff
: {},
245 lockRankDebugPtrmask
: {},
246 lockRankFaketimeState
: {},
248 lockRankRaceFini
: {},
249 lockRankPollCache
: {},