Re: Question regarding "Control Dependencies" in memory-barriers.txt

From: Pranith Kumar
Date: Tue Aug 05 2014 - 08:14:30 EST


On Tue, Aug 5, 2014 at 3:32 AM, Peter Zijlstra <peterz@xxxxxxxxxxxxx> 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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/