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.
8 "runtime/internal/atomic"
12 //go:generate go run wincallback.go
13 //go:generate go run mkduff.go
14 //go:generate go run mkfastlog2table.go
15 //go:generate go run mklockrank.go -o lockrank.go
19 type ticksType struct {
20 // lock protects access to start* and val.
27 // init initializes ticks to maximize the chance that we have a good ticksPerSecond reference.
29 // Must not run concurrently with ticksPerSecond.
30 func (t *ticksType) init() {
32 t.startTime = nanotime()
33 t.startTicks = cputicks()
37 // minTimeForTicksPerSecond is the minimum elapsed time we require to consider our ticksPerSecond
38 // measurement to be of decent enough quality for profiling.
40 // There's a linear relationship here between minimum time and error from the true value.
41 // The error from the true ticks-per-second in a linux/amd64 VM seems to be:
42 // - 1 ms -> ~0.02% error
43 // - 5 ms -> ~0.004% error
44 // - 10 ms -> ~0.002% error
45 // - 50 ms -> ~0.0003% error
46 // - 100 ms -> ~0.0001% error
48 // We're willing to take 0.004% error here, because ticksPerSecond is intended to be used for
49 // converting durations, not timestamps. Durations are usually going to be much larger, and so
50 // the tiny error doesn't matter. The error is definitely going to be a problem when trying to
51 // use this for timestamps, as it'll make those timestamps much less likely to line up.
52 const minTimeForTicksPerSecond = 5_000_000*(1-osHasLowResClockInt) + 100_000_000*osHasLowResClockInt
54 // ticksPerSecond returns a conversion rate between the cputicks clock and the nanotime clock.
56 // Note: Clocks are hard. Using this as an actual conversion rate for timestamps is ill-advised
57 // and should be avoided when possible. Use only for durations, where a tiny error term isn't going
58 // to make a meaningful difference in even a 1ms duration. If an accurate timestamp is needed,
59 // use nanotime instead. (The entire Windows platform is a broad exception to this rule, where nanotime
60 // produces timestamps on such a coarse granularity that the error from this conversion is actually
63 // The strategy for computing the conversion rate is to write down nanotime and cputicks as
64 // early in process startup as possible. From then, we just need to wait until we get values
65 // from nanotime that we can use (some platforms have a really coarse system time granularity).
66 // We require some amount of time to pass to ensure that the conversion rate is fairly accurate
67 // in aggregate. But because we compute this rate lazily, there's a pretty good chance a decent
68 // amount of time has passed by the time we get here.
70 // Must be called from a normal goroutine context (running regular goroutine with a P).
72 // Called by runtime/pprof in addition to runtime code.
74 // TODO(mknyszek): This doesn't account for things like CPU frequency scaling. Consider
75 // a more sophisticated and general approach in the future.
76 func ticksPerSecond() int64 {
77 // Get the conversion rate if we've already computed it.
83 // Compute the conversion rate.
92 // Grab the current time in both clocks.
94 nowTicks := cputicks()
96 // See if we can use these times.
97 if nowTicks > ticks.startTicks && nowTime-ticks.startTime > minTimeForTicksPerSecond {
98 // Perform the calculation with floats. We don't want to risk overflow.
99 r = int64(float64(nowTicks-ticks.startTicks) * 1e9 / float64(nowTime-ticks.startTime))
101 // Zero is both a sentinel value and it would be bad if callers used this as
102 // a divisor. We tried out best, so just make it 1.
111 // Sleep in one millisecond increments until we have a reliable time.
118 var argslice []string
120 //go:linkname syscall_runtime_envs syscall.runtime_envs
121 func syscall_runtime_envs() []string { return append([]string{}, envs...) }
123 //go:linkname syscall_Getpagesize syscall.Getpagesize
124 func syscall_Getpagesize() int { return int(physPageSize) }
126 //go:linkname os_runtime_args os.runtime_args
127 func os_runtime_args() []string { return append([]string{}, argslice...) }
129 //go:linkname syscall_Exit syscall.Exit
131 func syscall_Exit(code int) {
135 var godebugDefault string
136 var godebugUpdate atomic.Pointer[func(string, string)]
137 var godebugEnv atomic.Pointer[string] // set by parsedebugvars
138 var godebugNewIncNonDefault atomic.Pointer[func(string) func()]
140 //go:linkname godebug_setUpdate internal/godebug.setUpdate
141 func godebug_setUpdate(update func(string, string)) {
142 p := new(func(string, string))
144 godebugUpdate.Store(p)
148 //go:linkname godebug_setNewIncNonDefault internal/godebug.setNewIncNonDefault
149 func godebug_setNewIncNonDefault(newIncNonDefault func(string) func()) {
150 p := new(func(string) func())
151 *p = newIncNonDefault
152 godebugNewIncNonDefault.Store(p)
155 // A godebugInc provides access to internal/godebug's IncNonDefault function
156 // for a given GODEBUG setting.
157 // Calls before internal/godebug registers itself are dropped on the floor.
158 type godebugInc struct {
160 inc atomic.Pointer[func()]
163 func (g *godebugInc) IncNonDefault() {
166 newInc := godebugNewIncNonDefault.Load()
170 // If other goroutines are racing here, no big deal. One will win,
171 // and all the inc functions will be using the same underlying
174 *inc = (*newInc)(g.name)
180 func godebugNotify(envChanged bool) {
181 update := godebugUpdate.Load()
183 if p := godebugEnv.Load(); p != nil {
187 reparsedebugvars(env)
190 (*update)(godebugDefault, env)
194 //go:linkname syscall_runtimeSetenv syscall.runtimeSetenv
195 func syscall_runtimeSetenv(key, value string) {
197 if key == "GODEBUG" {
205 //go:linkname syscall_runtimeUnsetenv syscall.runtimeUnsetenv
206 func syscall_runtimeUnsetenv(key string) {
208 if key == "GODEBUG" {
209 godebugEnv.Store(nil)
214 // writeErrStr writes a string to descriptor 2.
217 func writeErrStr(s string) {
218 write(2, unsafe.Pointer(unsafe.StringData(s)), int32(len(s)))
221 // auxv is populated on relevant platforms but defined here for all platforms
222 // so x/sys/cpu can assume the getAuxv symbol exists without keeping its list
223 // of auxv-using GOOS build tags in sync.
225 // It contains an even number of elements, (tag, value) pairs.
228 func getAuxv() []uintptr { return auxv } // accessed from x/sys/cpu; see issue 57336