Source file src/runtime/runtime.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/abi"
     9  	"internal/runtime/atomic"
    10  	"unsafe"
    11  )
    12  
    13  //go:generate go run wincallback.go
    14  //go:generate go run mkduff.go
    15  //go:generate go run mkfastlog2table.go
    16  //go:generate go run mklockrank.go -o lockrank.go
    17  
    18  var ticks ticksType
    19  
    20  type ticksType struct {
    21  	// lock protects access to start* and val.
    22  	lock       mutex
    23  	startTicks int64
    24  	startTime  int64
    25  	val        atomic.Int64
    26  }
    27  
    28  // init initializes ticks to maximize the chance that we have a good ticksPerSecond reference.
    29  //
    30  // Must not run concurrently with ticksPerSecond.
    31  func (t *ticksType) init() {
    32  	lock(&ticks.lock)
    33  	t.startTime = nanotime()
    34  	t.startTicks = cputicks()
    35  	unlock(&ticks.lock)
    36  }
    37  
    38  // minTimeForTicksPerSecond is the minimum elapsed time we require to consider our ticksPerSecond
    39  // measurement to be of decent enough quality for profiling.
    40  //
    41  // There's a linear relationship here between minimum time and error from the true value.
    42  // The error from the true ticks-per-second in a linux/amd64 VM seems to be:
    43  // -   1 ms -> ~0.02% error
    44  // -   5 ms -> ~0.004% error
    45  // -  10 ms -> ~0.002% error
    46  // -  50 ms -> ~0.0003% error
    47  // - 100 ms -> ~0.0001% error
    48  //
    49  // We're willing to take 0.004% error here, because ticksPerSecond is intended to be used for
    50  // converting durations, not timestamps. Durations are usually going to be much larger, and so
    51  // the tiny error doesn't matter. The error is definitely going to be a problem when trying to
    52  // use this for timestamps, as it'll make those timestamps much less likely to line up.
    53  const minTimeForTicksPerSecond = 5_000_000*(1-osHasLowResClockInt) + 100_000_000*osHasLowResClockInt
    54  
    55  // ticksPerSecond returns a conversion rate between the cputicks clock and the nanotime clock.
    56  //
    57  // Note: Clocks are hard. Using this as an actual conversion rate for timestamps is ill-advised
    58  // and should be avoided when possible. Use only for durations, where a tiny error term isn't going
    59  // to make a meaningful difference in even a 1ms duration. If an accurate timestamp is needed,
    60  // use nanotime instead. (The entire Windows platform is a broad exception to this rule, where nanotime
    61  // produces timestamps on such a coarse granularity that the error from this conversion is actually
    62  // preferable.)
    63  //
    64  // The strategy for computing the conversion rate is to write down nanotime and cputicks as
    65  // early in process startup as possible. From then, we just need to wait until we get values
    66  // from nanotime that we can use (some platforms have a really coarse system time granularity).
    67  // We require some amount of time to pass to ensure that the conversion rate is fairly accurate
    68  // in aggregate. But because we compute this rate lazily, there's a pretty good chance a decent
    69  // amount of time has passed by the time we get here.
    70  //
    71  // Must be called from a normal goroutine context (running regular goroutine with a P).
    72  //
    73  // Called by runtime/pprof in addition to runtime code.
    74  //
    75  // TODO(mknyszek): This doesn't account for things like CPU frequency scaling. Consider
    76  // a more sophisticated and general approach in the future.
    77  func ticksPerSecond() int64 {
    78  	// Get the conversion rate if we've already computed it.
    79  	r := ticks.val.Load()
    80  	if r != 0 {
    81  		return r
    82  	}
    83  
    84  	// Compute the conversion rate.
    85  	for {
    86  		lock(&ticks.lock)
    87  		r = ticks.val.Load()
    88  		if r != 0 {
    89  			unlock(&ticks.lock)
    90  			return r
    91  		}
    92  
    93  		// Grab the current time in both clocks.
    94  		nowTime := nanotime()
    95  		nowTicks := cputicks()
    96  
    97  		// See if we can use these times.
    98  		if nowTicks > ticks.startTicks && nowTime-ticks.startTime > minTimeForTicksPerSecond {
    99  			// Perform the calculation with floats. We don't want to risk overflow.
   100  			r = int64(float64(nowTicks-ticks.startTicks) * 1e9 / float64(nowTime-ticks.startTime))
   101  			if r == 0 {
   102  				// Zero is both a sentinel value and it would be bad if callers used this as
   103  				// a divisor. We tried out best, so just make it 1.
   104  				r++
   105  			}
   106  			ticks.val.Store(r)
   107  			unlock(&ticks.lock)
   108  			break
   109  		}
   110  		unlock(&ticks.lock)
   111  
   112  		// Sleep in one millisecond increments until we have a reliable time.
   113  		timeSleep(1_000_000)
   114  	}
   115  	return r
   116  }
   117  
   118  var envs []string
   119  var argslice []string
   120  
   121  //go:linkname syscall_runtime_envs syscall.runtime_envs
   122  func syscall_runtime_envs() []string { return append([]string{}, envs...) }
   123  
   124  //go:linkname syscall_Getpagesize syscall.Getpagesize
   125  func syscall_Getpagesize() int { return int(physPageSize) }
   126  
   127  //go:linkname os_runtime_args os.runtime_args
   128  func os_runtime_args() []string { return append([]string{}, argslice...) }
   129  
   130  //go:linkname syscall_Exit syscall.Exit
   131  //go:nosplit
   132  func syscall_Exit(code int) {
   133  	exit(int32(code))
   134  }
   135  
   136  var godebugDefault string
   137  var godebugUpdate atomic.Pointer[func(string, string)]
   138  var godebugEnv atomic.Pointer[string] // set by parsedebugvars
   139  var godebugNewIncNonDefault atomic.Pointer[func(string) func()]
   140  
   141  //go:linkname godebug_setUpdate internal/godebug.setUpdate
   142  func godebug_setUpdate(update func(string, string)) {
   143  	p := new(func(string, string))
   144  	*p = update
   145  	godebugUpdate.Store(p)
   146  	godebugNotify(false)
   147  }
   148  
   149  //go:linkname godebug_setNewIncNonDefault internal/godebug.setNewIncNonDefault
   150  func godebug_setNewIncNonDefault(newIncNonDefault func(string) func()) {
   151  	p := new(func(string) func())
   152  	*p = newIncNonDefault
   153  	godebugNewIncNonDefault.Store(p)
   154  	defaultGOMAXPROCSUpdateGODEBUG()
   155  }
   156  
   157  // A godebugInc provides access to internal/godebug's IncNonDefault function
   158  // for a given GODEBUG setting.
   159  // Calls before internal/godebug registers itself are dropped on the floor.
   160  type godebugInc struct {
   161  	name string
   162  	inc  atomic.Pointer[func()]
   163  }
   164  
   165  func (g *godebugInc) IncNonDefault() {
   166  	inc := g.inc.Load()
   167  	if inc == nil {
   168  		newInc := godebugNewIncNonDefault.Load()
   169  		if newInc == nil {
   170  			return
   171  		}
   172  		inc = new(func())
   173  		*inc = (*newInc)(g.name)
   174  		if raceenabled {
   175  			racereleasemerge(unsafe.Pointer(&g.inc))
   176  		}
   177  		if !g.inc.CompareAndSwap(nil, inc) {
   178  			inc = g.inc.Load()
   179  		}
   180  	}
   181  	if raceenabled {
   182  		raceacquire(unsafe.Pointer(&g.inc))
   183  	}
   184  	(*inc)()
   185  }
   186  
   187  func godebugNotify(envChanged bool) {
   188  	update := godebugUpdate.Load()
   189  	var env string
   190  	if p := godebugEnv.Load(); p != nil {
   191  		env = *p
   192  	}
   193  	if envChanged {
   194  		reparsedebugvars(env)
   195  	}
   196  	if update != nil {
   197  		(*update)(godebugDefault, env)
   198  	}
   199  }
   200  
   201  //go:linkname syscall_runtimeSetenv syscall.runtimeSetenv
   202  func syscall_runtimeSetenv(key, value string) {
   203  	setenv_c(key, value)
   204  	if key == "GODEBUG" {
   205  		p := new(string)
   206  		*p = value
   207  		godebugEnv.Store(p)
   208  		godebugNotify(true)
   209  	}
   210  }
   211  
   212  //go:linkname syscall_runtimeUnsetenv syscall.runtimeUnsetenv
   213  func syscall_runtimeUnsetenv(key string) {
   214  	unsetenv_c(key)
   215  	if key == "GODEBUG" {
   216  		godebugEnv.Store(nil)
   217  		godebugNotify(true)
   218  	}
   219  }
   220  
   221  // writeErrStr writes a string to descriptor 2.
   222  // If SetCrashOutput(f) was called, it also writes to f.
   223  //
   224  //go:nosplit
   225  func writeErrStr(s string) {
   226  	writeErrData(unsafe.StringData(s), int32(len(s)))
   227  }
   228  
   229  // writeErrData is the common parts of writeErr{,Str}.
   230  //
   231  //go:nosplit
   232  func writeErrData(data *byte, n int32) {
   233  	write(2, unsafe.Pointer(data), n)
   234  
   235  	// If crashing, print a copy to the SetCrashOutput fd.
   236  	gp := getg()
   237  	if gp != nil && gp.m.dying > 0 ||
   238  		gp == nil && panicking.Load() > 0 {
   239  		if fd := crashFD.Load(); fd != ^uintptr(0) {
   240  			write(fd, unsafe.Pointer(data), n)
   241  		}
   242  	}
   243  }
   244  
   245  // crashFD is an optional file descriptor to use for fatal panics, as
   246  // set by debug.SetCrashOutput (see #42888). If it is a valid fd (not
   247  // all ones), writeErr and related functions write to it in addition
   248  // to standard error.
   249  //
   250  // Initialized to -1 in schedinit.
   251  var crashFD atomic.Uintptr
   252  
   253  //go:linkname setCrashFD
   254  func setCrashFD(fd uintptr) uintptr {
   255  	// Don't change the crash FD if a crash is already in progress.
   256  	//
   257  	// Unlike the case below, this is not required for correctness, but it
   258  	// is generally nicer to have all of the crash output go to the same
   259  	// place rather than getting split across two different FDs.
   260  	if panicking.Load() > 0 {
   261  		return ^uintptr(0)
   262  	}
   263  
   264  	old := crashFD.Swap(fd)
   265  
   266  	// If we are panicking, don't return the old FD to runtime/debug for
   267  	// closing. writeErrData may have already read the old FD from crashFD
   268  	// before the swap and closing it would cause the write to be lost [1].
   269  	// The old FD will never be closed, but we are about to crash anyway.
   270  	//
   271  	// On the writeErrData thread, panicking.Add(1) happens-before
   272  	// crashFD.Load() [2].
   273  	//
   274  	// On this thread, swapping old FD for new in crashFD happens-before
   275  	// panicking.Load() > 0.
   276  	//
   277  	// Therefore, if panicking.Load() == 0 here (old FD will be closed), it
   278  	// is impossible for the writeErrData thread to observe
   279  	// crashFD.Load() == old FD.
   280  	//
   281  	// [1] Or, if really unlucky, another concurrent open could reuse the
   282  	// FD, sending the write into an unrelated file.
   283  	//
   284  	// [2] If gp != nil, it occurs when incrementing gp.m.dying in
   285  	// startpanic_m. If gp == nil, we read panicking.Load() > 0, so an Add
   286  	// must have happened-before.
   287  	if panicking.Load() > 0 {
   288  		return ^uintptr(0)
   289  	}
   290  	return old
   291  }
   292  
   293  // auxv is populated on relevant platforms but defined here for all platforms
   294  // so x/sys/cpu and x/sys/unix can assume the getAuxv symbol exists without
   295  // keeping its list of auxv-using GOOS build tags in sync.
   296  //
   297  // It contains an even number of elements, (tag, value) pairs.
   298  var auxv []uintptr
   299  
   300  // golang.org/x/sys/cpu and golang.org/x/sys/unix use getAuxv via linkname.
   301  // Do not remove or change the type signature.
   302  // See go.dev/issue/57336 and go.dev/issue/67401.
   303  //
   304  //go:linkname getAuxv
   305  func getAuxv() []uintptr { return auxv }
   306  
   307  // zeroVal is used by reflect via linkname.
   308  //
   309  // zeroVal should be an internal detail,
   310  // but widely used packages access it using linkname.
   311  // Notable members of the hall of shame include:
   312  //   - github.com/ugorji/go/codec
   313  //
   314  // Do not remove or change the type signature.
   315  // See go.dev/issue/67401.
   316  //
   317  //go:linkname zeroVal
   318  var zeroVal [abi.ZeroValSize]byte
   319  

View as plain text