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  	lockRankProfInsert
    60  	lockRankProfBlock
    61  	lockRankProfMemActive
    62  	lockRankProfMemFuture
    63  	lockRankGcBitsArenas
    64  	lockRankRoot
    65  	lockRankTrace
    66  	lockRankTraceStackTab
    67  	lockRankNetpollInit
    68  
    69  	lockRankRwmutexW
    70  	lockRankRwmutexR
    71  
    72  	lockRankSpanSetSpine
    73  	lockRankGscan
    74  	lockRankStackpool
    75  	lockRankStackLarge
    76  	lockRankDefer
    77  	lockRankSudog
    78  
    79  	// Memory-related non-leaf locks
    80  	lockRankWbufSpans
    81  	lockRankMheap
    82  	lockRankMheapSpecial
    83  
    84  	// Memory-related leaf locks
    85  	lockRankGlobalAlloc
    86  	lockRankPageAllocScav
    87  
    88  	// Other leaf locks
    89  	lockRankGFree
    90  	// Generally, hchan must be acquired before gscan. But in one specific
    91  	// case (in syncadjustsudogs from markroot after the g has been suspended
    92  	// by suspendG), we allow gscan to be acquired, and then an hchan lock. To
    93  	// allow this case, we get this lockRankHchanLeaf rank in
    94  	// syncadjustsudogs(), rather than lockRankHchan. By using this special
    95  	// rank, we don't allow any further locks to be acquired other than more
    96  	// hchan locks.
    97  	lockRankHchanLeaf
    98  	lockRankPanic
    99  
   100  	// Leaf locks with no dependencies, so these constants are not actually used anywhere.
   101  	// There are other architecture-dependent leaf locks as well.
   102  	lockRankNewmHandoff
   103  	lockRankDebugPtrmask
   104  	lockRankFaketimeState
   105  	lockRankTicks
   106  	lockRankRaceFini
   107  	lockRankPollCache
   108  	lockRankDebug
   109  )
   110  
   111  // lockRankLeafRank is the rank of lock that does not have a declared rank, and hence is
   112  // a leaf lock.
   113  const lockRankLeafRank lockRank = 1000
   114  
   115  // lockNames gives the names associated with each of the above ranks
   116  var lockNames = []string{
   117  	lockRankDummy: "",
   118  
   119  	lockRankSysmon:       "sysmon",
   120  	lockRankScavenge:     "scavenge",
   121  	lockRankForcegc:      "forcegc",
   122  	lockRankSweepWaiters: "sweepWaiters",
   123  	lockRankAssistQueue:  "assistQueue",
   124  	lockRankCpuprof:      "cpuprof",
   125  	lockRankSweep:        "sweep",
   126  
   127  	lockRankPollDesc: "pollDesc",
   128  	lockRankSched:    "sched",
   129  	lockRankDeadlock: "deadlock",
   130  	lockRankAllg:     "allg",
   131  	lockRankAllp:     "allp",
   132  
   133  	lockRankTimers:      "timers",
   134  	lockRankItab:        "itab",
   135  	lockRankReflectOffs: "reflectOffs",
   136  
   137  	lockRankHchan:         "hchan",
   138  	lockRankTraceBuf:      "traceBuf",
   139  	lockRankFin:           "fin",
   140  	lockRankNotifyList:    "notifyList",
   141  	lockRankTraceStrings:  "traceStrings",
   142  	lockRankMspanSpecial:  "mspanSpecial",
   143  	lockRankProfInsert:    "profInsert",
   144  	lockRankProfBlock:     "profBlock",
   145  	lockRankProfMemActive: "profMemActive",
   146  	lockRankProfMemFuture: "profMemFuture",
   147  	lockRankGcBitsArenas:  "gcBitsArenas",
   148  	lockRankRoot:          "root",
   149  	lockRankTrace:         "trace",
   150  	lockRankTraceStackTab: "traceStackTab",
   151  	lockRankNetpollInit:   "netpollInit",
   152  
   153  	lockRankRwmutexW: "rwmutexW",
   154  	lockRankRwmutexR: "rwmutexR",
   155  
   156  	lockRankSpanSetSpine: "spanSetSpine",
   157  	lockRankGscan:        "gscan",
   158  	lockRankStackpool:    "stackpool",
   159  	lockRankStackLarge:   "stackLarge",
   160  	lockRankDefer:        "defer",
   161  	lockRankSudog:        "sudog",
   162  
   163  	lockRankWbufSpans:    "wbufSpans",
   164  	lockRankMheap:        "mheap",
   165  	lockRankMheapSpecial: "mheapSpecial",
   166  
   167  	lockRankGlobalAlloc:   "globalAlloc.mutex",
   168  	lockRankPageAllocScav: "pageAlloc.scav.lock",
   169  
   170  	lockRankGFree:     "gFree",
   171  	lockRankHchanLeaf: "hchanLeaf",
   172  	lockRankPanic:     "panic",
   173  
   174  	lockRankNewmHandoff:   "newmHandoff.lock",
   175  	lockRankDebugPtrmask:  "debugPtrmask.lock",
   176  	lockRankFaketimeState: "faketimeState.lock",
   177  	lockRankTicks:         "ticks.lock",
   178  	lockRankRaceFini:      "raceFiniLock",
   179  	lockRankPollCache:     "pollCache.lock",
   180  	lockRankDebug:         "debugLock",
   181  }
   182  
   183  func (rank lockRank) String() string {
   184  	if rank == 0 {
   185  		return "UNKNOWN"
   186  	}
   187  	if rank == lockRankLeafRank {
   188  		return "LEAF"
   189  	}
   190  	return lockNames[rank]
   191  }
   192  
   193  // lockPartialOrder is a partial order among the various lock types, listing the
   194  // immediate ordering that has actually been observed in the runtime. Each entry
   195  // (which corresponds to a particular lock rank) specifies the list of locks
   196  // that can already be held immediately "above" it.
   197  //
   198  // So, for example, the lockRankSched entry shows that all the locks preceding
   199  // it in rank can actually be held. The allp lock shows that only the sysmon or
   200  // sched lock can be held immediately above it when it is acquired.
   201  var lockPartialOrder [][]lockRank = [][]lockRank{
   202  	lockRankDummy:         {},
   203  	lockRankSysmon:        {},
   204  	lockRankScavenge:      {lockRankSysmon},
   205  	lockRankForcegc:       {lockRankSysmon},
   206  	lockRankSweepWaiters:  {},
   207  	lockRankAssistQueue:   {},
   208  	lockRankCpuprof:       {},
   209  	lockRankSweep:         {},
   210  	lockRankPollDesc:      {},
   211  	lockRankSched:         {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc},
   212  	lockRankDeadlock:      {lockRankDeadlock},
   213  	lockRankAllg:          {lockRankSysmon, lockRankSched},
   214  	lockRankAllp:          {lockRankSysmon, lockRankSched},
   215  	lockRankTimers:        {lockRankSysmon, lockRankScavenge, lockRankPollDesc, lockRankSched, lockRankAllp, lockRankTimers},
   216  	lockRankItab:          {},
   217  	lockRankReflectOffs:   {lockRankItab},
   218  	lockRankHchan:         {lockRankScavenge, lockRankSweep, lockRankHchan},
   219  	lockRankTraceBuf:      {lockRankSysmon, lockRankScavenge},
   220  	lockRankFin:           {lockRankSysmon, lockRankScavenge, lockRankSched, lockRankAllg, lockRankTimers, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf},
   221  	lockRankNotifyList:    {},
   222  	lockRankTraceStrings:  {lockRankTraceBuf},
   223  	lockRankMspanSpecial:  {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings},
   224  	lockRankProfInsert:    {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings},
   225  	lockRankProfBlock:     {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings},
   226  	lockRankProfMemActive: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings},
   227  	lockRankProfMemFuture: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings, lockRankProfMemActive},
   228  	lockRankGcBitsArenas:  {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings},
   229  	lockRankRoot:          {},
   230  	lockRankTrace:         {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankHchan, lockRankTraceBuf, lockRankTraceStrings, lockRankRoot},
   231  	lockRankTraceStackTab: {lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankAllg, lockRankTimers, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankRoot, lockRankTrace},
   232  	lockRankNetpollInit:   {lockRankTimers},
   233  
   234  	lockRankRwmutexW: {},
   235  	lockRankRwmutexR: {lockRankSysmon, lockRankRwmutexW},
   236  
   237  	lockRankSpanSetSpine:  {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings},
   238  	lockRankGscan:         {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankSpanSetSpine},
   239  	lockRankStackpool:     {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankTraceStackTab, lockRankNetpollInit, lockRankRwmutexR, lockRankSpanSetSpine, lockRankGscan},
   240  	lockRankStackLarge:    {lockRankSysmon, lockRankAssistQueue, lockRankSched, lockRankItab, lockRankHchan, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGcBitsArenas, lockRankRoot, lockRankSpanSetSpine, lockRankGscan},
   241  	lockRankDefer:         {},
   242  	lockRankSudog:         {lockRankHchan, lockRankNotifyList},
   243  	lockRankWbufSpans:     {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankRoot, lockRankTrace, lockRankGscan, lockRankDefer, lockRankSudog},
   244  	lockRankMheap:         {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGcBitsArenas, lockRankRoot, lockRankTrace, lockRankSpanSetSpine, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankDefer, lockRankSudog, lockRankWbufSpans},
   245  	lockRankMheapSpecial:  {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankPollDesc, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankTraceBuf, lockRankNotifyList, lockRankTraceStrings},
   246  	lockRankGlobalAlloc:   {lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankSpanSetSpine, lockRankMheap, lockRankMheapSpecial},
   247  	lockRankPageAllocScav: {lockRankMheap},
   248  
   249  	lockRankGFree:     {lockRankSched},
   250  	lockRankHchanLeaf: {lockRankGscan, lockRankHchanLeaf},
   251  	lockRankPanic:     {lockRankDeadlock}, // plus any other lock held on throw.
   252  
   253  	lockRankNewmHandoff:   {},
   254  	lockRankDebugPtrmask:  {},
   255  	lockRankFaketimeState: {},
   256  	lockRankTicks:         {},
   257  	lockRankRaceFini:      {},
   258  	lockRankPollCache:     {},
   259  	lockRankDebug:         {},
   260  }
   261  

View as plain text