diff options
| author | Russ Cox <rsc@golang.org> | 2022-11-11 12:36:31 -0500 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2022-11-14 15:19:57 +0000 |
| commit | ea4631cc0cf301c824bd665a7980c13289ab5c9d (patch) | |
| tree | 78c1ee219438b55df5da49575bf4cbbefe590f1e /src/runtime/runtime.go | |
| parent | 40bdcbb483548c0b660503c3ba80f9676b98fd5f (diff) | |
| download | go-ea4631cc0cf301c824bd665a7980c13289ab5c9d.tar.xz | |
internal/godebug: define more efficient API
We have been expanding our use of GODEBUG for compatibility,
and the current implementation forces a tradeoff between
freshness and efficiency. It parses the environment variable
in full each time it is called, which is expensive. But if clients
cache the result, they won't respond to run-time GODEBUG
changes, as happened with x509sha1 (#56436).
This CL changes the GODEBUG API to provide efficient,
up-to-date results. Instead of a single Get function,
New returns a *godebug.Setting that itself has a Get method.
Clients can save the result of New, which is no more expensive
than errors.New, in a global variable, and then call that
variable's Get method to get the value. Get costs only two
atomic loads in the case where the variable hasn't changed
since the last call.
Unfortunately, these changes do require importing sync
from godebug, which will mean that sync itself will never
be able to use a GODEBUG setting. That doesn't seem like
such a hardship. If it was really necessary, the runtime could
pass a setting to package sync itself at startup, with the
caveat that that setting, like the ones used by runtime itself,
would not respond to run-time GODEBUG changes.
Change-Id: I99a3acfa24fb2a692610af26a5d14bbc62c966ac
Reviewed-on: https://go-review.googlesource.com/c/go/+/449504
Run-TryBot: Russ Cox <rsc@golang.org>
Auto-Submit: Russ Cox <rsc@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Diffstat (limited to 'src/runtime/runtime.go')
| -rw-r--r-- | src/runtime/runtime.go | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/src/runtime/runtime.go b/src/runtime/runtime.go index bc60b3ca75..9f68738aa7 100644 --- a/src/runtime/runtime.go +++ b/src/runtime/runtime.go @@ -66,14 +66,26 @@ func syscall_Exit(code int) { exit(int32(code)) } -var godebugenv atomic.Pointer[string] // set by parsedebugvars +var godebugDefault string +var godebugUpdate atomic.Pointer[func(string, string)] +var godebugEnv atomic.Pointer[string] // set by parsedebugvars -//go:linkname godebug_getGODEBUG internal/godebug.getGODEBUG -func godebug_getGODEBUG() string { - if p := godebugenv.Load(); p != nil { - return *p +//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() +} + +func godebugNotify() { + if update := godebugUpdate.Load(); update != nil { + var env string + if p := godebugEnv.Load(); p != nil { + env = *p + } + (*update)(godebugDefault, env) } - return "" } //go:linkname syscall_runtimeSetenv syscall.runtimeSetenv @@ -82,7 +94,8 @@ func syscall_runtimeSetenv(key, value string) { if key == "GODEBUG" { p := new(string) *p = value - godebugenv.Store(p) + godebugEnv.Store(p) + godebugNotify() } } @@ -90,7 +103,8 @@ func syscall_runtimeSetenv(key, value string) { func syscall_runtimeUnsetenv(key string) { unsetenv_c(key) if key == "GODEBUG" { - godebugenv.Store(nil) + godebugEnv.Store(nil) + godebugNotify() } } |
