On Wed, Feb 19, 2014 at 8:01 PM, Paul E. McKenney <paul...@linux.vnet.ibm.com> wrote: > > The control dependency should order subsequent stores, at least assuming > that "a" and "b" don't start off with identical stores that the compiler > could pull out of the "if" and merge. The same might also be true for ?: > for all I know. (But see below)
Stores I don't worry about so much because (a) you can't sanely move stores up in a compiler anyway (b) no sane CPU or moves stores up, since they aren't on the critical path so a read->cmp->store is actually really hard to make anything sane re-order. I'm sure it can be done, and I'm sure it's stupid as hell. But that "it's hard to screw up" is *not* true for a load->cmp->load. So lets make this really simple: if you have a consume->cmp->read, is the ordering of the two reads guaranteed? > As long as there is an unbroken chain of -data- dependencies from the > consume to the later access in question, and as long as that chain > doesn't go through the excluded operations, yes. So let's make it *really* specific, and make it real code doing a real operation, that is actually realistic and reasonable in a threaded environment, and may even be in some critical code. The issue is the read-side ordering guarantee for 'a' and 'b', for this case: - Initial state: a = b = 0; - Thread 1 ("consumer"): if (atomic_read(&a, consume)) return b; /* not yet initialized */ return -1; - Thread 2 ("initializer"): b = some_value_lets_say_42; /* We are now ready to party */ atomic_write(&a, 1, release); and quite frankly, if there is no ordering guarantee between the read of "a" and the read of "b" in the consumer thread, then the C atomics standard is broken. Put another way: I claim that if "thread 1" ever sees a return value other than -1 or 42, then the whole definition of atomics is broken. Question 2: and what changes if the atomic_read() is turned into an acquire, and why? Does it start working? > Neither has a data-dependency guarantee, because there is no data > dependency from the load to either "a" or "b". After all, the value > loaded got absorbed into the "if" condition. However, according to > discussions earlier in this thread, the "if" variant would have a > control-dependency ordering guarantee for any stores in "a" and "b" > (but not loads!). So exactly what part of the standard allows the loads to be re-ordered, and why? Quite frankly, I'd think that any sane person will agree that the above code snippet is realistic, and that my requirement that thread 1 sees either -1 or 42 is valid. And if the C standards body has said that control dependencies break the read ordering, then I really think that the C standards committee has screwed up. If the consumer of an atomic load isn't a pointer chasing operation, then the consume should be defined to be the same as acquire. None of this "conditionals break consumers". No, conditionals on the dependency path should turn consumers into acquire, because otherwise the "consume" load is dangerous as hell. And if the definition of acquire doesn't include the control dependency either, then the C atomic memory model is just completely and utterly broken, since the above *trivial* and clearly useful example is broken. I really think the above example is pretty damn black-and-white. Either it works, or the standard isn't worth wiping your ass with. Linus