diff options
author | Paul E. McKenney <paulmck@us.ibm.com> | 2006-10-04 05:17:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-04 10:55:30 -0400 |
commit | 621934ee7ed5b073c7fd638b347e632c53572761 (patch) | |
tree | 5722f9cda22c099ad60545f963410dcbc762ee65 /Documentation/RCU | |
parent | 95d77884c77beed676036d2f74d10b470a483c63 (diff) |
[PATCH] srcu-3: RCU variant permitting read-side blocking
Updated patch adding a variant of RCU that permits sleeping in read-side
critical sections. SRCU is as follows:
o Each use of SRCU creates its own srcu_struct, and each
srcu_struct has its own set of grace periods. This is
critical, as it prevents one subsystem with a blocking
reader from holding up SRCU grace periods for other
subsystems.
o The SRCU primitives (srcu_read_lock(), srcu_read_unlock(),
and synchronize_srcu()) all take a pointer to a srcu_struct.
o The SRCU primitives must be called from process context.
o srcu_read_lock() returns an int that must be passed to
the matching srcu_read_unlock(). Realtime RCU avoids the
need for this by storing the state in the task struct,
but SRCU needs to allow a given code path to pass through
multiple SRCU domains -- storing state in the task struct
would therefore require either arbitrary space in the
task struct or arbitrary limits on SRCU nesting. So I
kicked the state-storage problem up to the caller.
Of course, it is not permitted to call synchronize_srcu()
while in an SRCU read-side critical section.
o There is no call_srcu(). It would not be hard to implement
one, but it seems like too easy a way to OOM the system.
(Hey, we have enough trouble with call_rcu(), which does
-not- permit readers to sleep!!!) So, if you want it,
please tell me why...
[josht@us.ibm.com: sparse notation]
Signed-off-by: Paul E. McKenney <paulmck@us.ibm.com>
Signed-off-by: Josh Triplett <josh@freedesktop.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'Documentation/RCU')
-rw-r--r-- | Documentation/RCU/checklist.txt | 38 | ||||
-rw-r--r-- | Documentation/RCU/rcu.txt | 3 | ||||
-rw-r--r-- | Documentation/RCU/whatisRCU.txt | 3 |
3 files changed, 43 insertions, 1 deletions
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt index 1d50cf0c905e..f4dffadbcb00 100644 --- a/Documentation/RCU/checklist.txt +++ b/Documentation/RCU/checklist.txt | |||
@@ -221,3 +221,41 @@ over a rather long period of time, but improvements are always welcome! | |||
221 | disable irq on a given acquisition of that lock will result in | 221 | disable irq on a given acquisition of that lock will result in |
222 | deadlock as soon as the RCU callback happens to interrupt that | 222 | deadlock as soon as the RCU callback happens to interrupt that |
223 | acquisition's critical section. | 223 | acquisition's critical section. |
224 | |||
225 | 13. SRCU (srcu_read_lock(), srcu_read_unlock(), and synchronize_srcu()) | ||
226 | may only be invoked from process context. Unlike other forms of | ||
227 | RCU, it -is- permissible to block in an SRCU read-side critical | ||
228 | section (demarked by srcu_read_lock() and srcu_read_unlock()), | ||
229 | hence the "SRCU": "sleepable RCU". Please note that if you | ||
230 | don't need to sleep in read-side critical sections, you should | ||
231 | be using RCU rather than SRCU, because RCU is almost always | ||
232 | faster and easier to use than is SRCU. | ||
233 | |||
234 | Also unlike other forms of RCU, explicit initialization | ||
235 | and cleanup is required via init_srcu_struct() and | ||
236 | cleanup_srcu_struct(). These are passed a "struct srcu_struct" | ||
237 | that defines the scope of a given SRCU domain. Once initialized, | ||
238 | the srcu_struct is passed to srcu_read_lock(), srcu_read_unlock() | ||
239 | and synchronize_srcu(). A given synchronize_srcu() waits only | ||
240 | for SRCU read-side critical sections governed by srcu_read_lock() | ||
241 | and srcu_read_unlock() calls that have been passd the same | ||
242 | srcu_struct. This property is what makes sleeping read-side | ||
243 | critical sections tolerable -- a given subsystem delays only | ||
244 | its own updates, not those of other subsystems using SRCU. | ||
245 | Therefore, SRCU is less prone to OOM the system than RCU would | ||
246 | be if RCU's read-side critical sections were permitted to | ||
247 | sleep. | ||
248 | |||
249 | The ability to sleep in read-side critical sections does not | ||
250 | come for free. First, corresponding srcu_read_lock() and | ||
251 | srcu_read_unlock() calls must be passed the same srcu_struct. | ||
252 | Second, grace-period-detection overhead is amortized only | ||
253 | over those updates sharing a given srcu_struct, rather than | ||
254 | being globally amortized as they are for other forms of RCU. | ||
255 | Therefore, SRCU should be used in preference to rw_semaphore | ||
256 | only in extremely read-intensive situations, or in situations | ||
257 | requiring SRCU's read-side deadlock immunity or low read-side | ||
258 | realtime latency. | ||
259 | |||
260 | Note that, rcu_assign_pointer() and rcu_dereference() relate to | ||
261 | SRCU just as they do to other forms of RCU. | ||
diff --git a/Documentation/RCU/rcu.txt b/Documentation/RCU/rcu.txt index 02e27bf1d365..f84407cba816 100644 --- a/Documentation/RCU/rcu.txt +++ b/Documentation/RCU/rcu.txt | |||
@@ -45,7 +45,8 @@ o How can I see where RCU is currently used in the Linux kernel? | |||
45 | 45 | ||
46 | Search for "rcu_read_lock", "rcu_read_unlock", "call_rcu", | 46 | Search for "rcu_read_lock", "rcu_read_unlock", "call_rcu", |
47 | "rcu_read_lock_bh", "rcu_read_unlock_bh", "call_rcu_bh", | 47 | "rcu_read_lock_bh", "rcu_read_unlock_bh", "call_rcu_bh", |
48 | "synchronize_rcu", and "synchronize_net". | 48 | "srcu_read_lock", "srcu_read_unlock", "synchronize_rcu", |
49 | "synchronize_net", and "synchronize_srcu". | ||
49 | 50 | ||
50 | o What guidelines should I follow when writing code that uses RCU? | 51 | o What guidelines should I follow when writing code that uses RCU? |
51 | 52 | ||
diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt index 820fee236967..e0d6d99b8f9b 100644 --- a/Documentation/RCU/whatisRCU.txt +++ b/Documentation/RCU/whatisRCU.txt | |||
@@ -778,6 +778,8 @@ Markers for RCU read-side critical sections: | |||
778 | rcu_read_unlock | 778 | rcu_read_unlock |
779 | rcu_read_lock_bh | 779 | rcu_read_lock_bh |
780 | rcu_read_unlock_bh | 780 | rcu_read_unlock_bh |
781 | srcu_read_lock | ||
782 | srcu_read_unlock | ||
781 | 783 | ||
782 | RCU pointer/list traversal: | 784 | RCU pointer/list traversal: |
783 | 785 | ||
@@ -804,6 +806,7 @@ RCU grace period: | |||
804 | synchronize_net | 806 | synchronize_net |
805 | synchronize_sched | 807 | synchronize_sched |
806 | synchronize_rcu | 808 | synchronize_rcu |
809 | synchronize_srcu | ||
807 | call_rcu | 810 | call_rcu |
808 | call_rcu_bh | 811 | call_rcu_bh |
809 | 812 | ||