Messages in this thread | | | From | Linus Torvalds <> | Date | Fri, 4 Jun 2021 12:09:26 -0700 | Subject | Re: [RFC] LKMM: Add volatile_if() |
| |
On Fri, Jun 4, 2021 at 11:27 AM Alan Stern <stern@rowland.harvard.edu> wrote: > > volatile_if (READ_ONCE(*x) * 0 + READ_ONCE(*y)) > WRITE_ONCE(*z, 42); > > where there is no ordering between *x and *z.
I wouldn't worry about it.
I think a compiler is allowed to optimize away stupid code.
I get upset when a compiler says "oh, that's undefined, so I will ignore the obvious meaning of it", but that's a different thing entirely.
I really wish that the C standards group showed some spine, and said "there is no undefined, there is only implementation-defined". That would solve a *lot* of problems.
But I also realize that will never happen. Because "spine" and "good taste" is not something that I've ever heard of happening in an industry standards committee.
Side note: it is worth noting that my version of "volatile_if()" has an added little quirk: it _ONLY_ orders the stuff inside the if-statement.
I do think it's worth not adding new special cases (especially that "asm goto" hack that will generate worse code than the compiler could do), but it means that
x = READ_ONCE(ptr); volatile_if (x > 0) WRITE_ONCE(*z, 42);
has an ordering, but if you write it as
x = READ_ONCE(ptr); volatile_if (x <= 0) return; WRITE_ONCE(*z, 42);
then I could in theory see teh compiler doing that WRITE_ONCE() as some kind of non-control dependency.
That said, I don't actually see how the compiler could do anything that actually broke the _semantics_ of the code. Yes, it could do the write using a magical data dependency on the conditional and turning it into a store on a conditional address instead (before doing the branch), but honestly, I don't see how that would actually break anything.
So this is more of a "in theory, the two sides are not symmetric". The "asm volatile" in a barrier() will force the compiler to generate the branch, and the memory clobber in barrier() will most certainly force any stores inside the "volatile_if()" to be after the branch.
But because the memory clobber is only inside the if-statement true case, the false case could have the compiler migrate any code in that false thing to before the if.
Again, semantics do matter, and I don't see how the compiler could actually break the fundamental issue of "load->conditional->store is a fundamental ordering even without memory barriers because of basic causality", because you can't just arbitrarily generate speculative stores that would be visible to others.
But at the same time, that's *such* a fundamental rule that I really am intrigued why people think "volatile_if()" is needed in reality (as opposed to some "in theory, the compiler can know things that are unknowable thanks to a magical oracle" BS argument)
Linus
| |