diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2016-06-15 19:08:17 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-06-17 03:54:45 -0400 |
commit | ebff09a6ff164aec2b33bf1f9a488c45ac108413 (patch) | |
tree | 4c2e43caeacbd254daa8439564e991b1de82750c /Documentation/memory-barriers.txt | |
parent | b316ff783d17bd6217804e2e4385ce9347d7dad9 (diff) |
locking/Documentation: Clarify limited control-dependency scope
Nothing in the control-dependencies section of memory-barriers.txt
says that control dependencies don't extend beyond the end of the
if-statement containing the control dependency. Worse yet, in many
situations, they do extend beyond that if-statement. In particular,
the compiler cannot destroy the control dependency given proper use of
READ_ONCE() and WRITE_ONCE(). However, a weakly ordered system having
a conditional-move instruction provides the control-dependency guarantee
only to code within the scope of the if-statement itself.
This commit therefore adds words and an example demonstrating this
limitation of control dependencies.
Reported-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: corbet@lwn.net
Cc: linux-arch@vger.kernel.org
Cc: linux-doc@vger.kernel.org
Link: http://lkml.kernel.org/r/20160615230817.GA18039@linux.vnet.ibm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'Documentation/memory-barriers.txt')
-rw-r--r-- | Documentation/memory-barriers.txt | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index 147ae8ec836f..a4d0a99de04d 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt | |||
@@ -806,6 +806,41 @@ out-guess your code. More generally, although READ_ONCE() does force | |||
806 | the compiler to actually emit code for a given load, it does not force | 806 | the compiler to actually emit code for a given load, it does not force |
807 | the compiler to use the results. | 807 | the compiler to use the results. |
808 | 808 | ||
809 | In addition, control dependencies apply only to the then-clause and | ||
810 | else-clause of the if-statement in question. In particular, it does | ||
811 | not necessarily apply to code following the if-statement: | ||
812 | |||
813 | q = READ_ONCE(a); | ||
814 | if (q) { | ||
815 | WRITE_ONCE(b, p); | ||
816 | } else { | ||
817 | WRITE_ONCE(b, r); | ||
818 | } | ||
819 | WRITE_ONCE(c, 1); /* BUG: No ordering against the read from "a". */ | ||
820 | |||
821 | It is tempting to argue that there in fact is ordering because the | ||
822 | compiler cannot reorder volatile accesses and also cannot reorder | ||
823 | the writes to "b" with the condition. Unfortunately for this line | ||
824 | of reasoning, the compiler might compile the two writes to "b" as | ||
825 | conditional-move instructions, as in this fanciful pseudo-assembly | ||
826 | language: | ||
827 | |||
828 | ld r1,a | ||
829 | ld r2,p | ||
830 | ld r3,r | ||
831 | cmp r1,$0 | ||
832 | cmov,ne r4,r2 | ||
833 | cmov,eq r4,r3 | ||
834 | st r4,b | ||
835 | st $1,c | ||
836 | |||
837 | A weakly ordered CPU would have no dependency of any sort between the load | ||
838 | from "a" and the store to "c". The control dependencies would extend | ||
839 | only to the pair of cmov instructions and the store depending on them. | ||
840 | In short, control dependencies apply only to the stores in the then-clause | ||
841 | and else-clause of the if-statement in question (including functions | ||
842 | invoked by those two clauses), not to code following that if-statement. | ||
843 | |||
809 | Finally, control dependencies do -not- provide transitivity. This is | 844 | Finally, control dependencies do -not- provide transitivity. This is |
810 | demonstrated by two related examples, with the initial values of | 845 | demonstrated by two related examples, with the initial values of |
811 | x and y both being zero: | 846 | x and y both being zero: |
@@ -869,6 +904,12 @@ In summary: | |||
869 | atomic{,64}_read() can help to preserve your control dependency. | 904 | atomic{,64}_read() can help to preserve your control dependency. |
870 | Please see the COMPILER BARRIER section for more information. | 905 | Please see the COMPILER BARRIER section for more information. |
871 | 906 | ||
907 | (*) Control dependencies apply only to the then-clause and else-clause | ||
908 | of the if-statement containing the control dependency, including | ||
909 | any functions that these two clauses call. Control dependencies | ||
910 | do -not- apply to code following the if-statement containing the | ||
911 | control dependency. | ||
912 | |||
872 | (*) Control dependencies pair normally with other types of barriers. | 913 | (*) Control dependencies pair normally with other types of barriers. |
873 | 914 | ||
874 | (*) Control dependencies do -not- provide transitivity. If you | 915 | (*) Control dependencies do -not- provide transitivity. If you |