doc: Update memory-barriers.txt for read-to-write dependencies
The memory-barriers.txt document contains an obsolete passage stating that smp_read_barrier_depends() is required to force ordering for read-to-write dependencies. We now know that this is not required, even for DEC Alpha. This commit therefore updates this passage to state that read-to-write dependencies are respected even without smp_read_barrier_depends(). Reported-by: Lance Roy <ldr709@gmail.com> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: David Howells <dhowells@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Alan Stern <stern@rowland.harvard.edu> Cc: Andrea Parri <parri.andrea@gmail.com> Cc: Jade Alglave <j.alglave@ucl.ac.uk> Cc: Luc Maranget <luc.maranget@inria.fr> [ paulmck: Reference control-dependencies sections and use WRITE_ONCE() per Will Deacon. Correctly place split-cache paragraph while there. ] Acked-by: Will Deacon <will.deacon@arm.com>
This commit is contained in:
parent
4de5f89ef8
commit
66ce3a4dcb
1 changed files with 30 additions and 23 deletions
|
@ -594,29 +594,6 @@ between the address load and the data load:
|
||||||
This enforces the occurrence of one of the two implications, and prevents the
|
This enforces the occurrence of one of the two implications, and prevents the
|
||||||
third possibility from arising.
|
third possibility from arising.
|
||||||
|
|
||||||
A data-dependency barrier must also order against dependent writes:
|
|
||||||
|
|
||||||
CPU 1 CPU 2
|
|
||||||
=============== ===============
|
|
||||||
{ A == 1, B == 2, C = 3, P == &A, Q == &C }
|
|
||||||
B = 4;
|
|
||||||
<write barrier>
|
|
||||||
WRITE_ONCE(P, &B);
|
|
||||||
Q = READ_ONCE(P);
|
|
||||||
<data dependency barrier>
|
|
||||||
*Q = 5;
|
|
||||||
|
|
||||||
The data-dependency barrier must order the read into Q with the store
|
|
||||||
into *Q. This prohibits this outcome:
|
|
||||||
|
|
||||||
(Q == &B) && (B == 4)
|
|
||||||
|
|
||||||
Please note that this pattern should be rare. After all, the whole point
|
|
||||||
of dependency ordering is to -prevent- writes to the data structure, along
|
|
||||||
with the expensive cache misses associated with those writes. This pattern
|
|
||||||
can be used to record rare error conditions and the like, and the ordering
|
|
||||||
prevents such records from being lost.
|
|
||||||
|
|
||||||
|
|
||||||
[!] Note that this extremely counterintuitive situation arises most easily on
|
[!] Note that this extremely counterintuitive situation arises most easily on
|
||||||
machines with split caches, so that, for example, one cache bank processes
|
machines with split caches, so that, for example, one cache bank processes
|
||||||
|
@ -628,6 +605,36 @@ odd-numbered bank is idle, one can see the new value of the pointer P (&B),
|
||||||
but the old value of the variable B (2).
|
but the old value of the variable B (2).
|
||||||
|
|
||||||
|
|
||||||
|
A data-dependency barrier is not required to order dependent writes
|
||||||
|
because the CPUs that the Linux kernel supports don't do writes
|
||||||
|
until they are certain (1) that the write will actually happen, (2)
|
||||||
|
of the location of the write, and (3) of the value to be written.
|
||||||
|
But please carefully read the "CONTROL DEPENDENCIES" section and the
|
||||||
|
Documentation/RCU/rcu_dereference.txt file: The compiler can and does
|
||||||
|
break dependencies in a great many highly creative ways.
|
||||||
|
|
||||||
|
CPU 1 CPU 2
|
||||||
|
=============== ===============
|
||||||
|
{ A == 1, B == 2, C = 3, P == &A, Q == &C }
|
||||||
|
B = 4;
|
||||||
|
<write barrier>
|
||||||
|
WRITE_ONCE(P, &B);
|
||||||
|
Q = READ_ONCE(P);
|
||||||
|
WRITE_ONCE(*Q, 5);
|
||||||
|
|
||||||
|
Therefore, no data-dependency barrier is required to order the read into
|
||||||
|
Q with the store into *Q. In other words, this outcome is prohibited,
|
||||||
|
even without a data-dependency barrier:
|
||||||
|
|
||||||
|
(Q == &B) && (B == 4)
|
||||||
|
|
||||||
|
Please note that this pattern should be rare. After all, the whole point
|
||||||
|
of dependency ordering is to -prevent- writes to the data structure, along
|
||||||
|
with the expensive cache misses associated with those writes. This pattern
|
||||||
|
can be used to record rare error conditions and the like, and the CPUs'
|
||||||
|
naturally occurring ordering prevents such records from being lost.
|
||||||
|
|
||||||
|
|
||||||
The data dependency barrier is very important to the RCU system,
|
The data dependency barrier is very important to the RCU system,
|
||||||
for example. See rcu_assign_pointer() and rcu_dereference() in
|
for example. See rcu_assign_pointer() and rcu_dereference() in
|
||||||
include/linux/rcupdate.h. This permits the current target of an RCU'd
|
include/linux/rcupdate.h. This permits the current target of an RCU'd
|
||||||
|
|
Loading…
Add table
Reference in a new issue