On Tue, Aug 5, 2014 at 3:32 AM, Peter Zijlstra <pet...@infradead.org> wrote: >> >> 685 This transformation loses the ordering between the load from variable 'a' >> 686 and the store to variable 'b'. If you are relying on this ordering, you >> 687 should do something like the following: >> 688 >> 689 q = ACCESS_ONCE(a); >> 690 BUILD_BUG_ON(MAX <= 1); /* Order load from a with store to b. */ >> 691 if (q % MAX) { >> 692 ACCESS_ONCE(b) = p; >> 693 do_something(); >> 694 } else { >> 695 ACCESS_ONCE(b) = p; >> 696 do_something_else(); >> 697 } >> 698 >> >> How is the BUILD_BUG_ON(MAX <= 1) guaranteeing the ordering w.r.t 'a' >> and 'b'. Shouldn't it have barrier() in both the legs of the if() >> statement like follows: > > The BUILD_BUG_ON guarantees that 'q % MAX' isn't a constant, and > therefore the compiler cannot take the conditional out. > > And no barrier() doesn't order anything except compiler output. The > ordering here happens by the conditional, CPUs do not do speculative > writes, this means it has to complete the load of q to compute the > branch before it can execute the store of b. > >
I don't think the write to 'b' here is speculative since it is happening in both the legs of the if() conditional. The write to b can be pulled out to before the conditional. Without the barrier(), isn't the following a valid transformation of the above? BUILD_BUG_ON(MAX <= 1); /* this will be compiled out if MAX != 1*/ q = ACCESS_ONCE(a); ACCESS_ONCE(b) = p; / *BUG: No ordering */ if (q % MAX) { do_something(); } else { do_something_else(); } I don't see how it is preserving the ordering. -- Pranith -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/