Black Lives Matter. Support the Equal Justice Initiative.

Source file src/runtime/lockrank.go

Documentation: runtime

     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.
     4  
     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.
    12  //
    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).
    16  //
    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
    23  // partial order.
    24  
    25  package runtime
    26  
    27  type lockRank int
    28  
    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
    31  // rank.
    32  const (
    33  	lockRankDummy lockRank = iota
    34  
    35  	// Locks held above sched
    36  	lockRankSysmon
    37  	lockRankScavenge
    38  	lockRankForcegc
    39  	lockRankSweepWaiters
    40  	lockRankAssistQueue
    41  	lockRankCpuprof
    42  	lockRankSweep
    43  
    44  	lockRankPollDesc
    45  	lockRankSched
    46  	lockRankDeadlock
    47  	lockRankPanic
    48  	lockRankAllg
    49  	lockRankAllp
    50  
    51  	lockRankTimers // Multiple timers locked simultaneously in destroy()
    52  	lockRankItab
    53  	lockRankReflectOffs
    54  	lockRankHchan // Multiple hchans acquired in lock order in syncadjustsudogs()
    55  	lockRankFin
    56  	lockRankNotifyList
    57  	lockRankTraceBuf
    58  	lockRankTraceStrings
    59  	lockRankMspanSpecial
    60  	lockRankProf
    61  	lockRankGcBitsArenas
    62  	lockRankRoot
    63  	lockRankTrace
    64  	lockRankTraceStackTab
    65  	lockRankNetpollInit
    66  
    67  	lockRankRwmutexW
    68  	lockRankRwmutexR
    69  
    70  	lockRankSpanSetSpine
    71  	lockRankGscan
    72  	lockRankStackpool
    73  	lockRankStackLarge
    74  	lockRankDefer
    75  	lockRankSudog
    76  
    77  	// Memory-related non-leaf locks
    78  	lockRankWbufSpans
    79  	lockRankMheap
    80  	lockRankMheapSpecial
    81  
    82  	// Memory-related leaf locks
    83  	lockRankGlobalAlloc
    84  
    85  	// Other leaf locks
    86  	lockRankGFree
    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
    93  	// hchan locks.
    94  	lockRankHchanLeaf
    95  
    96  	// Leaf locks with no dependencies, so these constants are not actually used anywhere.
    97  	// There are other architecture-dependent leaf locks as well.
    98  	lockRankNewmHandoff
    99  	lockRankDebugPtrmask
   100  	lockRankFaketimeState
   101  	lockRankTicks
   102  	lockRankRaceFini
   103  	lockRankPollCache
   104  	lockRankDebug
   105  )
   106  
   107  // lockRankLeafRank is the rank of lock that does not have a declared rank, and hence is
   108  // a leaf lock.
   109  const lockRankLeafRank lockRank = 1000
   110  
   111  // lockNames gives the names associated with each of the above ranks
   112  var lockNames = []string{
   113  	lockRankDummy: "",
   114  
   115  	lockRankSysmon:       "sysmon",
   116  	lockRankScavenge:     "scavenge",
   117  	lockRankForcegc:      "forcegc",
   118  	lockRankSweepWaiters: "sweepWaiters",
   119  	lockRankAssistQueue:  "assistQueue",
   120  	lockRankCpuprof:      "cpuprof",
   121  	lockRankSweep:        "sweep",
   122  
   123  	lockRankPollDesc: "pollDesc",
   124  	lockRankSched:    "sched",
   125  	lockRankDeadlock: "deadlock",
   126  	lockRankPanic:    "panic",
   127  	lockRankAllg:     "allg",
   128  	lockRankAllp:     "allp",
   129  
   130  	lockRankTimers:      "timers",
   131  	lockRankItab:        "itab",
   132  	lockRankReflectOffs: "reflectOffs",
   133  
   134  	lockRankHchan:         "hchan",
   135  	lockRankFin:           "fin",
   136  	lockRankNotifyList:    "notifyList",
   137  	lockRankTraceBuf:      "traceBuf",
   138  	lockRankTraceStrings:  "traceStrings",
   139  	lockRankMspanSpecial:  "mspanSpecial",
   140  	lockRankProf:          "prof",
   141  	lockRankGcBitsArenas:  "gcBitsArenas",
   142  	lockRankRoot:          "root",
   143  	lockRankTrace:         "trace",
   144  	lockRankTraceStackTab: "traceStackTab",
   145  	lockRankNetpollInit:   "netpollInit",
   146  
   147  	lockRankRwmutexW: "rwmutexW",
   148  	lockRankRwmutexR: "rwmutexR",
   149  
   150  	lockRankSpanSetSpine: "spanSetSpine",
   151  	lockRankGscan:        "gscan",
   152  	lockRankStackpool:    "stackpool",
   153  	lockRankStackLarge:   "stackLarge",
   154  	lockRankDefer:        "defer",
   155  	lockRankSudog:        "sudog",
   156  
   157  	lockRankWbufSpans:    "wbufSpans",
   158  	lockRankMheap:        "mheap",
   159  	lockRankMheapSpecial: "mheapSpecial",
   160  
   161  	lockRankGlobalAlloc: "globalAlloc.mutex",
   162  
   163  	lockRankGFree:     "gFree",
   164  	lockRankHchanLeaf: "hchanLeaf",
   165  
   166  	lockRankNewmHandoff:   "newmHandoff.lock",
   167  	lockRankDebugPtrmask:  "debugPtrmask.lock",
   168  	lockRankFaketimeState: "faketimeState.lock",
   169  	lockRankTicks:         "ticks.lock",
   170  	lockRankRaceFini:      "raceFiniLock",
   171  	lockRankPollCache:     "pollCache.lock",
   172  	lockRankDebug:         "debugLock",
   173  }
   174  
   175  func (rank lockRank) String() string {
   176  	if rank == 0 {
   177  		return "UNKNOWN"
   178  	}
   179  	if rank == lockRankLeafRank {
   180  		return "LEAF"
   181  	}
   182  	return lockNames[rank]
   183  }
   184  
   185  // lockPartialOrder is a partial order among the various lock types, listing the
   186  // immediate ordering that has actually been observed in the runtime. Each entry
   187  // (which corresponds to a particular lock rank) specifies the list of locks
   188  // that can already be held immediately "above" it.
   189  //
   190  // So, for example, the lockRankSched entry shows that all the locks preceding
   191  // it in rank can actually be held. The allp lock shows that only the sysmon or
   192  // sched lock can be held immediately above it when it is acquired.
   193  var lockPartialOrder [][]lockRank = [][]lockRank{
   194  	lockRankDummy:         {},
   195  	lockRankSysmon:        {},
   196  	lockRankScavenge:      {lockRankSysmon},
   197  	lockRankForcegc:       {lockRankSysmon},
   198  	lockRankSweepWaiters:  {},
   199  	lockRankAssistQueue:   {},
   200  	lockRankCpuprof:       {},
   201  	lockRankSweep:         {},
   202  	lockRankPollDesc:      {},
   203  	lockRankSched:         {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc},
   204  	lockRankDeadlock:      {lockRankDeadlock},
   205  	lockRankPanic:         {lockRankDeadlock},
   206  	lockRankAllg:          {lockRankSysmon, lockRankSched, lockRankPanic},
   207  	lockRankAllp:          {lockRankSysmon, lockRankSched},
   208  	lockRankTimers:        {lockRankSysmon, lockRankScavenge, lockRankSched, lockRankAllp, lockRankPollDesc, lockRankTimers},
   209  	lockRankItab:          {},
   210  	lockRankReflectOffs:   {lockRankItab},
   211  	lockRankHchan:         {lockRankScavenge, lockRankSweep, lockRankHchan},
   212  	lockRankFin:           {lockRankSysmon, lockRankScavenge, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan},
   213  	lockRankNotifyList:    {},
   214  	lockRankTraceBuf:      {lockRankSysmon, lockRankScavenge},
   215  	lockRankTraceStrings:  {lockRankTraceBuf},
   216  	lockRankMspanSpecial:  {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings},
   217  	lockRankProf:          {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan},
   218  	lockRankGcBitsArenas:  {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan},
   219  	lockRankRoot:          {},
   220  	lockRankTrace:         {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankSched, lockRankHchan, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot, lockRankSweep},
   221  	lockRankTraceStackTab: {lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot, lockRankTrace},
   222  	lockRankNetpollInit:   {lockRankTimers},
   223  
   224  	lockRankRwmutexW: {},
   225  	lockRankRwmutexR: {lockRankSysmon, lockRankRwmutexW},
   226  
   227  	lockRankSpanSetSpine: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan},
   228  	lockRankGscan:        {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot, lockRankNotifyList, lockRankProf, lockRankGcBitsArenas, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankSpanSetSpine},
   229  	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},
   230  	lockRankStackLarge:   {lockRankSysmon, lockRankAssistQueue, lockRankSched, lockRankItab, lockRankHchan, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan},
   231  	lockRankDefer:        {},
   232  	lockRankSudog:        {lockRankNotifyList, lockRankHchan},
   233  	lockRankWbufSpans:    {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankAllg, lockRankPollDesc, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankRoot, lockRankGscan, lockRankDefer, lockRankSudog},
   234  	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},
   235  	lockRankMheapSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan},
   236  	lockRankGlobalAlloc:  {lockRankProf, lockRankSpanSetSpine, lockRankMheap, lockRankMheapSpecial},
   237  
   238  	lockRankGFree:     {lockRankSched},
   239  	lockRankHchanLeaf: {lockRankGscan, lockRankHchanLeaf},
   240  
   241  	lockRankNewmHandoff:   {},
   242  	lockRankDebugPtrmask:  {},
   243  	lockRankFaketimeState: {},
   244  	lockRankTicks:         {},
   245  	lockRankRaceFini:      {},
   246  	lockRankPollCache:     {},
   247  	lockRankDebug:         {},
   248  }
   249  

View as plain text