1
0
Fork 0

doc: Remove obsolete RCU update functions from RCU documentation

Now that synchronize_rcu_bh, synchronize_rcu_bh_expedited, call_rcu_bh,
rcu_barrier_bh, synchronize_sched, synchronize_sched_expedited,
call_rcu_sched, rcu_barrier_sched, get_state_synchronize_sched,
and cond_synchronize_sched are obsolete, let's remove them from the
documentation aside from a small historical section.

Signed-off-by: Paul E. McKenney <paulmck@linux.ibm.com>
hifive-unleashed-5.2
Paul E. McKenney 2019-01-09 14:48:09 -08:00
parent 9e98c678c2
commit 4fea6ef0b2
8 changed files with 66 additions and 76 deletions

View File

@ -155,8 +155,7 @@ keeping lock contention under control at all tree levels regardless
of the level of loading on the system. of the level of loading on the system.
</p><p>RCU updaters wait for normal grace periods by registering </p><p>RCU updaters wait for normal grace periods by registering
RCU callbacks, either directly via <tt>call_rcu()</tt> and RCU callbacks, either directly via <tt>call_rcu()</tt>
friends (namely <tt>call_rcu_bh()</tt> and <tt>call_rcu_sched()</tt>),
or indirectly via <tt>synchronize_rcu()</tt> and friends. or indirectly via <tt>synchronize_rcu()</tt> and friends.
RCU callbacks are represented by <tt>rcu_head</tt> structures, RCU callbacks are represented by <tt>rcu_head</tt> structures,
which are queued on <tt>rcu_data</tt> structures while they are which are queued on <tt>rcu_data</tt> structures while they are

View File

@ -56,6 +56,7 @@ sections.
RCU-preempt Expedited Grace Periods</a></h2> RCU-preempt Expedited Grace Periods</a></h2>
<p> <p>
<tt>CONFIG_PREEMPT=y</tt> kernels implement RCU-preempt.
The overall flow of the handling of a given CPU by an RCU-preempt The overall flow of the handling of a given CPU by an RCU-preempt
expedited grace period is shown in the following diagram: expedited grace period is shown in the following diagram:
@ -139,6 +140,7 @@ or offline, among other things.
RCU-sched Expedited Grace Periods</a></h2> RCU-sched Expedited Grace Periods</a></h2>
<p> <p>
<tt>CONFIG_PREEMPT=n</tt> kernels implement RCU-sched.
The overall flow of the handling of a given CPU by an RCU-sched The overall flow of the handling of a given CPU by an RCU-sched
expedited grace period is shown in the following diagram: expedited grace period is shown in the following diagram:
@ -146,7 +148,7 @@ expedited grace period is shown in the following diagram:
<p> <p>
As with RCU-preempt, RCU-sched's As with RCU-preempt, RCU-sched's
<tt>synchronize_sched_expedited()</tt> ignores offline and <tt>synchronize_rcu_expedited()</tt> ignores offline and
idle CPUs, again because they are in remotely detectable idle CPUs, again because they are in remotely detectable
quiescent states. quiescent states.
However, because the However, because the

View File

@ -34,12 +34,11 @@ Similarly, any code that happens before the beginning of a given RCU grace
period is guaranteed to see the effects of all accesses following the end period is guaranteed to see the effects of all accesses following the end
of that grace period that are within RCU read-side critical sections. of that grace period that are within RCU read-side critical sections.
<p>This guarantee is particularly pervasive for <tt>synchronize_sched()</tt>, <p>Note well that RCU-sched read-side critical sections include any region
for which RCU-sched read-side critical sections include any region
of code for which preemption is disabled. of code for which preemption is disabled.
Given that each individual machine instruction can be thought of as Given that each individual machine instruction can be thought of as
an extremely small region of preemption-disabled code, one can think of an extremely small region of preemption-disabled code, one can think of
<tt>synchronize_sched()</tt> as <tt>smp_mb()</tt> on steroids. <tt>synchronize_rcu()</tt> as <tt>smp_mb()</tt> on steroids.
<p>RCU updaters use this guarantee by splitting their updates into <p>RCU updaters use this guarantee by splitting their updates into
two phases, one of which is executed before the grace period and two phases, one of which is executed before the grace period and

View File

@ -81,18 +81,19 @@ currently executing on some other CPU. We therefore cannot free
up any data structures used by the old NMI handler until execution up any data structures used by the old NMI handler until execution
of it completes on all other CPUs. of it completes on all other CPUs.
One way to accomplish this is via synchronize_sched(), perhaps as One way to accomplish this is via synchronize_rcu(), perhaps as
follows: follows:
unset_nmi_callback(); unset_nmi_callback();
synchronize_sched(); synchronize_rcu();
kfree(my_nmi_data); kfree(my_nmi_data);
This works because synchronize_sched() blocks until all CPUs complete This works because (as of v4.20) synchronize_rcu() blocks until all
any preemption-disabled segments of code that they were executing. CPUs complete any preemption-disabled segments of code that they were
Since NMI handlers disable preemption, synchronize_sched() is guaranteed executing.
Since NMI handlers disable preemption, synchronize_rcu() is guaranteed
not to return until all ongoing NMI handlers exit. It is therefore safe not to return until all ongoing NMI handlers exit. It is therefore safe
to free up the handler's data as soon as synchronize_sched() returns. to free up the handler's data as soon as synchronize_rcu() returns.
Important note: for this to work, the architecture in question must Important note: for this to work, the architecture in question must
invoke nmi_enter() and nmi_exit() on NMI entry and exit, respectively. invoke nmi_enter() and nmi_exit() on NMI entry and exit, respectively.

View File

@ -86,10 +86,8 @@ even on a UP system. So do not do it! Even on a UP system, the RCU
infrastructure -must- respect grace periods, and -must- invoke callbacks infrastructure -must- respect grace periods, and -must- invoke callbacks
from a known environment in which no locks are held. from a known environment in which no locks are held.
It -is- safe for synchronize_sched() and synchronize_rcu_bh() to return Note that it -is- safe for synchronize_rcu() to return immediately on
immediately on an UP system. It is also safe for synchronize_rcu() UP systems, including !PREEMPT SMP builds running on UP systems.
to return immediately on UP systems, except when running preemptable
RCU.
Quick Quiz #3: Why can't synchronize_rcu() return immediately on Quick Quiz #3: Why can't synchronize_rcu() return immediately on
UP systems running preemptable RCU? UP systems running preemptable RCU?

View File

@ -182,16 +182,13 @@ over a rather long period of time, but improvements are always welcome!
when publicizing a pointer to a structure that can when publicizing a pointer to a structure that can
be traversed by an RCU read-side critical section. be traversed by an RCU read-side critical section.
5. If call_rcu(), or a related primitive such as call_rcu_bh(), 5. If call_rcu() or call_srcu() is used, the callback function will
call_rcu_sched(), or call_srcu() is used, the callback function be called from softirq context. In particular, it cannot block.
will be called from softirq context. In particular, it cannot
block.
6. Since synchronize_rcu() can block, it cannot be called from 6. Since synchronize_rcu() can block, it cannot be called
any sort of irq context. The same rule applies for from any sort of irq context. The same rule applies
synchronize_rcu_bh(), synchronize_sched(), synchronize_srcu(), for synchronize_srcu(), synchronize_rcu_expedited(), and
synchronize_rcu_expedited(), synchronize_rcu_bh_expedited(), synchronize_srcu_expedited().
synchronize_sched_expedite(), and synchronize_srcu_expedited().
The expedited forms of these primitives have the same semantics The expedited forms of these primitives have the same semantics
as the non-expedited forms, but expediting is both expensive and as the non-expedited forms, but expediting is both expensive and
@ -212,20 +209,20 @@ over a rather long period of time, but improvements are always welcome!
of the system, especially to real-time workloads running on of the system, especially to real-time workloads running on
the rest of the system. the rest of the system.
7. If the updater uses call_rcu() or synchronize_rcu(), then the 7. As of v4.20, a given kernel implements only one RCU flavor,
corresponding readers must use rcu_read_lock() and which is RCU-sched for PREEMPT=n and RCU-preempt for PREEMPT=y.
rcu_read_unlock(). If the updater uses call_rcu_bh() or If the updater uses call_rcu() or synchronize_rcu(),
synchronize_rcu_bh(), then the corresponding readers must then the corresponding readers my use rcu_read_lock() and
use rcu_read_lock_bh() and rcu_read_unlock_bh(). If the rcu_read_unlock(), rcu_read_lock_bh() and rcu_read_unlock_bh(),
updater uses call_rcu_sched() or synchronize_sched(), then or any pair of primitives that disables and re-enables preemption,
the corresponding readers must disable preemption, possibly for example, rcu_read_lock_sched() and rcu_read_unlock_sched().
by calling rcu_read_lock_sched() and rcu_read_unlock_sched(). If the updater uses synchronize_srcu() or call_srcu(),
If the updater uses synchronize_srcu() or call_srcu(), then then the corresponding readers must use srcu_read_lock() and
the corresponding readers must use srcu_read_lock() and
srcu_read_unlock(), and with the same srcu_struct. The rules for srcu_read_unlock(), and with the same srcu_struct. The rules for
the expedited primitives are the same as for their non-expedited the expedited primitives are the same as for their non-expedited
counterparts. Mixing things up will result in confusion and counterparts. Mixing things up will result in confusion and
broken kernels. broken kernels, and has even resulted in an exploitable security
issue.
One exception to this rule: rcu_read_lock() and rcu_read_unlock() 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() may be substituted for rcu_read_lock_bh() and rcu_read_unlock_bh()
@ -288,8 +285,7 @@ over a rather long period of time, but improvements are always welcome!
d. Periodically invoke synchronize_rcu(), permitting a limited d. Periodically invoke synchronize_rcu(), permitting a limited
number of updates per grace period. number of updates per grace period.
The same cautions apply to call_rcu_bh(), call_rcu_sched(), The same cautions apply to call_srcu() and kfree_rcu().
call_srcu(), and kfree_rcu().
Note that although these primitives do take action to avoid memory Note that although these primitives do take action to avoid memory
exhaustion when any given CPU has too many callbacks, a determined exhaustion when any given CPU has too many callbacks, a determined
@ -336,12 +332,12 @@ over a rather long period of time, but improvements are always welcome!
to safely access and/or modify that data structure. to safely access and/or modify that data structure.
RCU callbacks are -usually- executed on the same CPU that executed RCU callbacks are -usually- executed on the same CPU that executed
the corresponding call_rcu(), call_rcu_bh(), or call_rcu_sched(), the corresponding call_rcu() or call_srcu(). but are by -no-
but are by -no- means guaranteed to be. For example, if a given means guaranteed to be. For example, if a given CPU goes offline
CPU goes offline while having an RCU callback pending, then that while having an RCU callback pending, then that RCU callback
RCU callback will execute on some surviving CPU. (If this was will execute on some surviving CPU. (If this was not the case,
not the case, a self-spawning RCU callback would prevent the a self-spawning RCU callback would prevent the victim CPU from
victim CPU from ever going offline.) ever going offline.)
13. Unlike other forms of RCU, it -is- permissible to block in an 13. Unlike other forms of RCU, it -is- permissible to block in an
SRCU read-side critical section (demarked by srcu_read_lock() SRCU read-side critical section (demarked by srcu_read_lock()
@ -381,8 +377,7 @@ over a rather long period of time, but improvements are always welcome!
SRCU's expedited primitive (synchronize_srcu_expedited()) SRCU's expedited primitive (synchronize_srcu_expedited())
never sends IPIs to other CPUs, so it is easier on never sends IPIs to other CPUs, so it is easier on
real-time workloads than is synchronize_rcu_expedited(), real-time workloads than is synchronize_rcu_expedited().
synchronize_rcu_bh_expedited() or synchronize_sched_expedited().
Note that rcu_dereference() and rcu_assign_pointer() relate to Note that rcu_dereference() and rcu_assign_pointer() relate to
SRCU just as they do to other forms of RCU. SRCU just as they do to other forms of RCU.
@ -428,22 +423,19 @@ over a rather long period of time, but improvements are always welcome!
These debugging aids can help you find problems that are These debugging aids can help you find problems that are
otherwise extremely difficult to spot. otherwise extremely difficult to spot.
17. If you register a callback using call_rcu(), call_rcu_bh(), 17. If you register a callback using call_rcu() or call_srcu(),
call_rcu_sched(), or call_srcu(), and pass in a function defined and pass in a function defined within a loadable module,
within a loadable module, then it in necessary to wait for then it in necessary to wait for all pending callbacks to
all pending callbacks to be invoked after the last invocation be invoked after the last invocation and before unloading
and before unloading that module. Note that it is absolutely that module. Note that it is absolutely -not- sufficient to
-not- sufficient to wait for a grace period! The current (say) wait for a grace period! The current (say) synchronize_rcu()
synchronize_rcu() implementation waits only for all previous implementation waits only for all previous callbacks registered
callbacks registered on the CPU that synchronize_rcu() is running on the CPU that synchronize_rcu() is running on, but it is -not-
on, but it is -not- guaranteed to wait for callbacks registered guaranteed to wait for callbacks registered on other CPUs.
on other CPUs.
You instead need to use one of the barrier functions: You instead need to use one of the barrier functions:
o call_rcu() -> rcu_barrier() o call_rcu() -> rcu_barrier()
o call_rcu_bh() -> rcu_barrier()
o call_rcu_sched() -> rcu_barrier()
o call_srcu() -> srcu_barrier() o call_srcu() -> srcu_barrier()
However, these barrier functions are absolutely -not- guaranteed However, these barrier functions are absolutely -not- guaranteed

View File

@ -52,10 +52,10 @@ o If I am running on a uniprocessor kernel, which can only do one
o How can I see where RCU is currently used in the Linux kernel? o How can I see where RCU is currently used in the Linux kernel?
Search for "rcu_read_lock", "rcu_read_unlock", "call_rcu", Search for "rcu_read_lock", "rcu_read_unlock", "call_rcu",
"rcu_read_lock_bh", "rcu_read_unlock_bh", "call_rcu_bh", "rcu_read_lock_bh", "rcu_read_unlock_bh", "srcu_read_lock",
"srcu_read_lock", "srcu_read_unlock", "synchronize_rcu", "srcu_read_unlock", "synchronize_rcu", "synchronize_net",
"synchronize_net", "synchronize_srcu", and the other RCU "synchronize_srcu", and the other RCU primitives. Or grab one
primitives. Or grab one of the cscope databases from: of the cscope databases from:
http://www.rdrop.com/users/paulmck/RCU/linuxusage/rculocktab.html http://www.rdrop.com/users/paulmck/RCU/linuxusage/rculocktab.html

View File

@ -83,16 +83,15 @@ Pseudo-code using rcu_barrier() is as follows:
2. Execute rcu_barrier(). 2. Execute rcu_barrier().
3. Allow the module to be unloaded. 3. Allow the module to be unloaded.
There are also rcu_barrier_bh(), rcu_barrier_sched(), and srcu_barrier() There is also an srcu_barrier() function for SRCU, and you of course
functions for the other flavors of RCU, and you of course must match must match the flavor of rcu_barrier() with that of call_rcu(). If your
the flavor of rcu_barrier() with that of call_rcu(). If your module module uses multiple flavors of call_rcu(), then it must also use multiple
uses multiple flavors of call_rcu(), then it must also use multiple
flavors of rcu_barrier() when unloading that module. For example, if flavors of rcu_barrier() when unloading that module. For example, if
it uses call_rcu_bh(), call_srcu() on srcu_struct_1, and call_srcu() on it uses call_rcu(), call_srcu() on srcu_struct_1, and call_srcu() on
srcu_struct_2(), then the following three lines of code will be required srcu_struct_2(), then the following three lines of code will be required
when unloading: when unloading:
1 rcu_barrier_bh(); 1 rcu_barrier();
2 srcu_barrier(&srcu_struct_1); 2 srcu_barrier(&srcu_struct_1);
3 srcu_barrier(&srcu_struct_2); 3 srcu_barrier(&srcu_struct_2);
@ -185,12 +184,12 @@ module invokes call_rcu() from timers, you will need to first cancel all
the timers, and only then invoke rcu_barrier() to wait for any remaining the timers, and only then invoke rcu_barrier() to wait for any remaining
RCU callbacks to complete. RCU callbacks to complete.
Of course, if you module uses call_rcu_bh(), you will need to invoke Of course, if you module uses call_rcu(), you will need to invoke
rcu_barrier_bh() before unloading. Similarly, if your module uses rcu_barrier() before unloading. Similarly, if your module uses
call_rcu_sched(), you will need to invoke rcu_barrier_sched() before call_srcu(), you will need to invoke srcu_barrier() before unloading,
unloading. If your module uses call_rcu(), call_rcu_bh(), -and- and on the same srcu_struct structure. If your module uses call_rcu()
call_rcu_sched(), then you will need to invoke each of rcu_barrier(), -and- call_srcu(), then you will need to invoke rcu_barrier() -and-
rcu_barrier_bh(), and rcu_barrier_sched(). srcu_barrier().
Implementing rcu_barrier() Implementing rcu_barrier()
@ -223,8 +222,8 @@ shown below. Note that the final "1" in on_each_cpu()'s argument list
ensures that all the calls to rcu_barrier_func() will have completed ensures that all the calls to rcu_barrier_func() will have completed
before on_each_cpu() returns. Line 9 then waits for the completion. before on_each_cpu() returns. Line 9 then waits for the completion.
This code was rewritten in 2008 to support rcu_barrier_bh() and This code was rewritten in 2008 and several times thereafter, but this
rcu_barrier_sched() in addition to the original rcu_barrier(). still gives the general idea.
The rcu_barrier_func() runs on each CPU, where it invokes call_rcu() The rcu_barrier_func() runs on each CPU, where it invokes call_rcu()
to post an RCU callback, as follows: to post an RCU callback, as follows: