[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <tip-ebff09a6ff164aec2b33bf1f9a488c45ac108413@git.kernel.org>
Date: Fri, 17 Jun 2016 05:19:41 -0700
From: "tip-bot for Paul E. McKenney" <tipbot@...or.com>
To: linux-tip-commits@...r.kernel.org
Cc: paulmck@...ux.vnet.ibm.com, will.deacon@....com, mingo@...nel.org,
hpa@...or.com, linux-kernel@...r.kernel.org,
torvalds@...ux-foundation.org, tglx@...utronix.de,
peterz@...radead.org
Subject: [tip:locking/core] locking/Documentation: Clarify limited
control-dependency scope
Commit-ID: ebff09a6ff164aec2b33bf1f9a488c45ac108413
Gitweb: http://git.kernel.org/tip/ebff09a6ff164aec2b33bf1f9a488c45ac108413
Author: Paul E. McKenney <paulmck@...ux.vnet.ibm.com>
AuthorDate: Wed, 15 Jun 2016 16:08:17 -0700
Committer: Ingo Molnar <mingo@...nel.org>
CommitDate: Fri, 17 Jun 2016 09:54:45 +0200
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@....com>
Signed-off-by: Paul E. McKenney <paulmck@...ux.vnet.ibm.com>
Acked-by: Peter Zijlstra (Intel) <peterz@...radead.org>
Cc: Linus Torvalds <torvalds@...ux-foundation.org>
Cc: Peter Zijlstra <peterz@...radead.org>
Cc: Thomas Gleixner <tglx@...utronix.de>
Cc: corbet@....net
Cc: linux-arch@...r.kernel.org
Cc: linux-doc@...r.kernel.org
Link: http://lkml.kernel.org/r/20160615230817.GA18039@linux.vnet.ibm.com
Signed-off-by: Ingo Molnar <mingo@...nel.org>
---
Documentation/memory-barriers.txt | 41 +++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index 147ae8e..a4d0a99 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
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
Powered by blists - more mailing lists