forked from Minki/linux
rcu: Update documentation to cover call_srcu() and srcu_barrier().
The advent of call_srcu() and srcu_barrier() obsoleted some of the documentation, so this commit brings that up to date. Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
This commit is contained in:
parent
cba6d0d64e
commit
74d874e7bd
@ -162,9 +162,9 @@ 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() or
|
5. If call_rcu(), or a related primitive such as call_rcu_bh(),
|
||||||
call_rcu_sched(), is used, the callback function must be
|
call_rcu_sched(), or call_srcu() is used, the callback function
|
||||||
written to be called from softirq context. In particular,
|
must be written to be called from softirq context. In particular,
|
||||||
it cannot block.
|
it cannot block.
|
||||||
|
|
||||||
6. Since synchronize_rcu() can block, it cannot be called from
|
6. Since synchronize_rcu() can block, it cannot be called from
|
||||||
@ -202,11 +202,12 @@ over a rather long period of time, but improvements are always welcome!
|
|||||||
updater uses call_rcu_sched() or synchronize_sched(), then
|
updater uses call_rcu_sched() or synchronize_sched(), then
|
||||||
the corresponding readers must disable preemption, possibly
|
the corresponding readers must disable preemption, possibly
|
||||||
by calling 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(), the the corresponding
|
If the updater uses synchronize_srcu() or call_srcu(),
|
||||||
readers must use srcu_read_lock() and srcu_read_unlock(),
|
the the corresponding readers must use srcu_read_lock() and
|
||||||
and with the same srcu_struct. The rules for the expedited
|
srcu_read_unlock(), and with the same srcu_struct. The rules for
|
||||||
primitives are the same as for their non-expedited counterparts.
|
the expedited primitives are the same as for their non-expedited
|
||||||
Mixing things up will result in confusion and broken kernels.
|
counterparts. Mixing things up will result in confusion and
|
||||||
|
broken kernels.
|
||||||
|
|
||||||
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()
|
||||||
@ -333,14 +334,14 @@ over a rather long period of time, but improvements are always welcome!
|
|||||||
victim CPU from ever going offline.)
|
victim CPU from ever going offline.)
|
||||||
|
|
||||||
14. SRCU (srcu_read_lock(), srcu_read_unlock(), srcu_dereference(),
|
14. SRCU (srcu_read_lock(), srcu_read_unlock(), srcu_dereference(),
|
||||||
synchronize_srcu(), and synchronize_srcu_expedited()) may only
|
synchronize_srcu(), synchronize_srcu_expedited(), and call_srcu())
|
||||||
be invoked from process context. Unlike other forms of RCU, it
|
may only be invoked from process context. Unlike other forms of
|
||||||
-is- permissible to block in an SRCU read-side critical section
|
RCU, it -is- permissible to block in an SRCU read-side critical
|
||||||
(demarked by srcu_read_lock() and srcu_read_unlock()), hence the
|
section (demarked by srcu_read_lock() and srcu_read_unlock()),
|
||||||
"SRCU": "sleepable RCU". Please note that if you don't need
|
hence the "SRCU": "sleepable RCU". Please note that if you
|
||||||
to sleep in read-side critical sections, you should be using
|
don't need to sleep in read-side critical sections, you should be
|
||||||
RCU rather than SRCU, because RCU is almost always faster and
|
using RCU rather than SRCU, because RCU is almost always faster
|
||||||
easier to use than is SRCU.
|
and easier to use than is SRCU.
|
||||||
|
|
||||||
If you need to enter your read-side critical section in a
|
If you need to enter your read-side critical section in a
|
||||||
hardirq or exception handler, and then exit that same read-side
|
hardirq or exception handler, and then exit that same read-side
|
||||||
@ -353,8 +354,8 @@ over a rather long period of time, but improvements are always welcome!
|
|||||||
cleanup_srcu_struct(). These are passed a "struct srcu_struct"
|
cleanup_srcu_struct(). These are passed a "struct srcu_struct"
|
||||||
that defines the scope of a given SRCU domain. Once initialized,
|
that defines the scope of a given SRCU domain. Once initialized,
|
||||||
the srcu_struct is passed to srcu_read_lock(), srcu_read_unlock()
|
the srcu_struct is passed to srcu_read_lock(), srcu_read_unlock()
|
||||||
synchronize_srcu(), and synchronize_srcu_expedited(). A given
|
synchronize_srcu(), synchronize_srcu_expedited(), and call_srcu().
|
||||||
synchronize_srcu() waits only for SRCU read-side critical
|
A given synchronize_srcu() waits only for SRCU read-side critical
|
||||||
sections governed by srcu_read_lock() and srcu_read_unlock()
|
sections governed by srcu_read_lock() and srcu_read_unlock()
|
||||||
calls that have been passed the same srcu_struct. This property
|
calls that have been passed the same srcu_struct. This property
|
||||||
is what makes sleeping read-side critical sections tolerable --
|
is what makes sleeping read-side critical sections tolerable --
|
||||||
@ -374,7 +375,7 @@ over a rather long period of time, but improvements are always welcome!
|
|||||||
requiring SRCU's read-side deadlock immunity or low read-side
|
requiring SRCU's read-side deadlock immunity or low read-side
|
||||||
realtime latency.
|
realtime latency.
|
||||||
|
|
||||||
Note that, rcu_assign_pointer() relates to SRCU just as they do
|
Note that, rcu_assign_pointer() relates to SRCU just as it does
|
||||||
to other forms of RCU.
|
to other forms of RCU.
|
||||||
|
|
||||||
15. The whole point of call_rcu(), synchronize_rcu(), and friends
|
15. The whole point of call_rcu(), synchronize_rcu(), and friends
|
||||||
|
@ -79,8 +79,6 @@ complete. 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.
|
||||||
|
|
||||||
Quick Quiz #1: Why is there no srcu_barrier()?
|
|
||||||
|
|
||||||
The rcutorture module makes use of rcu_barrier in its exit function
|
The rcutorture module makes use of rcu_barrier in its exit function
|
||||||
as follows:
|
as follows:
|
||||||
|
|
||||||
@ -162,7 +160,7 @@ for any pre-existing callbacks to complete.
|
|||||||
Then lines 55-62 print status and do operation-specific cleanup, and
|
Then lines 55-62 print status and do operation-specific cleanup, and
|
||||||
then return, permitting the module-unload operation to be completed.
|
then return, permitting the module-unload operation to be completed.
|
||||||
|
|
||||||
Quick Quiz #2: Is there any other situation where rcu_barrier() might
|
Quick Quiz #1: Is there any other situation where rcu_barrier() might
|
||||||
be required?
|
be required?
|
||||||
|
|
||||||
Your module might have additional complications. For example, if your
|
Your module might have additional complications. For example, if your
|
||||||
@ -242,7 +240,7 @@ reaches zero, as follows:
|
|||||||
4 complete(&rcu_barrier_completion);
|
4 complete(&rcu_barrier_completion);
|
||||||
5 }
|
5 }
|
||||||
|
|
||||||
Quick Quiz #3: What happens if CPU 0's rcu_barrier_func() executes
|
Quick Quiz #2: What happens if CPU 0's rcu_barrier_func() executes
|
||||||
immediately (thus incrementing rcu_barrier_cpu_count to the
|
immediately (thus incrementing rcu_barrier_cpu_count to the
|
||||||
value one), but the other CPU's rcu_barrier_func() invocations
|
value one), but the other CPU's rcu_barrier_func() invocations
|
||||||
are delayed for a full grace period? Couldn't this result in
|
are delayed for a full grace period? Couldn't this result in
|
||||||
@ -259,12 +257,7 @@ so that your module may be safely unloaded.
|
|||||||
|
|
||||||
Answers to Quick Quizzes
|
Answers to Quick Quizzes
|
||||||
|
|
||||||
Quick Quiz #1: Why is there no srcu_barrier()?
|
Quick Quiz #1: Is there any other situation where rcu_barrier() might
|
||||||
|
|
||||||
Answer: Since there is no call_srcu(), there can be no outstanding SRCU
|
|
||||||
callbacks. Therefore, there is no need to wait for them.
|
|
||||||
|
|
||||||
Quick Quiz #2: Is there any other situation where rcu_barrier() might
|
|
||||||
be required?
|
be required?
|
||||||
|
|
||||||
Answer: Interestingly enough, rcu_barrier() was not originally
|
Answer: Interestingly enough, rcu_barrier() was not originally
|
||||||
@ -278,7 +271,7 @@ Answer: Interestingly enough, rcu_barrier() was not originally
|
|||||||
implementing rcutorture, and found that rcu_barrier() solves
|
implementing rcutorture, and found that rcu_barrier() solves
|
||||||
this problem as well.
|
this problem as well.
|
||||||
|
|
||||||
Quick Quiz #3: What happens if CPU 0's rcu_barrier_func() executes
|
Quick Quiz #2: What happens if CPU 0's rcu_barrier_func() executes
|
||||||
immediately (thus incrementing rcu_barrier_cpu_count to the
|
immediately (thus incrementing rcu_barrier_cpu_count to the
|
||||||
value one), but the other CPU's rcu_barrier_func() invocations
|
value one), but the other CPU's rcu_barrier_func() invocations
|
||||||
are delayed for a full grace period? Couldn't this result in
|
are delayed for a full grace period? Couldn't this result in
|
||||||
|
@ -174,11 +174,20 @@ torture_type The type of RCU to test, with string values as follows:
|
|||||||
and synchronize_rcu_bh_expedited().
|
and synchronize_rcu_bh_expedited().
|
||||||
|
|
||||||
"srcu": srcu_read_lock(), srcu_read_unlock() and
|
"srcu": srcu_read_lock(), srcu_read_unlock() and
|
||||||
|
call_srcu().
|
||||||
|
|
||||||
|
"srcu_sync": srcu_read_lock(), srcu_read_unlock() and
|
||||||
synchronize_srcu().
|
synchronize_srcu().
|
||||||
|
|
||||||
"srcu_expedited": srcu_read_lock(), srcu_read_unlock() and
|
"srcu_expedited": srcu_read_lock(), srcu_read_unlock() and
|
||||||
synchronize_srcu_expedited().
|
synchronize_srcu_expedited().
|
||||||
|
|
||||||
|
"srcu_raw": srcu_read_lock_raw(), srcu_read_unlock_raw(),
|
||||||
|
and call_srcu().
|
||||||
|
|
||||||
|
"srcu_raw_sync": srcu_read_lock_raw(), srcu_read_unlock_raw(),
|
||||||
|
and synchronize_srcu().
|
||||||
|
|
||||||
"sched": preempt_disable(), preempt_enable(), and
|
"sched": preempt_disable(), preempt_enable(), and
|
||||||
call_rcu_sched().
|
call_rcu_sched().
|
||||||
|
|
||||||
|
@ -833,9 +833,9 @@ sched: Critical sections Grace period Barrier
|
|||||||
|
|
||||||
SRCU: Critical sections Grace period Barrier
|
SRCU: Critical sections Grace period Barrier
|
||||||
|
|
||||||
srcu_read_lock synchronize_srcu N/A
|
srcu_read_lock synchronize_srcu srcu_barrier
|
||||||
srcu_read_unlock synchronize_srcu_expedited
|
srcu_read_unlock call_srcu
|
||||||
srcu_read_lock_raw
|
srcu_read_lock_raw synchronize_srcu_expedited
|
||||||
srcu_read_unlock_raw
|
srcu_read_unlock_raw
|
||||||
srcu_dereference
|
srcu_dereference
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user