-
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
proposal: add a handful of acquire/release atomics (make the internal runtime versions public) #70607
Comments
Related Issues (Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.) |
As far as I can tell the current *Rel and *Acq versions only differ from the standard versions on ppc64. |
Oh, you mean they don't have proper acquire or release semantics on other platforms? Interesting. Could we have that for the runtime and the atomics library? My understanding is the the standard Go atomic promise sequential consistency, which require a lock prefix or fence on x86/64 processors. The documentation states "This definition provides the same semantics as C++'s sequentially consistent atomics". Since x86 mov instructions have acquire/release semantics, you need a fence or stronger instruction (I believe it's common to abuse xchg instruction for this). |
The intrinsics are only implemented for PPC64: go/src/cmd/compile/internal/ssagen/intrinsics.go Lines 243 to 256 in caee788
go/src/cmd/compile/internal/ssagen/intrinsics.go Lines 289 to 300 in caee788
Looking through the
Otherwise they are TCO wrappers around the sequentially consistent atomics. note: the compiler internally use theses functions calls to disable certain optimizations and various other things, because the implementation of atomic uses non atomic operators does not mean it is safe to do so outside of theses exact functions. If anything I guess this is because no one found a compelling use for theses, we can implement relaxed store and acquire load on most architectures people would care about if this proposal required it, for others fallback to sqcst impls as we currently do. |
Interesting, so go just uses a plain mov on x86/64 for atomic load, which actually is the same as what C++ does. It implements the Store with XCHG, which is also what C++ does. So then the question is, if we implement the release store with mov instead of xchg on x86/x64, does it matter? It would be faster, but in an impactful way? I would guess it matters a lot more on looser architectures like arm. Go has an extensive benchmark suite, and it uses StoreRel in some parts of the runtime. So I guess we could test this for the Go runtime pretty easily. It'd be nice to test it for a synthetic benchmark too, to see how much of a difference there is in theory. I could start with that. |
Proposal Details
I asked for this a decade ago, and I want to start this discussion up again.
I'm not saying Go should add the full gamut of relaxed, acquire, release, etc orderings available in other languages.
But I am saying it's useful to have some basic acquire and release loads and stores for 32bit, 64bit, and uintptr.
To see that this is useful one need look no further than the Go runtime which use exactly these.
uintptr:
internal/runtime/atomic.LoadAcquintptr
internal/runtime/atomic.StoreReluintptr
uint32:
internal/runtime/atomic.LoadAcq
internal/runtime/atomic.StoreRel
uint64:
internal/runtime/atomic.LoadAcq64
internal/runtime/atomic.StoreRel64
I would like that we make these 6 functions available in the atomics package and a LoadAcq and StoreRel on each of the atomic types. I can make a PR.
It's not that these are so advanced and so dangerous that only Go runtime authors should have them. We deserve advanced tools too. For a language with concurrency as a strength, it's lacking in some important primitives to develop performant concurrent data structures. And it's not that we can't have that in Go, it's already implemented, it just isn't public.
The text was updated successfully, but these errors were encountered: