mirror of https://github.com/golang/go.git
163 lines
3.8 KiB
Go
163 lines
3.8 KiB
Go
// Copyright 2009 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package runtime
|
|
|
|
import (
|
|
"runtime/internal/atomic"
|
|
"unsafe"
|
|
)
|
|
|
|
//go:generate go run wincallback.go
|
|
//go:generate go run mkduff.go
|
|
//go:generate go run mkfastlog2table.go
|
|
//go:generate go run mklockrank.go -o lockrank.go
|
|
|
|
var ticks ticksType
|
|
|
|
type ticksType struct {
|
|
lock mutex
|
|
val atomic.Int64
|
|
}
|
|
|
|
// Note: Called by runtime/pprof in addition to runtime code.
|
|
func tickspersecond() int64 {
|
|
r := ticks.val.Load()
|
|
if r != 0 {
|
|
return r
|
|
}
|
|
lock(&ticks.lock)
|
|
r = ticks.val.Load()
|
|
if r == 0 {
|
|
t0 := nanotime()
|
|
c0 := cputicks()
|
|
usleep(100 * 1000)
|
|
t1 := nanotime()
|
|
c1 := cputicks()
|
|
if t1 == t0 {
|
|
t1++
|
|
}
|
|
r = (c1 - c0) * 1000 * 1000 * 1000 / (t1 - t0)
|
|
if r == 0 {
|
|
r++
|
|
}
|
|
ticks.val.Store(r)
|
|
}
|
|
unlock(&ticks.lock)
|
|
return r
|
|
}
|
|
|
|
var envs []string
|
|
var argslice []string
|
|
|
|
//go:linkname syscall_runtime_envs syscall.runtime_envs
|
|
func syscall_runtime_envs() []string { return append([]string{}, envs...) }
|
|
|
|
//go:linkname syscall_Getpagesize syscall.Getpagesize
|
|
func syscall_Getpagesize() int { return int(physPageSize) }
|
|
|
|
//go:linkname os_runtime_args os.runtime_args
|
|
func os_runtime_args() []string { return append([]string{}, argslice...) }
|
|
|
|
//go:linkname syscall_Exit syscall.Exit
|
|
//go:nosplit
|
|
func syscall_Exit(code int) {
|
|
exit(int32(code))
|
|
}
|
|
|
|
var godebugDefault string
|
|
var godebugUpdate atomic.Pointer[func(string, string)]
|
|
var godebugEnv atomic.Pointer[string] // set by parsedebugvars
|
|
var godebugNewIncNonDefault atomic.Pointer[func(string) func()]
|
|
|
|
//go:linkname godebug_setUpdate internal/godebug.setUpdate
|
|
func godebug_setUpdate(update func(string, string)) {
|
|
p := new(func(string, string))
|
|
*p = update
|
|
godebugUpdate.Store(p)
|
|
godebugNotify(false)
|
|
}
|
|
|
|
//go:linkname godebug_setNewIncNonDefault internal/godebug.setNewIncNonDefault
|
|
func godebug_setNewIncNonDefault(newIncNonDefault func(string) func()) {
|
|
p := new(func(string) func())
|
|
*p = newIncNonDefault
|
|
godebugNewIncNonDefault.Store(p)
|
|
}
|
|
|
|
// A godebugInc provides access to internal/godebug's IncNonDefault function
|
|
// for a given GODEBUG setting.
|
|
// Calls before internal/godebug registers itself are dropped on the floor.
|
|
type godebugInc struct {
|
|
name string
|
|
inc atomic.Pointer[func()]
|
|
}
|
|
|
|
func (g *godebugInc) IncNonDefault() {
|
|
inc := g.inc.Load()
|
|
if inc == nil {
|
|
newInc := godebugNewIncNonDefault.Load()
|
|
if newInc == nil {
|
|
return
|
|
}
|
|
// If other goroutines are racing here, no big deal. One will win,
|
|
// and all the inc functions will be using the same underlying
|
|
// *godebug.Setting.
|
|
inc = new(func())
|
|
*inc = (*newInc)(g.name)
|
|
g.inc.Store(inc)
|
|
}
|
|
(*inc)()
|
|
}
|
|
|
|
func godebugNotify(envChanged bool) {
|
|
update := godebugUpdate.Load()
|
|
var env string
|
|
if p := godebugEnv.Load(); p != nil {
|
|
env = *p
|
|
}
|
|
if envChanged {
|
|
reparsedebugvars(env)
|
|
}
|
|
if update != nil {
|
|
(*update)(godebugDefault, env)
|
|
}
|
|
}
|
|
|
|
//go:linkname syscall_runtimeSetenv syscall.runtimeSetenv
|
|
func syscall_runtimeSetenv(key, value string) {
|
|
setenv_c(key, value)
|
|
if key == "GODEBUG" {
|
|
p := new(string)
|
|
*p = value
|
|
godebugEnv.Store(p)
|
|
godebugNotify(true)
|
|
}
|
|
}
|
|
|
|
//go:linkname syscall_runtimeUnsetenv syscall.runtimeUnsetenv
|
|
func syscall_runtimeUnsetenv(key string) {
|
|
unsetenv_c(key)
|
|
if key == "GODEBUG" {
|
|
godebugEnv.Store(nil)
|
|
godebugNotify(true)
|
|
}
|
|
}
|
|
|
|
// writeErrStr writes a string to descriptor 2.
|
|
//
|
|
//go:nosplit
|
|
func writeErrStr(s string) {
|
|
write(2, unsafe.Pointer(unsafe.StringData(s)), int32(len(s)))
|
|
}
|
|
|
|
// auxv is populated on relevant platforms but defined here for all platforms
|
|
// so x/sys/cpu can assume the getAuxv symbol exists without keeping its list
|
|
// of auxv-using GOOS build tags in sync.
|
|
//
|
|
// It contains an even number of elements, (tag, value) pairs.
|
|
var auxv []uintptr
|
|
|
|
func getAuxv() []uintptr { return auxv } // accessed from x/sys/cpu; see issue 57336
|