-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
sync::Once use release-acquire access modes #52349
Conversation
r? @sfackler (rust_highfive has picked a reviewer for you, use r? to override) |
src/libstd/sync/once.rs
Outdated
@@ -323,7 +323,7 @@ impl Once { | |||
POISONED | | |||
INCOMPLETE => { | |||
let old = self.state.compare_and_swap(state, RUNNING, | |||
Ordering::SeqCst); | |||
Ordering::AcqRel); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These could use compare_exchange
and a Ordering::Relaxed
for the failure
ordering, I believe. Do you have a way to verify/check that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could try to bribe Hai or @jhjourdan into proving it. ;) But that's likely not going to happen soon. Personally I will not use Relaxed
anywhere without being really sure.
cc #27610 and previous attempts #31650 and #44331. The conclusions there were to keep everything I personally strongly disagree with this decision. I think that |
Notice that I am not directly involved in this work, and they have not looked at |
FWIW I'm at least personally still a novice with atomic orderings which (as mentioned by @gereeter) in previous threads is why I've proposed for leaving this as @RalfJung you mentioned on Reddit that One question I'd have about this patch as-is is that it seems to differ from #44331 in a few orderings. Specifically in I completely agree that Now if we literally have an academic proof for the orderings being correct I'm all for switching to those orderings! Before that, though, I'm personally hesitant to do so without motivation in terms of benchmarks. I certainly trust @RalfJung to get concurrent orderings more correct than myself though! |
|
I just noticed Jehoon did that previous PR. He certainly knows more about weak memory than I do.^^
I don't think that is correct, e.g. rust/src/libcore/sync/atomic.rs Line 1727 in 7751885
However, I wish what you said was true because then one could just use |
Oh, I was looking at the wrong op (the Yeah… |
Would that need an RFC or is a PR enough? It'd be insta-stable... so I'd guess it needs an RFC. |
Since both C++ and LLVM do not permit it, there might be a good reason for that. I would be somewhat reluctant to land such change with just a PR. |
Certainly, whenever release-acquire is correct, then
I trust @jeehoonkang got this right.
Shall I change this PR to only make that an
Fair enough. Maybe we can get @jhjourdan or Hai (don't know his GitHub handle) to do a proof. ;) |
I think there are two different schools in concurrent programming: what I call the "bullet-proof" school and the "logical proof" school. In the bullet-proof school, people know that concurrent programming is hard, and in order to make it right, they don't optimize things when not 100% sure. The meaning of "100%" may vary among people: someone thinks a lot of tests; another thinks no fine-grained concurrency; maybe On the other hand, in the logical proof school, people know that concurrent programming is hard, but thanks to the recent advances of reasoning principles, it is no longer a beast. Iris and LambdaRust from @drdreyer's group (where @RalfJung is!) are notable examples of such reasoning principles, on which you can prove why certain fine-grained concurrency patterns are correct. Once an implementation is proved, we can believe the result and fearlessly deploy it. I'm personally an advocate for the logical proof school, and I believe so is @RalfJung. That's why we're constantly proposing to lower orderings in Rust std: e.g. we believe we "know" the logical proof of Probably this disagreement comes from the fact that the logical proof school has not finished its job yet: while we at academia have produced quite solid results so far, based on which I'm quite confident that using release/acquire is safe in |
Well put. I was not aware that there had been previous proposals to change the synchronization mode when I opened this PR -- so it seems likely to at least be a good idea to add a comment that prevents more people from repeating the same thing in the future. ;) |
Indeed well put! And to be clear, I'd be totally comfortable with a proof. @RalfJung's work and all have already found multiple bugs in libstd through proofs, so I have a good deal of confidence in them! I'm under the impression though that one doesn't exist for @jeehoonkang heh I think I would definitely classify myself in the "bullet-proof" school in that case! I definitely do agree that using release/acquire can convey intent more clearly, but my worry is that I will convey myself incorrectly because I don't fully understand release/acquire. In that sense I know I can't miscommuniate if I always use @RalfJung I'd be totally down with some comments in the code about "usage of |
Release stores, however, do have different codegen even on x86. From my understanding, this is unlikely to matter for Once since there's no stores on the hot path, but it's still useful to keep in mind. No architecture of interest provides SC for free, not even those with the relatively strong TSO model. |
Correct, there is no proof for I have sense then browser some more placed in libstd and seen that
I am really surprised that there is no codegen difference for the ARM architectures -- but indeed, this website lists "ldr; dmb ish" as codegen for both |
Actually, Hai and I talked about it today. We will see if it is possible to do a proof for Once without too much effort. The main technical issue has to do with the fact that there are comparisons of pointer equality, which means we have to show that any pointer we could possibly compare for equality has not been deallocated. Should be doable, but may be tricky. I don't think it has anything to do with weak memory. |
So it is not enough to rely on the non-determinism in case the pointer has been deallocated? |
Meanwhile, I have reduced this PR to just do |
Well, the problem is that if you do a CAS on a location that might be storing a deallocated pointer, then it might succeed even though the things being compared are not equal, and I don't know how you would reason about that. So I think you need to arrange for the location's invariant to store some knowledge that its contents are not a deallocated pointer. |
@bors: r+ |
📌 Commit 3e1254d has been approved by |
RFC submitted: rust-lang/rfcs#2503 |
sync::Once use release-acquire access modes Nothing here makes a case distinction like "this happened before OR after that". All we need is to get happens-before edges whenever we see that the state/signal has been changed. Release-acquire is good enough for that.
☀️ Test successful - status-appveyor, status-travis |
Nothing here makes a case distinction like "this happened before OR after that". All we need is to get happens-before edges whenever we see that the state/signal has been changed. Release-acquire is good enough for that.