Why release sequence can only contain read-modify-write but not pure write
Asked Answered
V

0

6

After a release operation A is performed on an atomic object M, the longest continuous subsequence of the modification order of M that consists of:

  1. Writes performed by the same thread that performed A. (until C++20)
  2. Atomic read-modify-write operations made to M by any thread. Is known as release sequence headed by A.
  • Q1: Why do we need the concept of release sequence?

    A1: See What does "release sequence" mean?

  • Q2: Is the first item removed in C++20?

  • Q3: Why read-modify-write operations qualify in a release sequence but pure write operations don't?

    What's special about relaxed RMWs that lets them form a chain without being an acquire load and release store? Either in computer-architecture terms, or in C++ language formalism? Or to put it another way, how can hardware support release-sequence semantics for atomic RMWs but have pure stores that break connections?

Vastha answered 10/9, 2023 at 11:57 Comment(11)
We need the concept of a release-sequence because some hardware is weak enough that an acquire load might not sync-with all previous release-stores in the modification-order for that object, not just the one who's value headed this release-sequence. My answer on What does "release sequence" mean? explains that most hardware is stronger, and provides the guarantees of older C++ standards from before they came up with the release-sequence rule at all.Legal
(IDK why C++20 removed point 1. Maybe with thread migration between cores could make things weaker? But that itself has to involve at least acq/rel sync (happens-before) between cores on the OS's part to not break multithreaded code. So maybe some other reason.)Legal
@PeterCordes Proposal and discussion is in open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0982r1.html.Ascensive
Basically, no known use case for this specific bullet, but it could negatively affect future hardware implementations that want to be compatible with the C++ memory model.Ascensive
@user17732522: Oh right, a release store by the same thread starts a new release-sequence, but everything before the previous release store is also before the later one. So that "writes performed by the same thread" guarantee was only relevant for relaxed stores, which is indeed weird. Thanks for the WG21 link on the motivation. I'm curious what hypothetical hardware design would be constrained by that; the writeup suggests that there could be some, unless they actually just meant that supporting the RMW-from-other-cores part of release sequences was a burden on current designs.Legal
@TSK: What kind of answer are you looking for in Q3? Like a [cpu-architecture] answer in terms of how these are implemented on PowerPC where store-forwarding between SMT logical cores makes it not Just Work for pure stores? Or pointing out that RMWs are required by ISO C++ to see the "latest value" (which many people get hung up on and think that makes them better for inter-thread latency; it doesn't, it just means RMWs on the same location are serialized with each other and writes, making it possible for them to be atomic, e.g. so fetch_add doesn't lose counts.)Legal
Although it takes some mental effort (at least to me it took some effort), you have to realize that a read is not in any way a write (not even of write of the read value, unlike what happens at the physical level on some circuitry) and that loads on atomics are not modifications, so 1) they can't have release semantics 2) can't appear in the modification order. If you want a read that is a modification, make it a RMW of the same value (hence it can have release semantics).Breadfruit
@PeterCordes (Q3) I was wondering why RMWs can be included a release sequence but pure stores cannot. The "read" part of RMWs doesn't look important here. It should be some special characteristics of RMWs that qualify them in a release sequence.Vastha
Ok, yeah, that's an interesting question. You should edit the question to elaborate on that. As for an answer, partly because real HW provides that guarantee for RMWs but not for pure stores. The store has a data dependency on the load, which is probably significant, but I'd have to think about or research some more details.Legal
If you had a middle-man thread that, instead of relaxed RMW, did an acquire load and then a release store back to the same object, IIRC the resulting happens-before is strong enough to be transitive; an acquire load of that new value would see values from before the original release store as well. But IDK about consume load / release store as a replacement for a relaxed RMW.Legal
Re: your title: reads don't disturb a release-sequence; any number of other threads can observe values if they want to. But x.store(x.load(relaxed), relaxed) would on paper, if that's what you mean. Reads aren't part of the modification order, they just observe a point in it.Legal

© 2022 - 2024 — McMap. All rights reserved.