| // Copyright 2020 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| // This file records the static ranks of the locks in the runtime. If a lock | |
| // is not given a rank, then it is assumed to be a leaf lock, which means no other | |
| // lock can be acquired while it is held. Therefore, leaf locks do not need to be | |
| // given an explicit rank. We list all of the architecture-independent leaf locks | |
| // for documentation purposes, but don't list any of the architecture-dependent | |
| // locks (which are all leaf locks). debugLock is ignored for ranking, since it is used | |
| // when printing out lock ranking errors. | |
| // | |
| // lockInit(l *mutex, rank int) is used to set the rank of lock before it is used. | |
| // If there is no clear place to initialize a lock, then the rank of a lock can be | |
| // specified during the lock call itself via lockWithrank(l *mutex, rank int). | |
| // | |
| // Besides the static lock ranking (which is a total ordering of the locks), we | |
| // also represent and enforce the actual partial order among the locks in the | |
| // arcs[] array below. That is, if it is possible that lock B can be acquired when | |
| // lock A is the previous acquired lock that is still held, then there should be | |
| // an entry for A in arcs[B][]. We will currently fail not only if the total order | |
| // (the lock ranking) is violated, but also if there is a missing entry in the | |
| // partial order. | |
| package runtime | |
| type lockRank int | |
| // Constants representing the lock rank of the architecture-independent locks in | |
| // the runtime. Locks with lower rank must be taken before locks with higher | |
| // rank. | |
| const ( | |
| lockRankDummy lockRank = iota | |
| // Locks held above sched | |
| lockRankSysmon | |
| lockRankScavenge | |
| lockRankForcegc | |
| lockRankSweepWaiters | |
| lockRankAssistQueue | |
| lockRankCpuprof | |
| lockRankSweep | |
| lockRankPollDesc | |
| lockRankSched | |
| lockRankDeadlock | |
| lockRankPanic | |
| lockRankAllg | |
| lockRankAllp | |
| lockRankTimers // Multiple timers locked simultaneously in destroy() | |
| lockRankItab | |
| lockRankReflectOffs | |
| lockRankHchan // Multiple hchans acquired in lock order in syncadjustsudogs() | |
| lockRankFin | |
| lockRankNotifyList | |
| lockRankTraceBuf | |
| lockRankTraceStrings | |
| lockRankMspanSpecial | |
| lockRankProf | |
| lockRankGcBitsArenas | |
| lockRankRoot | |
| lockRankTrace | |
| lockRankTraceStackTab | |
| lockRankNetpollInit | |
| lockRankRwmutexW | |
| lockRankRwmutexR | |
| lockRankSpanSetSpine | |
| lockRankGscan | |
| lockRankStackpool | |
| lockRankStackLarge | |
| lockRankDefer | |
| lockRankSudog | |
| // Memory-related non-leaf locks | |
| lockRankWbufSpans | |
| lockRankMheap | |
| lockRankMheapSpecial | |
| // Memory-related leaf locks | |
| lockRankGlobalAlloc | |
| // Other leaf locks | |
| lockRankGFree | |
| // Generally, hchan must be acquired before gscan. But in one specific | |
| // case (in syncadjustsudogs from markroot after the g has been suspended | |
| // by suspendG), we allow gscan to be acquired, and then an hchan lock. To | |
| // allow this case, we get this lockRankHchanLeaf rank in | |
| // syncadjustsudogs(), rather than lockRankHchan. By using this special | |
| // rank, we don't allow any further locks to be acquired other than more | |
| // hchan locks. | |
| lockRankHchanLeaf | |
| // Leaf locks with no dependencies, so these constants are not actually used anywhere. | |
| // There are other architecture-dependent leaf locks as well. | |
| lockRankNewmHandoff | |
| lockRankDebugPtrmask | |
| lockRankFaketimeState | |
| lockRankTicks | |
| lockRankRaceFini | |
| lockRankPollCache | |
| lockRankDebug | |
| ) | |
| // lockRankLeafRank is the rank of lock that does not have a declared rank, and hence is | |
| // a leaf lock. | |
| const lockRankLeafRank lockRank = 1000 | |
| // lockNames gives the names associated with each of the above ranks | |
| var lockNames = []string{ | |
| lockRankDummy: "", | |
| lockRankSysmon: "sysmon", | |
| lockRankScavenge: "scavenge", | |
| lockRankForcegc: "forcegc", | |
| lockRankSweepWaiters: "sweepWaiters", | |
| lockRankAssistQueue: "assistQueue", | |
| lockRankCpuprof: "cpuprof", | |
| lockRankSweep: "sweep", | |
| lockRankPollDesc: "pollDesc", | |
| lockRankSched: "sched", | |
| lockRankDeadlock: "deadlock", | |
| lockRankPanic: "panic", | |
| lockRankAllg: "allg", | |
| lockRankAllp: "allp", | |
| lockRankTimers: "timers", | |
| lockRankItab: "itab", | |
| lockRankReflectOffs: "reflectOffs", | |
| lockRankHchan: "hchan", | |
| lockRankFin: "fin", | |
| lockRankNotifyList: "notifyList", | |
| lockRankTraceBuf: "traceBuf", | |
| lockRankTraceStrings: "traceStrings", | |
| lockRankMspanSpecial: "mspanSpecial", | |
| lockRankProf: "prof", | |
| lockRankGcBitsArenas: "gcBitsArenas", | |
| lockRankRoot: "root", | |
| lockRankTrace: "trace", | |
| lockRankTraceStackTab: "traceStackTab", | |
| lockRankNetpollInit: "netpollInit", | |
| lockRankRwmutexW: "rwmutexW", | |
| lockRankRwmutexR: "rwmutexR", | |
| lockRankSpanSetSpine: "spanSetSpine", | |
| lockRankGscan: "gscan", | |
| lockRankStackpool: "stackpool", | |
| lockRankStackLarge: "stackLarge", | |
| lockRankDefer: "defer", | |
| lockRankSudog: "sudog", | |
| lockRankWbufSpans: "wbufSpans", | |
| lockRankMheap: "mheap", | |
| lockRankMheapSpecial: "mheapSpecial", | |
| lockRankGlobalAlloc: "globalAlloc.mutex", | |
| lockRankGFree: "gFree", | |
| lockRankHchanLeaf: "hchanLeaf", | |
| lockRankNewmHandoff: "newmHandoff.lock", | |
| lockRankDebugPtrmask: "debugPtrmask.lock", | |
| lockRankFaketimeState: "faketimeState.lock", | |
| lockRankTicks: "ticks.lock", | |
| lockRankRaceFini: "raceFiniLock", | |
| lockRankPollCache: "pollCache.lock", | |
| lockRankDebug: "debugLock", | |
| } | |
| func (rank lockRank) String() string { | |
| if rank == 0 { | |
| return "UNKNOWN" | |
| } | |
| if rank == lockRankLeafRank { | |
| return "LEAF" | |
| } | |
| return lockNames[rank] | |
| } | |
| // lockPartialOrder is a partial order among the various lock types, listing the | |
| // immediate ordering that has actually been observed in the runtime. Each entry | |
| // (which corresponds to a particular lock rank) specifies the list of locks | |
| // that can already be held immediately "above" it. | |
| // | |
| // So, for example, the lockRankSched entry shows that all the locks preceding | |
| // it in rank can actually be held. The allp lock shows that only the sysmon or | |
| // sched lock can be held immediately above it when it is acquired. | |
| var lockPartialOrder [][]lockRank = [][]lockRank{ | |
| lockRankDummy: {}, | |
| lockRankSysmon: {}, | |
| lockRankScavenge: {lockRankSysmon}, | |
| lockRankForcegc: {lockRankSysmon}, | |
| lockRankSweepWaiters: {}, | |
| lockRankAssistQueue: {}, | |
| lockRankCpuprof: {}, | |
| lockRankSweep: {}, | |
| lockRankPollDesc: {}, | |
| lockRankSched: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc}, | |
| lockRankDeadlock: {lockRankDeadlock}, | |
| lockRankPanic: {lockRankDeadlock}, | |
| lockRankAllg: {lockRankSysmon, lockRankSched, lockRankPanic}, | |
| lockRankAllp: {lockRankSysmon, lockRankSched}, | |
| lockRankTimers: {lockRankSysmon, lockRankScavenge, lockRankSched, lockRankAllp, lockRankPollDesc, lockRankTimers}, | |
| lockRankItab: {}, | |
| lockRankReflectOffs: {lockRankItab}, | |
| lockRankHchan: {lockRankScavenge, lockRankSweep, lockRankHchan}, | |
| lockRankFin: {lockRankSysmon, lockRankScavenge, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan}, | |
| lockRankNotifyList: {}, | |
| lockRankTraceBuf: {lockRankSysmon, lockRankScavenge}, | |
| lockRankTraceStrings: {lockRankTraceBuf}, | |
| lockRankMspanSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings}, | |
| lockRankProf: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan}, | |
| lockRankGcBitsArenas: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan}, | |
| lockRankRoot: {}, | |
| lockRankTrace: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankSched, lockRankHchan, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot, lockRankSweep}, | |
| lockRankTraceStackTab: {lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot, lockRankTrace}, | |
| lockRankNetpollInit: {lockRankTimers}, | |
| lockRankRwmutexW: {}, | |
| lockRankRwmutexR: {lockRankRwmutexW}, | |
| lockRankSpanSetSpine: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan}, | |
| lockRankGscan: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot, lockRankNotifyList, lockRankProf, lockRankGcBitsArenas, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankSpanSetSpine}, | |
| lockRankStackpool: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankPollDesc, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankRwmutexR, lockRankSpanSetSpine, lockRankGscan}, | |
| lockRankStackLarge: {lockRankSysmon, lockRankAssistQueue, lockRankSched, lockRankItab, lockRankHchan, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan}, | |
| lockRankDefer: {}, | |
| lockRankSudog: {lockRankNotifyList, lockRankHchan}, | |
| lockRankWbufSpans: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankAllg, lockRankPollDesc, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankRoot, lockRankGscan, lockRankDefer, lockRankSudog}, | |
| lockRankMheap: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankFin, lockRankPollDesc, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan, lockRankMspanSpecial, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankDefer, lockRankSudog, lockRankWbufSpans, lockRankSpanSetSpine}, | |
| lockRankMheapSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan}, | |
| lockRankGlobalAlloc: {lockRankProf, lockRankSpanSetSpine, lockRankMheap, lockRankMheapSpecial}, | |
| lockRankGFree: {lockRankSched}, | |
| lockRankHchanLeaf: {lockRankGscan, lockRankHchanLeaf}, | |
| lockRankNewmHandoff: {}, | |
| lockRankDebugPtrmask: {}, | |
| lockRankFaketimeState: {}, | |
| lockRankTicks: {}, | |
| lockRankRaceFini: {}, | |
| lockRankPollCache: {}, | |
| lockRankDebug: {}, | |
| } |