Documentation updates for v4.15
Subsystems (3)
cover Documentation updates for v4.15
Hello!
This series contains documentation updates, including some updates to docbook header comments:
1. Design documentation illustrating RCU's grace-period memory
ordering guarantees.
2. Add verbiage stating that long-running irq handlers can stall
RCU grace periods.
3. Add verbiage stating that slow systems can stall RCU grace periods.
4. Update description of RCU CPU stall warning messages.
5. Replace uses of "transitive" in memory-barriers.txt.
6. Rework multicopy-atomicity section of memory-barriers.txt,
courtesy of Alan Stern.
7. Fix RCU's docbook options.
8. Add parameters to rcupdate.h docbook comments.
9. Remove extra docbook comment in rculist.h.
10. Fix docbook comments for rcu_sync functions.
11. Fix list and emphasis in rcupdate.h docbook comments.
12. Flag code segment in rcu_pointer_handoff()'s docbook comment.
13. Fix code display in rcu_pointer_handoff()'s docbook comment.
14. Fix tree.c bulleted lists in docbook comments.
15. Fix typo in pairing example in memory-barriers.txt, courtesy
of Scott Tsai.
16. Rewrite confusing statement about memory barriers in
memory-barriers.txt, courtesy of Guilherme G. Piccoli.
Thanx, Paul
------------------------------------------------------------------------
Documentation/RCU/Design/Memory-Ordering/Tree-RCU-Diagram.html | 9 Documentation/RCU/Design/Memory-Ordering/Tree-RCU-Memory-Ordering.html | 707 + Documentation/RCU/Design/Memory-Ordering/TreeRCU-callback-invocation.svg | 486 Documentation/RCU/Design/Memory-Ordering/TreeRCU-callback-registry.svg | 655 + Documentation/RCU/Design/Memory-Ordering/TreeRCU-dyntick.svg | 700 + Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-cleanup.svg | 1126 ++ Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-fqs.svg | 1309 ++ Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-init-1.svg | 656 + Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-init-2.svg | 656 + Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-init-3.svg | 632 + Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp.svg | 5135 ++++++++++ Documentation/RCU/Design/Memory-Ordering/TreeRCU-hotplug.svg | 775 + Documentation/RCU/Design/Memory-Ordering/TreeRCU-qs.svg | 1095 ++ Documentation/RCU/Design/Memory-Ordering/rcu_node-lock.svg | 229 Documentation/RCU/stallwarn.txt | 200 Documentation/core-api/kernel-api.rst | 14 Documentation/memory-barriers.txt | 249 include/linux/rculist.h | 2 include/linux/rcupdate.h | 26 kernel/rcu/sync.c | 9 kernel/rcu/tree.c | 18 21 files changed, 14449 insertions(+), 239 deletions(-)
PATCH 1/16 documentation: RCU grace-period memory ordering guarantees
This commit provides text and diagrams showing how Tree RCU implements its grace-period memory ordering guarantees.
--- .../Design/Memory-Ordering/Tree-RCU-Diagram.html | 9 + .../Memory-Ordering/Tree-RCU-Memory-Ordering.html | 707 +++ .../TreeRCU-callback-invocation.svg | 486 ++ .../Memory-Ordering/TreeRCU-callback-registry.svg | 655 +++ .../RCU/Design/Memory-Ordering/TreeRCU-dyntick.svg | 700 +++ .../Design/Memory-Ordering/TreeRCU-gp-cleanup.svg | 1126 +++++ .../RCU/Design/Memory-Ordering/TreeRCU-gp-fqs.svg | 1309 +++++ .../Design/Memory-Ordering/TreeRCU-gp-init-1.svg | 656 +++ .../Design/Memory-Ordering/TreeRCU-gp-init-2.svg | 656 +++ .../Design/Memory-Ordering/TreeRCU-gp-init-3.svg | 632 +++ .../RCU/Design/Memory-Ordering/TreeRCU-gp.svg | 5135 ++++++++++++++++++++ .../RCU/Design/Memory-Ordering/TreeRCU-hotplug.svg | 775 +++ .../RCU/Design/Memory-Ordering/TreeRCU-qs.svg | 1095 +++++ .../RCU/Design/Memory-Ordering/rcu_node-lock.svg | 229 + 14 files changed, 14170 insertions(+) create mode 100644 Documentation/RCU/Design/Memory-Ordering/Tree-RCU-Diagram.html create mode 100644 Documentation/RCU/Design/Memory-Ordering/Tree-RCU-Memory-Ordering.html create mode 100644 Documentation/RCU/Design/Memory-Ordering/TreeRCU-callback-invocation.svg create mode 100644 Documentation/RCU/Design/Memory-Ordering/TreeRCU-callback-registry.svg create mode 100644 Documentation/RCU/Design/Memory-Ordering/TreeRCU-dyntick.svg create mode 100644 Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-cleanup.svg create mode 100644 Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-fqs.svg create mode 100644 Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-init-1.svg create mode 100644 Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-init-2.svg create mode 100644 Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-init-3.svg create mode 100644 Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp.svg create mode 100644 Documentation/RCU/Design/Memory-Ordering/TreeRCU-hotplug.svg create mode 100644 Documentation/RCU/Design/Memory-Ordering/TreeRCU-qs.svg create mode 100644 Documentation/RCU/Design/Memory-Ordering/rcu_node-lock.svg
Documentation/RCU/Design/Memory-Ordering/Tree-RCU-Diagram.html new file +9 -0
@@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html4/loose.dtd"> + <html> + <head><title>A Diagram of TREE_RCU's Grace-Period Memory Ordering</title> + <meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> + +<p><img src="TreeRCU-gp.svg" alt="TreeRCU-gp.svg"> + +</body></html>
Documentation/RCU/Design/Memory-Ordering/Tree-RCU-Memory-Ordering.html new file +707 -0
707 lines not on this page · raw message
Documentation/RCU/Design/Memory-Ordering/TreeRCU-callback-invocation.svg new file +486 -0
486 lines not on this page · raw message
Documentation/RCU/Design/Memory-Ordering/TreeRCU-callback-registry.svg new file +655 -0
655 lines not on this page · raw message
Documentation/RCU/Design/Memory-Ordering/TreeRCU-dyntick.svg new file +700 -0
700 lines not on this page · raw message
Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-cleanup.svg new file +1126 -0
443 lines not on this page · raw message
Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-fqs.svg new file +1309 -0
1,309 lines not on this page · raw message
Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-init-1.svg new file +656 -0
656 lines not on this page · raw message
Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-init-2.svg new file +656 -0
656 lines not on this page · raw message
Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp-init-3.svg new file +632 -0
632 lines not on this page · raw message
Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp.svg new file +5135 -0
5,135 lines not on this page · raw message
Documentation/RCU/Design/Memory-Ordering/TreeRCU-hotplug.svg new file +775 -0
775 lines not on this page · raw message
Documentation/RCU/Design/Memory-Ordering/TreeRCU-qs.svg new file +1095 -0
1,095 lines not on this page · raw message
Documentation/RCU/Design/Memory-Ordering/rcu_node-lock.svg new file +229 -0
229 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Signature · 1 line
2.5.2
Part of the diff is not shown here. View the raw message.
PATCH 2/16 documentation: Long-running irq handlers can stall RCU grace periods
In reply to Paul E. McKenneyIf a periodic interrupt's handler takes longer to execute than the period between successive interrupts, RCU's kthreads and softirq handlers can be prevented from executing, resulting in otherwise inexplicable RCU CPU stall warnings. This commit therefore calls out this possibility in Documentation/RCU/stallwarn.txt.
--- Documentation/RCU/stallwarn.txt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
Documentation/RCU/stallwarn.txt +11 -1
@@ -40,7 +40,9 @@ o Booting Linux using a console connection that is too slow to o Anything that prevents RCU's grace-period kthreads from running. This can result in the "All QSes seen" console-log message. This message will include information on when the kthread last - ran and how often it should be expected to run. + ran and how often it should be expected to run. It can also + result in the "rcu_.*kthread starved for" console-log message, + which will include additional debugging information. o A CPU-bound real-time task in a CONFIG_PREEMPT kernel, which might happen to preempt a low-priority task in the middle of an RCU
@@ -60,6 +62,14 @@ o A CPU-bound real-time task in a CONFIG_PREEMPT_RT kernel that CONFIG_PREEMPT_RCU case, you might see stall-warning messages. +o A periodic interrupt whose handler takes longer than the time + interval between successive pairs of interrupts. This can + prevent RCU's kthreads and softirq handlers from running. + Note that certain high-overhead debugging options, for example + the function_graph tracer, can result in interrupt handler taking + considerably longer than normal, which can in turn result in + RCU CPU stall warnings. + o A hardware or software issue shuts off the scheduler-clock interrupt on a CPU that is not in dyntick-idle mode. This problem really has happened, and seems to be most likely to
Signature · 1 line
2.5.2
PATCH 3/16 documentation: Slow systems can stall RCU grace periods
In reply to Paul E. McKenneyIf a fast system has a worst-case grace-period duration of (say) ten seconds, then running the same workload on a system ten times as slow will get you an RCU CPU stall warning given default stall-warning timeout settings. This commit therefore adds this possibility to stallwarn.txt.
--- Documentation/RCU/stallwarn.txt | 6 ++++++ 1 file changed, 6 insertions(+)
Documentation/RCU/stallwarn.txt +6 -0
@@ -70,6 +70,12 @@ o A periodic interrupt whose handler takes longer than the time considerably longer than normal, which can in turn result in RCU CPU stall warnings. +o Testing a workload on a fast system, tuning the stall-warning + timeout down to just barely avoid RCU CPU stall warnings, and then + running the same workload with the same stall-warning timeout on a + slow system. Note that thermal throttling and on-demand governors + can cause a single system to be sometimes fast and sometimes slow! + o A hardware or software issue shuts off the scheduler-clock interrupt on a CPU that is not in dyntick-idle mode. This problem really has happened, and seems to be most likely to
Signature · 1 line
2.5.2
PATCH 4/16 documentation: Update RCU CPU stall warning messages
In reply to Paul E. McKenneyThe RCU CPU stall warnings have morphed significantly since the last update, so this commit brings the documentation up to date.
--- Documentation/RCU/stallwarn.txt | 182 +++++++++++++++++++++++----------------- 1 file changed, 105 insertions(+), 77 deletions(-)
Documentation/RCU/stallwarn.txt +105 -77
@@ -171,67 +171,32 @@ Interpreting RCU's CPU Stall-Detector "Splats" For non-RCU-tasks flavors of RCU, when a CPU detects that it is stalling, it will print a message similar to the following: -INFO: rcu_sched_state detected stall on CPU 5 (t=2500 jiffies) + INFO: rcu_sched detected stalls on CPUs/tasks: + 2-...: (3 GPs behind) idle=06c/0/0 softirq=1453/1455 fqs=0 + 16-...: (0 ticks this GP) idle=81c/0/0 softirq=764/764 fqs=0 + (detected by 32, t=2603 jiffies, g=7073, c=7072, q=625) -This message indicates that CPU 5 detected that it was causing a stall, -and that the stall was affecting RCU-sched. This message will normally be -followed by a stack dump of the offending CPU. On TREE_RCU kernel builds, -RCU and RCU-sched are implemented by the same underlying mechanism, -while on PREEMPT_RCU kernel builds, RCU is instead implemented -by rcu_preempt_state. - -On the other hand, if the offending CPU fails to print out a stall-warning -message quickly enough, some other CPU will print a message similar to -the following: - -INFO: rcu_bh_state detected stalls on CPUs/tasks: { 3 5 } (detected by 2, 2502 jiffies) - -This message indicates that CPU 2 detected that CPUs 3 and 5 were both -causing stalls, and that the stall was affecting RCU-bh. This message +This message indicates that CPU 32 detected that CPUs 2 and 16 were both +causing stalls, and that the stall was affecting RCU-sched. This message will normally be followed by stack dumps for each CPU. Please note that -PREEMPT_RCU builds can be stalled by tasks as well as by CPUs, -and that the tasks will be indicated by PID, for example, "P3421". -It is even possible for a rcu_preempt_state stall to be caused by both -CPUs -and- tasks, in which case the offending CPUs and tasks will all -be called out in the list. - -Finally, if the grace period ends just as the stall warning starts -printing, there will be a spurious stall-warning message: - -INFO: rcu_bh_state detected stalls on CPUs/tasks: { } (detected by 4, 2502 jiffies) - -This is rare, but does happen from time to time in real life. It is also -possible for a zero-jiffy stall to be flagged in this case, depending -on how the stall warning and the grace-period initialization happen to -interact. Please note that it is not possible to entirely eliminate this -sort of false positive without resorting to things like stop_machine(), -which is overkill for this sort of problem. - -Recent kernels will print a long form of the stall-warning message: - - INFO: rcu_preempt detected stall on CPU - 0: (63959 ticks this GP) idle=241/3fffffffffffffff/0 softirq=82/543 - (t=65000 jiffies) - -In kernels with CONFIG_RCU_FAST_NO_HZ, more information is printed: - - INFO: rcu_preempt detected stall on CPU - 0: (64628 ticks this GP) idle=dd5/3fffffffffffffff/0 softirq=82/543 last_accelerate: a345/d342 nonlazy_posted: 25 .D - (t=65000 jiffies) +PREEMPT_RCU builds can be stalled by tasks as well as by CPUs, and that +the tasks will be indicated by PID, for example, "P3421". It is even +possible for a rcu_preempt_state stall to be caused by both CPUs -and- +tasks, in which case the offending CPUs and tasks will all be called +out in the list. -The "(64628 ticks this GP)" indicates that this CPU has taken more -than 64,000 scheduling-clock interrupts during the current stalled -grace period. If the CPU was not yet aware of the current grace -period (for example, if it was offline), then this part of the message -indicates how many grace periods behind the CPU is. +CPU 2's "(3 GPs behind)" indicates that this CPU has not interacted with +the RCU core for the past three grace periods. In contrast, CPU 16's "(0 +ticks this GP)" indicates that this CPU has not taken any scheduling-clock +interrupts during the current stalled grace period. The "idle=" portion of the message prints the dyntick-idle state. The hex number before the first "/" is the low-order 12 bits of the -dynticks counter, which will have an even-numbered value if the CPU is -in dyntick-idle mode and an odd-numbered value otherwise. The hex -number between the two "/"s is the value of the nesting, which will -be a small positive number if in the idle loop and a very large positive -number (as shown above) otherwise. +dynticks counter, which will have an even-numbered value if the CPU +is in dyntick-idle mode and an odd-numbered value otherwise. The hex +number between the two "/"s is the value of the nesting, which will be +a small non-negative number if in the idle loop (as shown above) and a +very large positive number otherwise. The "softirq=" portion of the message tracks the number of RCU softirq handlers that the stalled CPU has executed. The number before the "/"
@@ -246,24 +211,72 @@ handlers are no longer able to execute on this CPU. This can happen if the stalled CPU is spinning with interrupts are disabled, or, in -rt kernels, if a high-priority process is starving RCU's softirq handler. -For CONFIG_RCU_FAST_NO_HZ kernels, the "last_accelerate:" prints the -low-order 16 bits (in hex) of the jiffies counter when this CPU last -invoked rcu_try_advance_all_cbs() from rcu_needs_cpu() or last invoked -rcu_accelerate_cbs() from rcu_prepare_for_idle(). The "nonlazy_posted:" -prints the number of non-lazy callbacks posted since the last call to -rcu_needs_cpu(). Finally, an "L" indicates that there are currently -no non-lazy callbacks ("." is printed otherwise, as shown above) and -"D" indicates that dyntick-idle processing is enabled ("." is printed -otherwise, for example, if disabled via the "nohz=" kernel boot parameter). +The "fps=" shows the number of force-quiescent-state idle/offline +detection passes that the grace-period kthread has made across this +CPU since the last time that this CPU noted the beginning of a grace +period. + +The "detected by" line indicates which CPU detected the stall (in this +case, CPU 32), how many jiffies have elapsed since the start of the +grace period (in this case 2603), the number of the last grace period +to start and to complete (7073 and 7072, respectively), and an estimate +of the total number of RCU callbacks queued across all CPUs (625 in +this case). + +In kernels with CONFIG_RCU_FAST_NO_HZ, more information is printed +for each CPU: + + 0: (64628 ticks this GP) idle=dd5/3fffffffffffffff/0 softirq=82/543 last_accelerate: a345/d342 nonlazy_posted: 25 .D + +The "last_accelerate:" prints the low-order 16 bits (in hex) of the +jiffies counter when this CPU last invoked rcu_try_advance_all_cbs() +from rcu_needs_cpu() or last invoked rcu_accelerate_cbs() from +rcu_prepare_for_idle(). The "nonlazy_posted:" prints the number +of non-lazy callbacks posted since the last call to rcu_needs_cpu(). +Finally, an "L" indicates that there are currently no non-lazy callbacks +("." is printed otherwise, as shown above) and "D" indicates that +dyntick-idle processing is enabled ("." is printed otherwise, for example, +if disabled via the "nohz=" kernel boot parameter). + +If the grace period ends just as the stall warning starts printing, +there will be a spurious stall-warning message, which will include +the following: + + INFO: Stall ended before state dump start + +This is rare, but does happen from time to time in real life. It is also +possible for a zero-jiffy stall to be flagged in this case, depending +on how the stall warning and the grace-period initialization happen to +interact. Please note that it is not possible to entirely eliminate this +sort of false positive without resorting to things like stop_machine(), +which is overkill for this sort of problem. + +If all CPUs and tasks have passed through quiescent states, but the +grace period has nevertheless failed to end, the stall-warning splat +will include something like the following: + + All QSes seen, last rcu_preempt kthread activity 23807 (4297905177-4297881370), jiffies_till_next_fqs=3, root ->qsmask 0x0 + +The "23807" indicates that it has been more than 23 thousand jiffies +since the grace-period kthread ran. The "jiffies_till_next_fqs" +indicates how frequently that kthread should run, giving the number +of jiffies between force-quiescent-state scans, in this case three, +which is way less than 23807. Finally, the root rcu_node structure's +->qsmask field is printed, which will normally be zero. If the relevant grace-period kthread has been unable to run prior to -the stall warning, the following additional line is printed: +the stall warning, as was the case in the "All QSes seen" line above, +the following additional line is printed: - rcu_preempt kthread starved for 2023 jiffies! + kthread starved for 23807 jiffies! g7073 c7072 f0x0 RCU_GP_WAIT_FQS(3) ->state=0x1 -Starving the grace-period kthreads of CPU time can of course result in -RCU CPU stall warnings even when all CPUs and tasks have passed through -the required quiescent states. +Starving the grace-period kthreads of CPU time can of course result +in RCU CPU stall warnings even when all CPUs and tasks have passed +through the required quiescent states. The "g" and "c" numbers flag the +number of the last grace period started and completed, respectively, +the "f" precedes the ->gp_flags command to the grace-period kthread, +the "RCU_GP_WAIT_FQS" indicates that the kthread is waiting for a short +timeout, and the "state" precedes value of the task_struct ->state field. Multiple Warnings From One Stall
@@ -280,13 +293,28 @@ Stall Warnings for Expedited Grace Periods If an expedited grace period detects a stall, it will place a message like the following in dmesg: - INFO: rcu_sched detected expedited stalls on CPUs: { 1 2 6 } 26009 jiffies s: 1043 - -This indicates that CPUs 1, 2, and 6 have failed to respond to a -reschedule IPI, that the expedited grace period has been going on for -26,009 jiffies, and that the expedited grace-period sequence counter is -1043. The fact that this last value is odd indicates that an expedited -grace period is in flight. + INFO: rcu_sched detected expedited stalls on CPUs/tasks: { 7-... } 21119 jiffies s: 73 root: 0x2/. + +This indicates that CPU 7 has failed to respond to a reschedule IPI. +The three periods (".") following the CPU number indicate that the CPU +is online (otherwise the first period would instead have been "O"), +that the CPU was online at the beginning of the expedited grace period +(otherwise the second period would have instead been "o"), and that +the CPU has been online at least once since boot (otherwise, the third +period would instead have been "N"). The number before the "jiffies" +indicates that the expedited grace period has been going on for 21,119 +jiffies. The number following the "s:" indicates that the expedited +grace-period sequence counter is 73. The fact that this last value is +odd indicates that an expedited grace period is in flight. The number +following "root:" is a bitmask that indicates which children of the root +rcu_node structure correspond to CPUs and/or tasks that are blocking the +current expedited grace period. If the tree had more than one level, +additional hex numbers would be printed for the states of the other +rcu_node structures in the tree. + +As with normal grace periods, PREEMPT_RCU builds can be stalled by +tasks as well as by CPUs, and that the tasks will be indicated by PID, +for example, "P3421". It is entirely possible to see stall warnings from normal and from -expedited grace periods at about the same time from the same run. +expedited grace periods at about the same time during the same run.
Signature · 1 line
2.5.2
PATCH 5/16 memory-barriers: Replace uses of "transitive"
In reply to Paul E. McKenneyThe current version of memory-barriers.txt misuses the term "transitive", so this commit replaces it with multi-copy atomic, also adding a definition of this term.
--- Documentation/memory-barriers.txt | 185 +++++++++++++++++++------------------- 1 file changed, 91 insertions(+), 94 deletions(-)
Documentation/memory-barriers.txt +91 -94
@@ -53,7 +53,7 @@ CONTENTS - SMP barrier pairing. - Examples of memory barrier sequences. - Read memory barriers vs load speculation. - - Transitivity + - Multicopy atomicity. (*) Explicit kernel barriers.
@@ -635,6 +635,11 @@ can be used to record rare error conditions and the like, and the CPUs' naturally occurring ordering prevents such records from being lost. +Note well that the ordering provided by a data dependency is local to +the CPU containing it. See the section on "Multicopy atomicity" for +more information. + + The data dependency barrier is very important to the RCU system, for example. See rcu_assign_pointer() and rcu_dereference() in include/linux/rcupdate.h. This permits the current target of an RCU'd
@@ -851,38 +856,11 @@ 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: - - CPU 0 CPU 1 - ======================= ======================= - r1 = READ_ONCE(x); r2 = READ_ONCE(y); - if (r1 > 0) if (r2 > 0) - WRITE_ONCE(y, 1); WRITE_ONCE(x, 1); - - assert(!(r1 == 1 && r2 == 1)); - -The above two-CPU example will never trigger the assert(). However, -if control dependencies guaranteed transitivity (which they do not), -then adding the following CPU would guarantee a related assertion: - - CPU 2 - ===================== - WRITE_ONCE(x, 2); - - assert(!(r1 == 2 && r2 == 1 && x == 2)); /* FAILS!!! */ -But because control dependencies do -not- provide transitivity, the above -assertion can fail after the combined three-CPU example completes. If you -need the three-CPU example to provide ordering, you will need smp_mb() -between the loads and stores in the CPU 0 and CPU 1 code fragments, -that is, just before or just after the "if" statements. Furthermore, -the original two-CPU example is very fragile and should be avoided. +Note well that the ordering provided by a control dependency is local +to the CPU containing it. See the section on "Multicopy atomicity" +for more information. -These two examples are the LB and WWC litmus tests from this paper: -http://www.cl.cam.ac.uk/users/pes20/ppc-supplemental/test6.pdf and this -site: https://www.cl.cam.ac.uk/~pes20/ppcmem/index.html. In summary:
@@ -922,8 +900,8 @@ In summary: (*) Control dependencies pair normally with other types of barriers. - (*) Control dependencies do -not- provide transitivity. If you - need transitivity, use smp_mb(). + (*) Control dependencies do -not- provide multicopy atomicity. If you + need all the CPUs to see a given store at the same time, use smp_mb(). (*) Compilers do not understand control dependencies. It is therefore your job to ensure that they do not break your code.
@@ -936,13 +914,14 @@ 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, 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: +other types of barriers, albeit without multicopy atomicity. 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 =============== ===============
@@ -1359,64 +1338,77 @@ the speculation will be cancelled and the value reloaded: retrieved : : +-------+ -TRANSITIVITY ------------- +MULTICOPY ATOMICITY +-------------------- + +Multicopy atomicity is a deeply intuitive notion about ordering that is +not always provided by real computer systems, namely that a given store +is visible at the same time to all CPUs, or, alternatively, that all +CPUs agree on the order in which all stores took place. However, use of +full multicopy atomicity would rule out valuable hardware optimizations, +so a weaker form called ``other multicopy atomicity'' instead guarantees +that a given store is observed at the same time by all -other- CPUs. The +remainder of this document discusses this weaker form, but for brevity +will call it simply ``multicopy atomicity''. -Transitivity is a deeply intuitive notion about ordering that is not -always provided by real computer systems. The following example -demonstrates transitivity: +The following example demonstrates multicopy atomicity: CPU 1 CPU 2 CPU 3 ======================= ======================= ======================= { X = 0, Y = 0 } - STORE X=1 LOAD X STORE Y=1 - <general barrier> <general barrier> - LOAD Y LOAD X + STORE X=1 r1=LOAD X (reads 1) LOAD Y (reads 1) + <general barrier> <read barrier> + STORE Y=r1 LOAD X -Suppose that CPU 2's load from X returns 1 and its load from Y returns 0. -This indicates that CPU 2's load from X in some sense follows CPU 1's -store to X and that CPU 2's load from Y in some sense preceded CPU 3's -store to Y. The question is then "Can CPU 3's load from X return 0?" +Suppose that CPU 2's load from X returns 1 which it then stores to Y and +that CPU 3's load from Y returns 1. This indicates that CPU 2's load +from X in some sense follows CPU 1's store to X and that CPU 2's store +to Y in some sense preceded CPU 3's load from Y. The question is then +"Can CPU 3's load from X return 0?" -Because CPU 2's load from X in some sense came after CPU 1's store, it +Because CPU 3's load from X in some sense came after CPU 2's load, it is natural to expect that CPU 3's load from X must therefore return 1. -This expectation is an example of transitivity: if a load executing on -CPU A follows a load from the same variable executing on CPU B, then -CPU A's load must either return the same value that CPU B's load did, -or must return some later value. - -In the Linux kernel, use of general memory barriers guarantees -transitivity. Therefore, in the above example, if CPU 2's load from X -returns 1 and its load from Y returns 0, then CPU 3's load from X must -also return 1. - -However, transitivity is -not- guaranteed for read or write barriers. -For example, suppose that CPU 2's general barrier in the above example -is changed to a read barrier as shown below: +This expectation is an example of multicopy atomicity: if a load executing +on CPU A follows a load from the same variable executing on CPU B, then +an understandable but incorrect expectation is that CPU A's load must +either return the same value that CPU B's load did, or must return some +later value. + +In the Linux kernel, the above use of a general memory barrier compensates +for any lack of multicopy atomicity. Therefore, in the above example, +if CPU 2's load from X returns 1 and its load from Y returns 0, and CPU 3's +load from Y returns 1, then CPU 3's load from X must also return 1. + +However, dependencies, read barriers, and write barriers are not always +able to compensate for non-multicopy atomicity. For example, suppose +that CPU 2's general barrier is removed from the above example, leaving +only the data dependency shown below: CPU 1 CPU 2 CPU 3 ======================= ======================= ======================= { X = 0, Y = 0 } - STORE X=1 LOAD X STORE Y=1 - <read barrier> <general barrier> - LOAD Y LOAD X - -This substitution destroys transitivity: in this example, it is perfectly -legal for CPU 2's load from X to return 1, its load from Y to return 0, -and CPU 3's load from X to return 0. - -The key point is that although CPU 2's read barrier orders its pair -of loads, it does not guarantee to order CPU 1's store. Therefore, if -this example runs on a system where CPUs 1 and 2 share a store buffer -or a level of cache, CPU 2 might have early access to CPU 1's writes. -General barriers are therefore required to ensure that all CPUs agree -on the combined order of CPU 1's and CPU 2's accesses. - -General barriers provide "global transitivity", so that all CPUs will -agree on the order of operations. In contrast, a chain of release-acquire -pairs provides only "local transitivity", so that only those CPUs on -the chain are guaranteed to agree on the combined order of the accesses. -For example, switching to C code in deference to Herman Hollerith: + STORE X=1 r1=LOAD X (reads 1) LOAD Y (reads 1) + <data dependency> <read barrier> + STORE Y=r1 LOAD X (reads 0) + +This substitution allows non-multicopy atomicity to run rampant: in +this example, it is perfectly legal for CPU 2's load from X to return 1, +CPU 3's load from Y to return 1, and its load from X to return 0. + +The key point is that although CPU 2's data dependency orders its load +and store, it does not guarantee to order CPU 1's store. Therefore, +if this example runs on a non-multicopy-atomic system where CPUs 1 and 2 +share a store buffer or a level of cache, CPU 2 might have early access +to CPU 1's writes. A general barrier is therefore required to ensure +that all CPUs agree on the combined order of CPU 1's and CPU 2's accesses. + +General barriers can compensate not only for non-multicopy atomicity, +but can also generate additional ordering that can ensure that -all- +CPUs will perceive the same order of -all- operations. In contrast, a +chain of release-acquire pairs do not provide this additional ordering, +which means that only those CPUs on the chain are guaranteed to agree +on the combined order of the accesses. For example, switching to C code +in deference to the ghost of Herman Hollerith: int u, v, x, y, z;
@@ -1448,9 +1440,9 @@ For example, switching to C code in deference to Herman Hollerith: r3 = READ_ONCE(u); } -Because cpu0(), cpu1(), and cpu2() participate in a local transitive -chain of smp_store_release()/smp_load_acquire() pairs, the following -outcome is prohibited: +Because cpu0(), cpu1(), and cpu2() participate in a chain of +smp_store_release()/smp_load_acquire() pairs, the following outcome +is prohibited: r0 == 1 && r1 == 1 && r2 == 1
@@ -1460,9 +1452,9 @@ outcome is prohibited: r1 == 1 && r5 == 0 -However, the transitivity of release-acquire is local to the participating -CPUs and does not apply to cpu3(). Therefore, the following outcome -is possible: +However, the ordering provided by a release-acquire chain is local +to the CPUs participating in that chain and does not apply to cpu3(), +at least aside from stores. Therefore, the following outcome is possible: r0 == 0 && r1 == 1 && r2 == 1 && r3 == 0 && r4 == 0
@@ -1490,8 +1482,8 @@ following outcome is possible: Note that this outcome can happen even on a mythical sequentially consistent system where nothing is ever reordered. -To reiterate, if your code requires global transitivity, use general -barriers throughout. +To reiterate, if your code requires full ordering of all operations, +use general barriers throughout. ========================
@@ -3101,6 +3093,9 @@ AMD64 Architecture Programmer's Manual Volume 2: System Programming Chapter 7.1: Memory-Access Ordering Chapter 7.4: Buffering and Combining Memory Writes +ARM Architecture Reference Manual (ARMv8, for ARMv8-A architecture profile) + Chapter B2: The AArch64 Application Level Memory Model + IA-32 Intel Architecture Software Developer's Manual, Volume 3: System Programming Guide Chapter 7.1: Locked Atomic Operations
@@ -3112,6 +3107,8 @@ The SPARC Architecture Manual, Version 9 Appendix D: Formal Specification of the Memory Models Appendix J: Programming with the Memory Models +Storage in the PowerPC (Stone and Fitzgerald) + UltraSPARC Programmer Reference Manual Chapter 5: Memory Accesses and Cacheability Chapter 15: Sparc-V9 Memory Models
Signature · 1 line
2.5.2
PATCH 6/16 memory-barriers: Rework multicopy-atomicity section
In reply to Paul E. McKenneyFrom: Alan Stern <[email protected]>
--- Documentation/memory-barriers.txt | 58 ++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 28 deletions(-)
Documentation/memory-barriers.txt +30 -28
@@ -1343,13 +1343,13 @@ MULTICOPY ATOMICITY Multicopy atomicity is a deeply intuitive notion about ordering that is not always provided by real computer systems, namely that a given store -is visible at the same time to all CPUs, or, alternatively, that all -CPUs agree on the order in which all stores took place. However, use of -full multicopy atomicity would rule out valuable hardware optimizations, -so a weaker form called ``other multicopy atomicity'' instead guarantees -that a given store is observed at the same time by all -other- CPUs. The -remainder of this document discusses this weaker form, but for brevity -will call it simply ``multicopy atomicity''. +becomes visible at the same time to all CPUs, or, alternatively, that all +CPUs agree on the order in which all stores become visible. However, +support of full multicopy atomicity would rule out valuable hardware +optimizations, so a weaker form called ``other multicopy atomicity'' +instead guarantees only that a given store becomes visible at the same +time to all -other- CPUs. The remainder of this document discusses this +weaker form, but for brevity will call it simply ``multicopy atomicity''. The following example demonstrates multicopy atomicity:
@@ -1360,24 +1360,26 @@ The following example demonstrates multicopy atomicity: <general barrier> <read barrier> STORE Y=r1 LOAD X -Suppose that CPU 2's load from X returns 1 which it then stores to Y and -that CPU 3's load from Y returns 1. This indicates that CPU 2's load -from X in some sense follows CPU 1's store to X and that CPU 2's store -to Y in some sense preceded CPU 3's load from Y. The question is then -"Can CPU 3's load from X return 0?" +Suppose that CPU 2's load from X returns 1, which it then stores to Y, +and CPU 3's load from Y returns 1. This indicates that CPU 1's store +to X precedes CPU 2's load from X and that CPU 2's store to Y precedes +CPU 3's load from Y. In addition, the memory barriers guarantee that +CPU 2 executes its load before its store, and CPU 3 loads from Y before +it loads from X. The question is then "Can CPU 3's load from X return 0?" -Because CPU 3's load from X in some sense came after CPU 2's load, it +Because CPU 3's load from X in some sense comes after CPU 2's load, it is natural to expect that CPU 3's load from X must therefore return 1. -This expectation is an example of multicopy atomicity: if a load executing -on CPU A follows a load from the same variable executing on CPU B, then -an understandable but incorrect expectation is that CPU A's load must -either return the same value that CPU B's load did, or must return some -later value. - -In the Linux kernel, the above use of a general memory barrier compensates -for any lack of multicopy atomicity. Therefore, in the above example, -if CPU 2's load from X returns 1 and its load from Y returns 0, and CPU 3's -load from Y returns 1, then CPU 3's load from X must also return 1. +This expectation follows from multicopy atomicity: if a load executing +on CPU B follows a load from the same variable executing on CPU A (and +CPU A did not originally store the value which it read), then on +multicopy-atomic systems, CPU B's load must return either the same value +that CPU A's load did or some later value. However, the Linux kernel +does not require systems to be multicopy atomic. + +The use of a general memory barrier in the example above compensates +for any lack of multicopy atomicity. In the example, if CPU 2's load +from X returns 1 and CPU 3's load from Y returns 1, then CPU 3's load +from X must indeed also return 1. However, dependencies, read barriers, and write barriers are not always able to compensate for non-multicopy atomicity. For example, suppose
@@ -1396,11 +1398,11 @@ this example, it is perfectly legal for CPU 2's load from X to return 1, CPU 3's load from Y to return 1, and its load from X to return 0. The key point is that although CPU 2's data dependency orders its load -and store, it does not guarantee to order CPU 1's store. Therefore, -if this example runs on a non-multicopy-atomic system where CPUs 1 and 2 -share a store buffer or a level of cache, CPU 2 might have early access -to CPU 1's writes. A general barrier is therefore required to ensure -that all CPUs agree on the combined order of CPU 1's and CPU 2's accesses. +and store, it does not guarantee to order CPU 1's store. Thus, if this +example runs on a non-multicopy-atomic system where CPUs 1 and 2 share a +store buffer or a level of cache, CPU 2 might have early access to CPU 1's +writes. General barriers are therefore required to ensure that all CPUs +agree on the combined order of multiple accesses. General barriers can compensate not only for non-multicopy atomicity, but can also generate additional ordering that can ensure that -all-
Signature · 1 line
2.5.2
PATCH 7/16 doc: Fix options for RCU options
In reply to Paul E. McKenneyCommit 764f80798b95 ("doc: Add RCU files to docbook-generation files") added :external: options for RCU source files in the file Documentation/core-api/kernel-api.rst. However, this now means nothing, so this commit changes them to ":export:". Some files will no doubt need other options at some point.
--- Documentation/core-api/kernel-api.rst | 14 -------------- 1 file changed, 14 deletions(-)
Documentation/core-api/kernel-api.rst +0 -14
@@ -352,44 +352,30 @@ Read-Copy Update (RCU) ---------------------- .. kernel-doc:: include/linux/rcupdate.h - :external: .. kernel-doc:: include/linux/rcupdate_wait.h - :external: .. kernel-doc:: include/linux/rcutree.h - :external: .. kernel-doc:: kernel/rcu/tree.c - :external: .. kernel-doc:: kernel/rcu/tree_plugin.h - :external: .. kernel-doc:: kernel/rcu/tree_exp.h - :external: .. kernel-doc:: kernel/rcu/update.c - :external: .. kernel-doc:: include/linux/srcu.h - :external: .. kernel-doc:: kernel/rcu/srcutree.c - :external: .. kernel-doc:: include/linux/rculist_bl.h - :external: .. kernel-doc:: include/linux/rculist.h - :external: .. kernel-doc:: include/linux/rculist_nulls.h - :external: .. kernel-doc:: include/linux/rcu_sync.h - :external: .. kernel-doc:: kernel/rcu/sync.c - :external:
Signature · 1 line
2.5.2
PATCH 8/16 doc: Add parameters to rcupdate.h docbook comments
In reply to Paul E. McKenney--- include/linux/rcupdate.h | 4 ++++ 1 file changed, 4 insertions(+)
include/linux/rcupdate.h +4 -0
@@ -778,6 +778,8 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)/** * RCU_INIT_POINTER() - initialize an RCU protected pointer +* @p: The pointer to be initialized. +* @v: The value to initialized the pointer to. * * Initialize an RCU-protected pointer in special cases where readers * do not need ordering constraints on the CPU or the compiler. These
@@ -819,6 +821,8 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)/** * RCU_POINTER_INITIALIZER() - statically initialize an RCU protected pointer +* @p: The pointer to be initialized. +* @v: The value to initialized the pointer to. * * GCC-style initialization for an RCU-protected pointer in a structure field. */
Signature · 1 line
2.5.2
PATCH 9/16 rcu: Remove extra docbook comment in rculist.h
In reply to Paul E. McKenney--- include/linux/rculist.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/rculist.h +1 -1
@@ -276,7 +276,7 @@ static inline void list_splice_tail_init_rcu(struct list_head *list,#define list_entry_rcu (ptr, type, member) \ container_of(lockless_dereference(ptr), type, member) -/** +/* * Where are list_empty_rcu() and list_first_entry_rcu()? * * Implementing those functions following their counterparts list_empty() and
Signature · 1 line
2.5.2
PATCH 10/16 rcu: Fix docbook comments for rcu_sync functions
In reply to Paul E. McKenney--- kernel/rcu/sync.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
kernel/rcu/sync.c +6 -3
@@ -85,6 +85,9 @@ void rcu_sync_init(struct rcu_sync *rsp, enum rcu_sync_type type) }/** +* rcu_sync_enter_start - Force readers onto slow path for multiple updates +* @rsp: Pointer to rcu_sync structure to use for synchronization +* * Must be called after rcu_sync_init() and before first use. * * Ensures rcu_sync_is_idle() returns false and rcu_sync_{enter,exit}()
@@ -142,7 +145,7 @@ void rcu_sync_enter(struct rcu_sync *rsp)/** * rcu_sync_func() - Callback function managing reader access to fastpath -* @rsp: Pointer to rcu_sync structure to use for synchronization +* @rhp: Pointer to rcu_head in rcu_sync structure to use for synchronization * * This function is passed to one of the call_rcu() functions by * rcu_sync_exit(), so that it is invoked after a grace period following the
@@ -158,9 +161,9 @@ void rcu_sync_enter(struct rcu_sync *rsp)* rcu_sync_exit(). Otherwise, set all state back to idle so that readers * can again use their fastpaths. */ -static void rcu_sync_func (struct rcu_head *rcu) +static void rcu_sync_func (struct rcu_head *rhp) { - struct rcu_sync *rsp = container_of(rcu, struct rcu_sync, cb_head); + struct rcu_sync *rsp = container_of(rhp, struct rcu_sync, cb_head);unsigned long flags;BUG_ON (rsp->gp_state !=GP_PASSED );
Signature · 1 line
2.5.2
PATCH 11/16 doc: Fix list and emphasis in rcupdate.h
In reply to Paul E. McKenney--- include/linux/rcupdate.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
include/linux/rcupdate.h +8 -7
@@ -523,7 +523,7 @@ static inline void rcu_preempt_sleep_check(void) { }* Return the value of the specified RCU-protected pointer, but omit * both the smp_read_barrier_depends() and the READ_ONCE(). This * is useful in cases where update-side locks prevent the value of the -* pointer from changing. Please note that this primitive does -not- +* pointer from changing. Please note that this primitive does *not* * prevent the compiler from repeating this reference or combining it * with other references, so it should not be used without protection * of appropriate locks.
@@ -785,13 +785,14 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)* do not need ordering constraints on the CPU or the compiler. These * special cases are: * -* 1. This use of RCU_INIT_POINTER() is NULLing out the pointer -or- +* 1. This use of RCU_INIT_POINTER() is NULLing out the pointer *or* * 2. The caller has taken whatever steps are required to prevent -* RCU readers from concurrently accessing this pointer -or- +* RCU readers from concurrently accessing this pointer *or* * 3. The referenced data structure has already been exposed to -* readers either at compile time or via rcu_assign_pointer() -and- -* a. You have not made -any- reader-visible changes to -* this structure since then -or- +* readers either at compile time or via rcu_assign_pointer() *and* +* +* a. You have not made *any* reader-visible changes to +* this structure since then *or* * b. It is OK for readers accessing this structure from its * new location to see the old state of the structure. (For * example, the changes were to statistical counters or to
@@ -807,7 +808,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)* by a single external-to-structure RCU-protected pointer, then you may * use RCU_INIT_POINTER() to initialize the internal RCU-protected * pointers, but you must use rcu_assign_pointer() to initialize the -* external-to-structure pointer -after- you have completely initialized +* external-to-structure pointer *after* you have completely initialized * the reader-accessible portions of the linked structure. * * Note that unlike rcu_assign_pointer(), RCU_INIT_POINTER() provides no
Signature · 1 line
2.5.2
PATCH 12/16 doc: Flag code segment in rcu_pointer_handoff()'s docbook header
In reply to Paul E. McKenney--- include/linux/rcupdate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/rcupdate.h +1 -1
@@ -567,7 +567,7 @@ static inline void rcu_preempt_sleep_check(void) { }* This is simply an identity function, but it documents where a pointer * is handed off from RCU to some other synchronization mechanism, for * example, reference counting or locking. In C11, it would map to -* kill_dependency(). It could be used as follows: +* kill_dependency(). It could be used as follows:: * * rcu_read_lock(); * p = rcu_dereference(gp);
Signature · 1 line
2.5.2
PATCH 13/16 doc: Fix code display in rcu_pointer_handoff()'s docbook comment
In reply to Paul E. McKenney--- include/linux/rcupdate.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
include/linux/rcupdate.h +3 -2
@@ -567,8 +567,8 @@ static inline void rcu_preempt_sleep_check(void) { }* This is simply an identity function, but it documents where a pointer * is handed off from RCU to some other synchronization mechanism, for * example, reference counting or locking. In C11, it would map to -* kill_dependency(). It could be used as follows:: -* +* kill_dependency(). It could be used as follows: +* `` * rcu_read_lock(); * p = rcu_dereference(gp); * long_lived = is_long_lived(p);
@@ -579,6 +579,7 @@ static inline void rcu_preempt_sleep_check(void) { }* p = rcu_pointer_handoff(p); * } * rcu_read_unlock(); +*`` */ #define rcu_pointer_handoff (p) (p)
Signature · 1 line
2.5.2
PATCH 14/16 doc: Fix tree.c bulleted lists in docbook comment headers
In reply to Paul E. McKenney--- kernel/rcu/tree.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
kernel/rcu/tree.c +10 -8
@@ -3097,9 +3097,10 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func,* read-side critical sections have completed. call_rcu_sched() assumes * that the read-side critical sections end on enabling of preemption * or on voluntary preemption. -* RCU read-side critical sections are delimited by : -* - rcu_read_lock_sched() and rcu_read_unlock_sched(), OR -* - anything that disables preemption. +* RCU read-side critical sections are delimited by: +* +* - rcu_read_lock_sched() and rcu_read_unlock_sched(), OR +* - anything that disables preemption. * * These may be nested. *
@@ -3124,11 +3125,12 @@ EXPORT_SYMBOL_GPL(call_rcu_sched);* handler. This means that read-side critical sections in process * context must not be interrupted by softirqs. This interface is to be * used when most of the read-side critical sections are in softirq context. -* RCU read-side critical sections are delimited by : -* - rcu_read_lock() and rcu_read_unlock(), if in interrupt context. -* OR -* - rcu_read_lock_bh() and rcu_read_unlock_bh(), if in process context. -* These may be nested. +* RCU read-side critical sections are delimited by: +* +* - rcu_read_lock() and rcu_read_unlock(), if in interrupt context, OR +* - rcu_read_lock_bh() and rcu_read_unlock_bh(), if in process context. +* +* These may be nested. * * See the description of call_rcu() for more detailed information on * memory ordering guarantees.
Signature · 1 line
2.5.2
PATCH 15/16 memory-barriers.txt: Fix typo in pairing example
In reply to Paul E. McKenneyFrom: Scott Tsai <[email protected]>
In the "general barrier pairing with implicit control depdendency" example, the last write by CPU 1 was meant to change variable x and not y. The example would be pretty uninteresting if no CPU ever changes x and the variable was initialized to zero.
--- Documentation/memory-barriers.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Documentation/memory-barriers.txt +1 -1
@@ -947,7 +947,7 @@ Or even: =============== =============================== r1 = READ_ONCE(y); <general barrier> - WRITE_ONCE(y, 1); if (r2 = READ_ONCE(x)) { + WRITE_ONCE(x, 1); if (r2 = READ_ONCE(x)) { <implicit control dependency> WRITE_ONCE(y, 1); }
Signature · 1 line
2.5.2
PATCH 16/16 Documentation: rewrite confusing statement about memory barriers
In reply to Paul E. McKenneyFrom: "Guilherme G. Piccoli" <[email protected]>
In this specific portion of the write memory barriers description, the documentation mentions sequential order of stores, which is confusing since sequential ordering is not guaranteed.
This patch tries to improve the doc in order to avoid any mis-understanding.
--- Documentation/memory-barriers.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Documentation/memory-barriers.txt +2 -2
@@ -383,8 +383,8 @@ Memory barriers come in four basic varieties: to have any effect on loads. A CPU can be viewed as committing a sequence of store operations to the - memory system as time progresses. All stores before a write barrier will - occur in the sequence _before_ all the stores after the write barrier. + memory system as time progresses. All stores _before_ a write barrier + will occur _before_ all the stores after the write barrier. [!] Note that write barriers should normally be paired with read or data dependency barriers; see the "SMP barrier pairing" subsection.
Signature · 1 line
2.5.2