|
@@ -806,6 +806,41 @@ out-guess your code. More generally, although READ_ONCE() does force
|
|
|
the compiler to actually emit code for a given load, it does not force
|
|
|
the compiler to use the results.
|
|
|
|
|
|
+In addition, control dependencies apply only to the then-clause and
|
|
|
+else-clause of the if-statement in question. In particular, it does
|
|
|
+not necessarily apply to code following the if-statement:
|
|
|
+
|
|
|
+ q = READ_ONCE(a);
|
|
|
+ if (q) {
|
|
|
+ WRITE_ONCE(b, p);
|
|
|
+ } else {
|
|
|
+ WRITE_ONCE(b, r);
|
|
|
+ }
|
|
|
+ WRITE_ONCE(c, 1); /* BUG: No ordering against the read from "a". */
|
|
|
+
|
|
|
+It is tempting to argue that there in fact is ordering because the
|
|
|
+compiler cannot reorder volatile accesses and also cannot reorder
|
|
|
+the writes to "b" with the condition. Unfortunately for this line
|
|
|
+of reasoning, the compiler might compile the two writes to "b" as
|
|
|
+conditional-move instructions, as in this fanciful pseudo-assembly
|
|
|
+language:
|
|
|
+
|
|
|
+ ld r1,a
|
|
|
+ ld r2,p
|
|
|
+ ld r3,r
|
|
|
+ cmp r1,$0
|
|
|
+ cmov,ne r4,r2
|
|
|
+ cmov,eq r4,r3
|
|
|
+ st r4,b
|
|
|
+ st $1,c
|
|
|
+
|
|
|
+A weakly ordered CPU would have no dependency of any sort between the load
|
|
|
+from "a" and the store to "c". The control dependencies would extend
|
|
|
+only to the pair of cmov instructions and the store depending on them.
|
|
|
+In short, control dependencies apply only to the stores in the then-clause
|
|
|
+and else-clause of the if-statement in question (including functions
|
|
|
+invoked by those two clauses), not to code following that if-statement.
|
|
|
+
|
|
|
Finally, control dependencies do -not- provide transitivity. This is
|
|
|
demonstrated by two related examples, with the initial values of
|
|
|
x and y both being zero:
|
|
@@ -869,6 +904,12 @@ In summary:
|
|
|
atomic{,64}_read() can help to preserve your control dependency.
|
|
|
Please see the COMPILER BARRIER section for more information.
|
|
|
|
|
|
+ (*) Control dependencies apply only to the then-clause and else-clause
|
|
|
+ of the if-statement containing the control dependency, including
|
|
|
+ any functions that these two clauses call. Control dependencies
|
|
|
+ do -not- apply to code following the if-statement containing the
|
|
|
+ control dependency.
|
|
|
+
|
|
|
(*) Control dependencies pair normally with other types of barriers.
|
|
|
|
|
|
(*) Control dependencies do -not- provide transitivity. If you
|