[tip:core/locking] Documentation/memory-barriers.txt: Document ACCESS_ONCE()
Commit-ID: 692118dac47e65f5131686b1103ebfebf0cbfa8e Gitweb: http://git.kernel.org/tip/692118dac47e65f5131686b1103ebfebf0cbfa8e Author: Paul E. McKenney AuthorDate: Wed, 11 Dec 2013 13:59:07 -0800 Committer: Ingo Molnar CommitDate: Mon, 16 Dec 2013 11:36:12 +0100 Documentation/memory-barriers.txt: Document ACCESS_ONCE() The situations in which ACCESS_ONCE() is required are not well documented, so this commit adds some verbiage to memory-barriers.txt. Reported-by: Peter Zijlstra Signed-off-by: Paul E. McKenney Reviewed-by: Josh Triplett Reviewed-by: Peter Zijlstra Cc: Cc: Linus Torvalds Cc: Andrew Morton Link: http://lkml.kernel.org/r/1386799151-2219-4-git-send-email-paul...@linux.vnet.ibm.com Signed-off-by: Ingo Molnar --- Documentation/memory-barriers.txt | 306 +- 1 file changed, 271 insertions(+), 35 deletions(-) diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index deafa36..919fd60 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -231,37 +231,8 @@ And there are a number of things that _must_ or _must_not_ be assumed: (*) It _must_not_ be assumed that the compiler will do what you want with memory references that are not protected by ACCESS_ONCE(). Without ACCESS_ONCE(), the compiler is within its rights to do all sorts - of "creative" transformations: - - (-) Repeat the load, possibly getting a different value on the second - and subsequent loads. This is especially prone to happen when -register pressure is high. - - (-) Merge adjacent loads and stores to the same location. The most - familiar example is the transformation from: - - while (a) - do_something(); - - to something like: - - if (a) - for (;;) - do_something(); - - Using ACCESS_ONCE() as follows prevents this sort of optimization: - - while (ACCESS_ONCE(a)) - do_something(); - - (-) "Store tearing", where a single store in the source code is split - into smaller stores in the object code. Note that gcc really -will do this on some architectures when storing certain constants. -It can be cheaper to do a series of immediate stores than to -form the constant in a register and then to store that register. - - (-) "Load tearing", which splits loads in a manner analogous to -store tearing. + of "creative" transformations, which are covered in the Compiler + Barrier section. (*) It _must_not_ be assumed that independent loads and stores will be issued in the order given. This means that for: @@ -749,7 +720,8 @@ In summary: (*) Control dependencies require that the compiler avoid reordering the dependency into nonexistence. Careful use of ACCESS_ONCE() or - barrier() can help to preserve your control dependency. + barrier() can help to preserve your control dependency. Please + see the Compiler Barrier section for more information. (*) Control dependencies do -not- provide transitivity. If you need transitivity, use smp_mb(). @@ -1248,12 +1220,276 @@ compiler from moving the memory accesses either side of it to the other side: barrier(); This is a general barrier -- there are no read-read or write-write variants -of barrier(). Howevever, ACCESS_ONCE() can be thought of as a weak form +of barrier(). However, ACCESS_ONCE() can be thought of as a weak form for barrier() that affects only the specific accesses flagged by the ACCESS_ONCE(). -The compiler barrier has no direct effect on the CPU, which may then reorder -things however it wishes. +The barrier() function has the following effects: + + (*) Prevents the compiler from reordering accesses following the + barrier() to precede any accesses preceding the barrier(). + One example use for this property is to ease communication between + interrupt-handler code and the code that was interrupted. + + (*) Within a loop, forces the compiler to load the variables used + in that loop's conditional on each pass through that loop. + +The ACCESS_ONCE() function can prevent any number of optimizations that, +while perfectly safe in single-threaded code, can be fatal in concurrent +code. Here are some examples of these sorts of optimizations: + + (*) The compiler is within its rights to merge successive loads from + the same variable. Such merging can cause the compiler to "optimize" + the following code: + + while (tmp = a) + do_something_with(tmp); + + into the following code, which, although in some sense legitimate + for single-threaded code, is almost certainly not what the developer + intended: + + if (tmp = a) + for (;;) +
[tip:core/locking] Documentation/memory-barriers.txt: Document ACCESS_ONCE()
Commit-ID: 692118dac47e65f5131686b1103ebfebf0cbfa8e Gitweb: http://git.kernel.org/tip/692118dac47e65f5131686b1103ebfebf0cbfa8e Author: Paul E. McKenney paul...@linux.vnet.ibm.com AuthorDate: Wed, 11 Dec 2013 13:59:07 -0800 Committer: Ingo Molnar mi...@kernel.org CommitDate: Mon, 16 Dec 2013 11:36:12 +0100 Documentation/memory-barriers.txt: Document ACCESS_ONCE() The situations in which ACCESS_ONCE() is required are not well documented, so this commit adds some verbiage to memory-barriers.txt. Reported-by: Peter Zijlstra pet...@infradead.org Signed-off-by: Paul E. McKenney paul...@linux.vnet.ibm.com Reviewed-by: Josh Triplett j...@joshtriplett.org Reviewed-by: Peter Zijlstra a.p.zijls...@chello.nl Cc: linux-a...@vger.kernel.org Cc: Linus Torvalds torva...@linux-foundation.org Cc: Andrew Morton a...@linux-foundation.org Link: http://lkml.kernel.org/r/1386799151-2219-4-git-send-email-paul...@linux.vnet.ibm.com Signed-off-by: Ingo Molnar mi...@kernel.org --- Documentation/memory-barriers.txt | 306 +- 1 file changed, 271 insertions(+), 35 deletions(-) diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index deafa36..919fd60 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -231,37 +231,8 @@ And there are a number of things that _must_ or _must_not_ be assumed: (*) It _must_not_ be assumed that the compiler will do what you want with memory references that are not protected by ACCESS_ONCE(). Without ACCESS_ONCE(), the compiler is within its rights to do all sorts - of creative transformations: - - (-) Repeat the load, possibly getting a different value on the second - and subsequent loads. This is especially prone to happen when -register pressure is high. - - (-) Merge adjacent loads and stores to the same location. The most - familiar example is the transformation from: - - while (a) - do_something(); - - to something like: - - if (a) - for (;;) - do_something(); - - Using ACCESS_ONCE() as follows prevents this sort of optimization: - - while (ACCESS_ONCE(a)) - do_something(); - - (-) Store tearing, where a single store in the source code is split - into smaller stores in the object code. Note that gcc really -will do this on some architectures when storing certain constants. -It can be cheaper to do a series of immediate stores than to -form the constant in a register and then to store that register. - - (-) Load tearing, which splits loads in a manner analogous to -store tearing. + of creative transformations, which are covered in the Compiler + Barrier section. (*) It _must_not_ be assumed that independent loads and stores will be issued in the order given. This means that for: @@ -749,7 +720,8 @@ In summary: (*) Control dependencies require that the compiler avoid reordering the dependency into nonexistence. Careful use of ACCESS_ONCE() or - barrier() can help to preserve your control dependency. + barrier() can help to preserve your control dependency. Please + see the Compiler Barrier section for more information. (*) Control dependencies do -not- provide transitivity. If you need transitivity, use smp_mb(). @@ -1248,12 +1220,276 @@ compiler from moving the memory accesses either side of it to the other side: barrier(); This is a general barrier -- there are no read-read or write-write variants -of barrier(). Howevever, ACCESS_ONCE() can be thought of as a weak form +of barrier(). However, ACCESS_ONCE() can be thought of as a weak form for barrier() that affects only the specific accesses flagged by the ACCESS_ONCE(). -The compiler barrier has no direct effect on the CPU, which may then reorder -things however it wishes. +The barrier() function has the following effects: + + (*) Prevents the compiler from reordering accesses following the + barrier() to precede any accesses preceding the barrier(). + One example use for this property is to ease communication between + interrupt-handler code and the code that was interrupted. + + (*) Within a loop, forces the compiler to load the variables used + in that loop's conditional on each pass through that loop. + +The ACCESS_ONCE() function can prevent any number of optimizations that, +while perfectly safe in single-threaded code, can be fatal in concurrent +code. Here are some examples of these sorts of optimizations: + + (*) The compiler is within its rights to merge successive loads from + the same variable. Such merging can cause the compiler to optimize + the following code: + + while (tmp = a) + do_something_with(tmp); + + into the following code,