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  	lockRankAllg
    48  	lockRankAllp
    49  
    50  	lockRankTimers // Multiple timers locked simultaneously in destroy()
    51  	lockRankItab
    52  	lockRankReflectOffs
    53  	lockRankHchan // Multiple hchans acquired in lock order in syncadjustsudogs()
    54  	lockRankFin
    55  	lockRankNotifyList
    56  	lockRankTraceBuf
    57  	lockRankTraceStrings
    58  	lockRankMspanSpecial
    59  	lockRankProf
    60  	lockRankGcBitsArenas
    61  	lockRankRoot
    62  	lockRankTrace
    63  	lockRankTraceStackTab
    64  	lockRankNetpollInit
    65  
    66  	lockRankRwmutexW
    67  	lockRankRwmutexR
    68  
    69  	lockRankSpanSetSpine
    70  	lockRankGscan
    71  	lockRankStackpool
    72  	lockRankStackLarge
    73  	lockRankDefer
    74  	lockRankSudog
    75  
    76  	// Memory-related non-leaf locks
    77  	lockRankWbufSpans
    78  	lockRankMheap
    79  	lockRankMheapSpecial
    80  
    81  	// Memory-related leaf locks
    82  	lockRankGlobalAlloc
    83  
    84  	// Other leaf locks
    85  	lockRankGFree
    86  	// Generally, hchan must be acquired before gscan. But in one specific
    87  	// case (in syncadjustsudogs from markroot after the g has been suspended
    88  	// by suspendG), we allow gscan to be acquired, and then an hchan lock. To
    89  	// allow this case, we get this lockRankHchanLeaf rank in
    90  	// syncadjustsudogs(), rather than lockRankHchan. By using this special
    91  	// rank, we don't allow any further locks to be acquired other than more
    92  	// hchan locks.
    93  	lockRankHchanLeaf
    94  	lockRankPanic
    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  	lockRankAllg:     "allg",
   127  	lockRankAllp:     "allp",
   128  
   129  	lockRankTimers:      "timers",
   130  	lockRankItab:        "itab",
   131  	lockRankReflectOffs: "reflectOffs",
   132  
   133  	lockRankHchan:         "hchan",
   134  	lockRankFin:           "fin",
   135  	lockRankNotifyList:    "notifyList",
   136  	lockRankTraceBuf:      "traceBuf",
   137  	lockRankTraceStrings:  "traceStrings",
   138  	lockRankMspanSpecial:  "mspanSpecial",
   139  	lockRankProf:          "prof",
   140  	lockRankGcBitsArenas:  "gcBitsArenas",
   141  	lockRankRoot:          "root",
   142  	lockRankTrace:         "trace",
   143  	lockRankTraceStackTab: "traceStackTab",
   144  	lockRankNetpollInit:   "netpollInit",
   145  
   146  	lockRankRwmutexW: "rwmutexW",
   147  	lockRankRwmutexR: "rwmutexR",
   148  
   149  	lockRankSpanSetSpine: "spanSetSpine",
   150  	lockRankGscan:        "gscan",
   151  	lockRankStackpool:    "stackpool",
   152  	lockRankStackLarge:   "stackLarge",
   153  	lockRankDefer:        "defer",
   154  	lockRankSudog:        "sudog",
   155  
   156  	lockRankWbufSpans:    "wbufSpans",
   157  	lockRankMheap:        "mheap",
   158  	lockRankMheapSpecial: "mheapSpecial",
   159  
   160  	lockRankGlobalAlloc: "globalAlloc.mutex",
   161  
   162  	lockRankGFree:     "gFree",
   163  	lockRankHchanLeaf: "hchanLeaf",
   164  	lockRankPanic:     "panic",
   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  	lockRankAllg:          {lockRankSysmon, lockRankSched},
   206  	lockRankAllp:          {lockRankSysmon, lockRankSched},
   207  	lockRankTimers:        {lockRankSysmon, lockRankScavenge, lockRankPollDesc, lockRankSched, lockRankAllp, lockRankTimers},
   208  	lockRankItab:          {},
   209  	lockRankReflectOffs:   {lockRankItab},
   210  	lockRankHchan:         {lockRankScavenge, lockRankSweep, lockRankHchan},
   211  	lockRankFin:           {lockRankSysmon, lockRankScavenge, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan},
   212  	lockRankNotifyList:    {},
   213  	lockRankTraceBuf:      {lockRankSysmon, lockRankScavenge},
   214  	lockRankTraceStrings:  {lockRankTraceBuf},
   215  	lockRankMspanSpecial:  {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings},
   216  	lockRankProf:          {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings},
   217  	lockRankGcBitsArenas:  {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings},
   218  	lockRankRoot:          {},
   219  	lockRankTrace:         {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankHchan, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot},
   220  	lockRankTraceStackTab: {lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot, lockRankTrace},
   221  	lockRankNetpollInit:   {lockRankTimers},
   222  
   223  	lockRankRwmutexW: {},
   224  	lockRankRwmutexR: {lockRankSysmon, lockRankRwmutexW},
   225  
   226  	lockRankSpanSetSpine: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings},
   227  	lockRankGscan:        {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankSpanSetSpine},
   228  	lockRankStackpool:    {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankRwmutexR, lockRankSpanSetSpine, lockRankGscan},
   229  	lockRankStackLarge:   {lockRankSysmon, lockRankAssistQueue, lockRankSched, lockRankItab, lockRankHchan, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan},
   230  	lockRankDefer:        {},
   231  	lockRankSudog:        {lockRankHchan, lockRankNotifyList},
   232  	lockRankWbufSpans:    {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankRoot, lockRankGscan, lockRankDefer, lockRankSudog},
   233  	lockRankMheap:        {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankDefer, lockRankSudog, lockRankWbufSpans},
   234  	lockRankMheapSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings},
   235  	lockRankGlobalAlloc:  {lockRankProf, lockRankSpanSetSpine, lockRankMheap, lockRankMheapSpecial},
   236  
   237  	lockRankGFree:     {lockRankSched},
   238  	lockRankHchanLeaf: {lockRankGscan, lockRankHchanLeaf},
   239  	lockRankPanic:     {lockRankDeadlock}, // plus any other lock held on throw.
   240  
   241  	lockRankNewmHandoff:   {},
   242  	lockRankDebugPtrmask:  {},
   243  	lockRankFaketimeState: {},
   244  	lockRankTicks:         {},
   245  	lockRankRaceFini:      {},
   246  	lockRankPollCache:     {},
   247  	lockRankDebug:         {},
   248  }
   249  

View as plain text