Skip to content

Commit

Permalink
documentation: Clarify control-dependency pairing
Browse files Browse the repository at this point in the history
This commit explicitly states that control dependencies pair normally
with other barriers, and gives an example of such pairing.

Reported-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
  • Loading branch information
Paul E. McKenney committed Feb 26, 2015
1 parent daf1aab commit ff38281
Showing 1 changed file with 29 additions and 13 deletions.
42 changes: 29 additions & 13 deletions Documentation/memory-barriers.txt
Original file line number Diff line number Diff line change
Expand Up @@ -592,9 +592,9 @@ See also the subsection on "Cache Coherency" for a more thorough example.
CONTROL DEPENDENCIES
--------------------

A control dependency requires a full read memory barrier, not simply a data
dependency barrier to make it work correctly. Consider the following bit of
code:
A load-load control dependency requires a full read memory barrier, not
simply a data dependency barrier to make it work correctly. Consider the
following bit of code:

q = ACCESS_ONCE(a);
if (q) {
Expand All @@ -615,14 +615,15 @@ case what's actually required is:
}

However, stores are not speculated. This means that ordering -is- provided
in the following example:
for load-store control dependencies, as in the following example:

q = ACCESS_ONCE(a);
if (q) {
ACCESS_ONCE(b) = p;
}

Please note that ACCESS_ONCE() is not optional! Without the
Control dependencies pair normally with other types of barriers.
That said, please note that ACCESS_ONCE() is not optional! Without the
ACCESS_ONCE(), might combine the load from 'a' with other loads from
'a', and the store to 'b' with other stores to 'b', with possible highly
counterintuitive effects on ordering.
Expand Down Expand Up @@ -813,6 +814,8 @@ In summary:
barrier() can help to preserve your control dependency. Please
see the Compiler Barrier section for more information.

(*) Control dependencies pair normally with other types of barriers.

(*) Control dependencies do -not- provide transitivity. If you
need transitivity, use smp_mb().

Expand All @@ -823,14 +826,14 @@ SMP BARRIER PAIRING
When dealing with CPU-CPU interactions, certain types of memory barrier should
always be paired. A lack of appropriate pairing is almost certainly an error.

General barriers pair with each other, though they also pair with
most other types of barriers, albeit without transitivity. An acquire
barrier pairs with a release barrier, but both may also pair with other
barriers, including of course general barriers. A write barrier pairs
with a data dependency barrier, an acquire barrier, a release barrier,
a read barrier, or a general barrier. Similarly a read barrier or a
data dependency barrier pairs with a write barrier, an acquire barrier,
a release barrier, or a general barrier:
General barriers pair with each other, though they also pair with most
other types of barriers, albeit without transitivity. An acquire barrier
pairs with a release barrier, but both may also pair with other barriers,
including of course general barriers. A write barrier pairs with a data
dependency barrier, a control dependency, an acquire barrier, a release
barrier, a read barrier, or a general barrier. Similarly a read barrier,
control dependency, or a data dependency barrier pairs with a write
barrier, an acquire barrier, a release barrier, or a general barrier:

CPU 1 CPU 2
=============== ===============
Expand All @@ -850,6 +853,19 @@ Or:
<data dependency barrier>
y = *x;

Or even:

CPU 1 CPU 2
=============== ===============================
r1 = ACCESS_ONCE(y);
<general barrier>
ACCESS_ONCE(y) = 1; if (r2 = ACCESS_ONCE(x)) {
<implicit control dependency>
ACCESS_ONCE(y) = 1;
}

assert(r1 == 0 || r2 == 0);

Basically, the read barrier always has to be there, even though it can be of
the "weaker" type.

Expand Down

0 comments on commit ff38281

Please sign in to comment.