OSDN Git Service

doc: Clarify and expand RCU updaters and corresponding readers
authorPaul E. McKenney <paulmck@kernel.org>
Thu, 24 Jun 2021 16:05:52 +0000 (18:05 +0200)
committerDaniel Borkmann <daniel@iogearbox.net>
Thu, 24 Jun 2021 17:41:14 +0000 (19:41 +0200)
This commit clarifies which primitives readers can use given that the
corresponding updaters have made a specific choice.  This commit also adds
this information for the various RCU Tasks flavors.  While in the area, it
removes a paragraph that no longer applies in any straightforward manner.

Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20210624160609.292325-3-toke@redhat.com
Documentation/RCU/checklist.rst

index 1030119..07f6cb8 100644 (file)
@@ -211,27 +211,33 @@ over a rather long period of time, but improvements are always welcome!
        of the system, especially to real-time workloads running on
        the rest of the system.
 
-7.     As of v4.20, a given kernel implements only one RCU flavor,
-       which is RCU-sched for PREEMPTION=n and RCU-preempt for PREEMPTION=y.
-       If the updater uses call_rcu() or synchronize_rcu(),
-       then the corresponding readers may use rcu_read_lock() and
-       rcu_read_unlock(), rcu_read_lock_bh() and rcu_read_unlock_bh(),
-       or any pair of primitives that disables and re-enables preemption,
-       for example, rcu_read_lock_sched() and rcu_read_unlock_sched().
-       If the updater uses synchronize_srcu() or call_srcu(),
-       then the corresponding readers must use srcu_read_lock() and
-       srcu_read_unlock(), and with the same srcu_struct.  The rules for
-       the expedited primitives are the same as for their non-expedited
-       counterparts.  Mixing things up will result in confusion and
-       broken kernels, and has even resulted in an exploitable security
-       issue.
-
-       One exception to this rule: rcu_read_lock() and rcu_read_unlock()
-       may be substituted for rcu_read_lock_bh() and rcu_read_unlock_bh()
-       in cases where local bottom halves are already known to be
-       disabled, for example, in irq or softirq context.  Commenting
-       such cases is a must, of course!  And the jury is still out on
-       whether the increased speed is worth it.
+7.     As of v4.20, a given kernel implements only one RCU flavor, which
+       is RCU-sched for PREEMPTION=n and RCU-preempt for PREEMPTION=y.
+       If the updater uses call_rcu() or synchronize_rcu(), then
+       the corresponding readers may use:  (1) rcu_read_lock() and
+       rcu_read_unlock(), (2) any pair of primitives that disables
+       and re-enables softirq, for example, rcu_read_lock_bh() and
+       rcu_read_unlock_bh(), or (3) any pair of primitives that disables
+       and re-enables preemption, for example, rcu_read_lock_sched() and
+       rcu_read_unlock_sched().  If the updater uses synchronize_srcu()
+       or call_srcu(), then the corresponding readers must use
+       srcu_read_lock() and srcu_read_unlock(), and with the same
+       srcu_struct.  The rules for the expedited RCU grace-period-wait
+       primitives are the same as for their non-expedited counterparts.
+
+       If the updater uses call_rcu_tasks() or synchronize_rcu_tasks(),
+       then the readers must refrain from executing voluntary
+       context switches, that is, from blocking.  If the updater uses
+       call_rcu_tasks_trace() or synchronize_rcu_tasks_trace(), then
+       the corresponding readers must use rcu_read_lock_trace() and
+       rcu_read_unlock_trace().  If an updater uses call_rcu_tasks_rude()
+       or synchronize_rcu_tasks_rude(), then the corresponding readers
+       must use anything that disables interrupts.
+
+       Mixing things up will result in confusion and broken kernels, and
+       has even resulted in an exploitable security issue.  Therefore,
+       when using non-obvious pairs of primitives, commenting is of
+       course a must.
 
 8.     Although synchronize_rcu() is slower than is call_rcu(), it
        usually results in simpler code.  So, unless update performance is