Source file src/runtime/lockrank.go

     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  	lockRankTraceBuf
    55  	lockRankFin
    56  	lockRankNotifyList
    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  	lockRankPageAllocScav
    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  	lockRankPanic
    96  
    97  	// Leaf locks with no dependencies, so these constants are not actually used anywhere.
    98  	// There are other architecture-dependent leaf locks as well.
    99  	lockRankNewmHandoff
   100  	lockRankDebugPtrmask
   101  	lockRankFaketimeState
   102  	lockRankTicks
   103  	lockRankRaceFini
   104  	lockRankPollCache
   105  	lockRankDebug
   106  )
   107  
   108  // lockRankLeafRank is the rank of lock that does not have a declared rank, and hence is
   109  // a leaf lock.
   110  const lockRankLeafRank lockRank = 1000
   111  
   112  // lockNames gives the names associated with each of the above ranks
   113  var lockNames = []string{
   114  	lockRankDummy: "",
   115  
   116  	lockRankSysmon:       "sysmon",
   117  	lockRankScavenge:     "scavenge",
   118  	lockRankForcegc:      "forcegc",
   119  	lockRankSweepWaiters: "sweepWaiters",
   120  	lockRankAssistQueue:  "assistQueue",
   121  	lockRankCpuprof:      "cpuprof",
   122  	lockRankSweep:        "sweep",
   123  
   124  	lockRankPollDesc: "pollDesc",
   125  	lockRankSched:    "sched",
   126  	lockRankDeadlock: "deadlock",
   127  	lockRankAllg:     "allg",
   128  	lockRankAllp:     "allp",
   129  
   130  	lockRankTimers:      "timers",
   131  	lockRankItab:        "itab",
   132  	lockRankReflectOffs: "reflectOffs",
   133  
   134  	lockRankHchan:         "hchan",
   135  	lockRankTraceBuf:      "traceBuf",
   136  	lockRankFin:           "fin",
   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",
   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  	lockRankPageAllocScav: "pageAlloc.scav.lock",
   163  
   164  	lockRankGFree:     "gFree",
   165  	lockRankHchanLeaf: "hchanLeaf",
   166  	lockRankPanic:     "panic",
   167  
   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",
   175  }
   176  
   177  func (rank lockRank) String() string {
   178  	if rank == 0 {
   179  		return "UNKNOWN"
   180  	}
   181  	if rank == lockRankLeafRank {
   182  		return "LEAF"
   183  	}
   184  	return lockNames[rank]
   185  }
   186  
   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.
   191  //
   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{
   196  	lockRankDummy:         {},
   197  	lockRankSysmon:        {},
   198  	lockRankScavenge:      {lockRankSysmon},
   199  	lockRankForcegc:       {lockRankSysmon},
   200  	lockRankSweepWaiters:  {},
   201  	lockRankAssistQueue:   {},
   202  	lockRankCpuprof:       {},
   203  	lockRankSweep:         {},
   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},
   210  	lockRankItab:          {},
   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},
   220  	lockRankRoot:          {},
   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},
   224  
   225  	lockRankRwmutexW: {},
   226  	lockRankRwmutexR: {lockRankSysmon, lockRankRwmutexW},
   227  
   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},
   232  	lockRankDefer:         {},
   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},
   239  
   240  	lockRankGFree:     {lockRankSched},
   241  	lockRankHchanLeaf: {lockRankGscan, lockRankHchanLeaf},
   242  	lockRankPanic:     {lockRankDeadlock}, // plus any other lock held on throw.
   243  
   244  	lockRankNewmHandoff:   {},
   245  	lockRankDebugPtrmask:  {},
   246  	lockRankFaketimeState: {},
   247  	lockRankTicks:         {},
   248  	lockRankRaceFini:      {},
   249  	lockRankPollCache:     {},
   250  	lockRankDebug:         {},
   251  }
   252  

View as plain text