Source file src/runtime/debug.go

     1  // Copyright 2009 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  package runtime
     6  
     7  import (
     8  	"internal/runtime/atomic"
     9  	"unsafe"
    10  )
    11  
    12  // GOMAXPROCS sets the maximum number of CPUs that can be executing
    13  // simultaneously and returns the previous setting. If n < 1, it does not change
    14  // the current setting.
    15  //
    16  // # Default
    17  //
    18  // If the GOMAXPROCS environment variable is set to a positive whole number,
    19  // GOMAXPROCS defaults to that value.
    20  //
    21  // Otherwise, the Go runtime selects an appropriate default value from a combination of
    22  //   - the number of logical CPUs on the machine,
    23  //   - the process’s CPU affinity mask,
    24  //   - and, on Linux, the process’s average CPU throughput limit based on cgroup CPU
    25  //     quota, if any.
    26  //
    27  // If GODEBUG=containermaxprocs=0 is set and GOMAXPROCS is not set by the
    28  // environment variable, then GOMAXPROCS instead defaults to the value of
    29  // [runtime.NumCPU]. Note that GODEBUG=containermaxprocs=0 is [default] for
    30  // language version 1.24 and below.
    31  //
    32  // # Updates
    33  //
    34  // The Go runtime periodically updates the default value based on changes to
    35  // the total logical CPU count, the CPU affinity mask, or cgroup quota. Setting
    36  // a custom value with the GOMAXPROCS environment variable or by calling
    37  // GOMAXPROCS disables automatic updates. The default value and automatic
    38  // updates can be restored by calling [SetDefaultGOMAXPROCS].
    39  //
    40  // If GODEBUG=updatemaxprocs=0 is set, the Go runtime does not perform
    41  // automatic GOMAXPROCS updating. Note that GODEBUG=updatemaxprocs=0 is
    42  // [default] for language version 1.24 and below.
    43  //
    44  // # Compatibility
    45  //
    46  // Note that the default GOMAXPROCS behavior may change as the scheduler
    47  // improves, especially the implementation detail below.
    48  //
    49  // # Implementation details
    50  //
    51  // When computing default GOMAXPROCS via cgroups, the Go runtime computes the
    52  // "average CPU throughput limit" as the cgroup CPU quota / period. In cgroup
    53  // v2, these values come from the cpu.max file. In cgroup v1, they come from
    54  // cpu.cfs_quota_us and cpu.cfs_period_us, respectively. In container runtimes
    55  // that allow configuring CPU limits, this value usually corresponds to the
    56  // "CPU limit" option, not "CPU request".
    57  //
    58  // The Go runtime typically selects the default GOMAXPROCS as the minimum of
    59  // the logical CPU count, the CPU affinity mask count, or the cgroup CPU
    60  // throughput limit. However, it will never set GOMAXPROCS less than 2 unless
    61  // the logical CPU count or CPU affinity mask count are below 2.
    62  //
    63  // If the cgroup CPU throughput limit is not a whole number, the Go runtime
    64  // rounds up to the next whole number.
    65  //
    66  // GOMAXPROCS updates are performed up to once per second, or less if the
    67  // application is idle.
    68  //
    69  // [default]: https://go.dev/doc/godebug#default
    70  func GOMAXPROCS(n int) int {
    71  	if GOARCH == "wasm" && n > 1 {
    72  		n = 1 // WebAssembly has no threads yet, so only one CPU is possible.
    73  	}
    74  
    75  	lock(&sched.lock)
    76  	ret := int(gomaxprocs)
    77  	if n <= 0 {
    78  		unlock(&sched.lock)
    79  		return ret
    80  	}
    81  	// Set early so we can wait for sysmon befor STW. See comment on
    82  	// computeMaxProcsLock.
    83  	sched.customGOMAXPROCS = true
    84  	unlock(&sched.lock)
    85  
    86  	// Wait for sysmon to complete running defaultGOMAXPROCS.
    87  	lock(&computeMaxProcsLock)
    88  	unlock(&computeMaxProcsLock)
    89  
    90  	if n == ret {
    91  		// sched.customGOMAXPROCS set, but no need to actually STW
    92  		// since the gomaxprocs itself isn't changing.
    93  		return ret
    94  	}
    95  
    96  	stw := stopTheWorldGC(stwGOMAXPROCS)
    97  
    98  	// newprocs will be processed by startTheWorld
    99  	//
   100  	// TODO(prattmic): this could use a nicer API. Perhaps add it to the
   101  	// stw parameter?
   102  	newprocs = int32(n)
   103  
   104  	startTheWorldGC(stw)
   105  	return ret
   106  }
   107  
   108  // SetDefaultGOMAXPROCS updates the GOMAXPROCS setting to the runtime
   109  // default, as described by [GOMAXPROCS], ignoring the GOMAXPROCS
   110  // environment variable.
   111  //
   112  // SetDefaultGOMAXPROCS can be used to enable the default automatic updating
   113  // GOMAXPROCS behavior if it has been disabled by the GOMAXPROCS
   114  // environment variable or a prior call to [GOMAXPROCS], or to force an immediate
   115  // update if the caller is aware of a change to the total logical CPU count, CPU
   116  // affinity mask or cgroup quota.
   117  func SetDefaultGOMAXPROCS() {
   118  	// SetDefaultGOMAXPROCS conceptually means "[re]do what the runtime
   119  	// would do at startup if the GOMAXPROCS environment variable were
   120  	// unset." It still respects GODEBUG.
   121  
   122  	procs := defaultGOMAXPROCS(0)
   123  
   124  	lock(&sched.lock)
   125  	curr := gomaxprocs
   126  	custom := sched.customGOMAXPROCS
   127  	unlock(&sched.lock)
   128  
   129  	if !custom && procs == curr {
   130  		// Nothing to do if we're already using automatic GOMAXPROCS
   131  		// and the limit is unchanged.
   132  		return
   133  	}
   134  
   135  	stw := stopTheWorldGC(stwGOMAXPROCS)
   136  
   137  	// newprocs will be processed by startTheWorld
   138  	//
   139  	// TODO(prattmic): this could use a nicer API. Perhaps add it to the
   140  	// stw parameter?
   141  	newprocs = procs
   142  	lock(&sched.lock)
   143  	sched.customGOMAXPROCS = false
   144  	unlock(&sched.lock)
   145  
   146  	startTheWorldGC(stw)
   147  }
   148  
   149  // NumCPU returns the number of logical CPUs usable by the current process.
   150  //
   151  // The set of available CPUs is checked by querying the operating system
   152  // at process startup. Changes to operating system CPU allocation after
   153  // process startup are not reflected.
   154  func NumCPU() int {
   155  	return int(numCPUStartup)
   156  }
   157  
   158  // NumCgoCall returns the number of cgo calls made by the current process.
   159  func NumCgoCall() int64 {
   160  	var n = int64(atomic.Load64(&ncgocall))
   161  	for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
   162  		n += int64(mp.ncgocall)
   163  	}
   164  	return n
   165  }
   166  
   167  func totalMutexWaitTimeNanos() int64 {
   168  	total := sched.totalMutexWaitTime.Load()
   169  
   170  	total += sched.totalRuntimeLockWaitTime.Load()
   171  	for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
   172  		total += mp.mLockProfile.waitTime.Load()
   173  	}
   174  
   175  	return total
   176  }
   177  
   178  // NumGoroutine returns the number of goroutines that currently exist.
   179  func NumGoroutine() int {
   180  	return int(gcount())
   181  }
   182  
   183  //go:linkname debug_modinfo runtime/debug.modinfo
   184  func debug_modinfo() string {
   185  	return modinfo
   186  }
   187  
   188  // mayMoreStackPreempt is a maymorestack hook that forces a preemption
   189  // at every possible cooperative preemption point.
   190  //
   191  // This is valuable to apply to the runtime, which can be sensitive to
   192  // preemption points. To apply this to all preemption points in the
   193  // runtime and runtime-like code, use the following in bash or zsh:
   194  //
   195  //	X=(-{gc,asm}flags={runtime/...,reflect,sync}=-d=maymorestack=runtime.mayMoreStackPreempt) GOFLAGS=${X[@]}
   196  //
   197  // This must be deeply nosplit because it is called from a function
   198  // prologue before the stack is set up and because the compiler will
   199  // call it from any splittable prologue (leading to infinite
   200  // recursion).
   201  //
   202  // Ideally it should also use very little stack because the linker
   203  // doesn't currently account for this in nosplit stack depth checking.
   204  //
   205  // Ensure mayMoreStackPreempt can be called for all ABIs.
   206  //
   207  //go:nosplit
   208  //go:linkname mayMoreStackPreempt
   209  func mayMoreStackPreempt() {
   210  	// Don't do anything on the g0 or gsignal stack.
   211  	gp := getg()
   212  	if gp == gp.m.g0 || gp == gp.m.gsignal {
   213  		return
   214  	}
   215  	// Force a preemption, unless the stack is already poisoned.
   216  	if gp.stackguard0 < stackPoisonMin {
   217  		gp.stackguard0 = stackPreempt
   218  	}
   219  }
   220  
   221  // mayMoreStackMove is a maymorestack hook that forces stack movement
   222  // at every possible point.
   223  //
   224  // See mayMoreStackPreempt.
   225  //
   226  //go:nosplit
   227  //go:linkname mayMoreStackMove
   228  func mayMoreStackMove() {
   229  	// Don't do anything on the g0 or gsignal stack.
   230  	gp := getg()
   231  	if gp == gp.m.g0 || gp == gp.m.gsignal {
   232  		return
   233  	}
   234  	// Force stack movement, unless the stack is already poisoned.
   235  	if gp.stackguard0 < stackPoisonMin {
   236  		gp.stackguard0 = stackForceMove
   237  	}
   238  }
   239  
   240  // debugPinnerKeepUnpin is used to make runtime.(*Pinner).Unpin reachable.
   241  var debugPinnerKeepUnpin bool = false
   242  
   243  // debugPinnerV1 returns a new Pinner that pins itself. This function can be
   244  // used by debuggers to easily obtain a Pinner that will not be garbage
   245  // collected (or moved in memory) even if no references to it exist in the
   246  // target program. This pinner in turn can be used to extend this property
   247  // to other objects, which debuggers can use to simplify the evaluation of
   248  // expressions involving multiple call injections.
   249  func debugPinnerV1() *Pinner {
   250  	p := new(Pinner)
   251  	p.Pin(unsafe.Pointer(p))
   252  	if debugPinnerKeepUnpin {
   253  		// Make Unpin reachable.
   254  		p.Unpin()
   255  	}
   256  	return p
   257  }
   258  

View as plain text