-
Notifications
You must be signed in to change notification settings - Fork 17.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
x/sys/cpu: respect CPU feature overrides specified in GODEBUG #33963
Comments
I think we should port over all CPU feature masking options that internal/cpu supports. Individual feature settings and masking all features. This will also help packages imported into the standard library that use x/sys/cpu (see #32102) to be aligned with what internal/cpu will report. Adding others to discuss if it is ok for x/ packages to interpret GODEBUG. |
Remind me why we have both internal/cpu and golang.org/x/sys/cpu? It'd sure be nice if we only had one (x/sys/cpu) and the Go runtime could just use it. |
To the extent that I also agree with @bradfitz that ideally in the long term we should find some way to consolidate on only |
I think there is a lot of scope to share an implementation (or large parts thereof), but it isn't trivial. |
The encoding/binary dependency is not necessary. And the only use of runtime is to look at It seems like we could make golang.org/x/sys/cpu a leaf package and drop internal/cpu. |
Other complications for why runtime does not use x/sys/cpu:
Let me ask the other way around when we already think about sharing a common implementation: |
We've tried to stop adding new packages to std, preferring everything to be public where it can have its own release cadence. (e.g. fix bugs today, don't wait 6 months.... https://golang.org/doc/faq#x_in_std) |
I am aware of that but I think that point will lose some of its appeal when we hide the coupling with runtime internals under the hood with build tags and unsafe. We also have exposed other std lib/runtime functions in new std lib packages lately like bytes/hash that are coupled to the runtime. If we will have a serious bug in CPU feature detection I would want to fix that for the runtime in a point release too instead of waiting 6 months. |
I sent https://go-review.googlesource.com/c/sys/+/194646 to remove the encoding/binary dependency at least. We don't use maps as-is. Maybe that complicates the GODEBUG parsing, but we have the code already without it, and it's not particularly performance sensitive. For hwcap, perhaps a new // These are initialized by archauxv in runtime/os_linux_arm64.go.
var HWCap uint
var HWCap2 uint Those could be: //go:hwcap1
var HWCap uint
//go:hwcap2
var HWCap2 uint And any package (or one package under different versions) could all get it initialized. |
Probably many people know this, but some background. Right now the Any attempt to replace internal/cpu with x/sys/cpu needs to preserve that property. If we vendor x/sys/cpu, and update the initialization so that it works with the vendored x/sys/cpu replacing internal/cpu, then the initialization will only affect the vendored copy. It won't affect user imports of golang.org/x/sys/cpu. Using One approach might be
At first glance I think that handles everything except that the godoc for x/sys/cpu might be bad. |
Just a drive by comment @ianlancetaylor.
Instead of this, which as you note would make the documentation confusing, what if x/sys/cpu just redeclared all the Something like: package cpu
import "golang.org/x/sys/cpu/internal/details"
var X86 struct{
HasAES bool // AES hardware implementation (AES NI)
// ...
}
func init() {
X86.HasAES = details.X86.HasAES
// ...
} That way the godoc is exactly the same as it is now. The struct declarations and the copying could even be automated with |
Sure, we could do that, but it's less than ideal because then we have two copies of all the types. Let's see if we can figure out a better way. |
There is an interesting interplay with #30241. If |
I'm probably missing something, but couldn't we use a |
Note that the standard library does not in general have access to |
So here is one possible alternative.
Then the startup sequence becomes, roughly:
If we eventually unify |
Would there be a problem later with the outlined procedure when user code or std lib needs to initialize two different major versions of x/sys/cpu? When HWcap3 or similar comes along that needs to be sourced from runtime I assume we would need build tags on the initialization or variables linknamed in x/sys/cpu? |
I don't think so? If I understand linking correctly(‽), the For simplicity, presumably the standard library should depend on only one major version of
Yes, that seems correct. |
I was thinking about initialization function problems with different major versions. I guess there is no problem because runtime only needs to initialize the major version that it itself uses. |
I'm nervous about trying to use I think we clearly want a user program to be able to import its own specific version of golang.org/x/sys/cpu without anything breaking if the standard library is using a different (vendored) version of golang.org/x/sys/cpu. It's not immediately obvious to me how to do that if we are using special directives. If we're willing to use a build tag to build the vendored version of golang.org/x/sys/cpu, then I think we can adopt my earlier suggestion without the cpu/internal/details packages, while retaining a usable godoc and without relying on any special linker directives for vendored packages. |
I don't think that's incompatible with the (That may imply that the aliased variables need to be unexported, but if need be we can use an ordinary |
I would really rather not do that if we can avoid it — a dependency on path-specific build tags would add a lot of complexity if we eventually allow |
Actually, I don't think we need Then we vendor in |
I don't see how we can usefully merge vendor/golang.org/x/sys/cpu with golang.org/x/sys/cpu, given that in the normal case they will be different versions of the package. And it's a fairly small package. Is it worth doing the work to merge the two packages in the special case where they are exactly the same version? I do think that a runtime/cpu package would work, if we decide that it's OK to add that to the standard library API. |
Given how special this package is (effectively part of the runtime already), I'd be fine with exporting it as |
If we end up doing #30241, then the version of |
@bcmills Given that the package is tightly tied to the runtime, I don't see how that could work in general. It would become impossible for us to significantly change the package in any way; if we did we would break people using different versions of the external package. |
@ianlancetaylor, as long as the runtime ABI only changes at major releases, |
It seems to me that the likelihood of subtle problems from doing this outweighs any possible benefit. |
@PolliOs has a prototype to support GODEBUG for x/sys/cpu which we will send for review after a bit more testing and refinement. |
This comment has been minimized.
This comment has been minimized.
Change https://golang.org/cl/245237 mentions this issue: |
golang.org/x/sys/cpu does not allow CPU feature detection to be overridden, unlike internal/cpu. This results in surprising behavior while debugging software that do not use internal/cpu but the external golang.org/x/sys/cpu package.
@martisch already mentioned this difference in #32102 (comment).
The use case was forcing qtls in https://github.com/lucas-clemente/quic-go to use ChaCha20-Poly1305 instead of AES128-GCM in TLS 1.3 for debugging purposes.
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes, reproduced with golang/sys@5fe476d.
What did you do?
Create detect.go:
Run with:
What did you expect to see?
What did you see instead?
The text was updated successfully, but these errors were encountered: