diff options
author | Paul E. McKenney <paulmck@us.ibm.com> | 2005-09-10 03:26:24 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-10 13:06:24 -0400 |
commit | dd81eca83c8300c95d8a1eaf0d38f56513711535 (patch) | |
tree | a1cb1aee24b703b86f7197cfe4f379529a683c5a /Documentation/RCU/UP.txt | |
parent | 12c62c2e9abf8da804fe1def1f5bb44d023f569f (diff) |
[PATCH] Yet another RCU documentation update
Update RCU documentation based on discussions and review of RCU-based tree
patches. Add an introductory whatisRCU.txt file.
Signed-off-by: <paulmck@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'Documentation/RCU/UP.txt')
-rw-r--r-- | Documentation/RCU/UP.txt | 79 |
1 files changed, 67 insertions, 12 deletions
diff --git a/Documentation/RCU/UP.txt b/Documentation/RCU/UP.txt index 3bfb84b3b7db..aab4a9ec3931 100644 --- a/Documentation/RCU/UP.txt +++ b/Documentation/RCU/UP.txt | |||
@@ -8,7 +8,7 @@ is that since there is only one CPU, it should not be necessary to | |||
8 | wait for anything else to get done, since there are no other CPUs for | 8 | wait for anything else to get done, since there are no other CPUs for |
9 | anything else to be happening on. Although this approach will -sort- -of- | 9 | anything else to be happening on. Although this approach will -sort- -of- |
10 | work a surprising amount of the time, it is a very bad idea in general. | 10 | work a surprising amount of the time, it is a very bad idea in general. |
11 | This document presents two examples that demonstrate exactly how bad an | 11 | This document presents three examples that demonstrate exactly how bad an |
12 | idea this is. | 12 | idea this is. |
13 | 13 | ||
14 | 14 | ||
@@ -26,6 +26,9 @@ from softirq, the list scan would find itself referencing a newly freed | |||
26 | element B. This situation can greatly decrease the life expectancy of | 26 | element B. This situation can greatly decrease the life expectancy of |
27 | your kernel. | 27 | your kernel. |
28 | 28 | ||
29 | This same problem can occur if call_rcu() is invoked from a hardware | ||
30 | interrupt handler. | ||
31 | |||
29 | 32 | ||
30 | Example 2: Function-Call Fatality | 33 | Example 2: Function-Call Fatality |
31 | 34 | ||
@@ -44,8 +47,37 @@ its arguments would cause it to fail to make the fundamental guarantee | |||
44 | underlying RCU, namely that call_rcu() defers invoking its arguments until | 47 | underlying RCU, namely that call_rcu() defers invoking its arguments until |
45 | all RCU read-side critical sections currently executing have completed. | 48 | all RCU read-side critical sections currently executing have completed. |
46 | 49 | ||
47 | Quick Quiz: why is it -not- legal to invoke synchronize_rcu() in | 50 | Quick Quiz #1: why is it -not- legal to invoke synchronize_rcu() in |
48 | this case? | 51 | this case? |
52 | |||
53 | |||
54 | Example 3: Death by Deadlock | ||
55 | |||
56 | Suppose that call_rcu() is invoked while holding a lock, and that the | ||
57 | callback function must acquire this same lock. In this case, if | ||
58 | call_rcu() were to directly invoke the callback, the result would | ||
59 | be self-deadlock. | ||
60 | |||
61 | In some cases, it would possible to restructure to code so that | ||
62 | the call_rcu() is delayed until after the lock is released. However, | ||
63 | there are cases where this can be quite ugly: | ||
64 | |||
65 | 1. If a number of items need to be passed to call_rcu() within | ||
66 | the same critical section, then the code would need to create | ||
67 | a list of them, then traverse the list once the lock was | ||
68 | released. | ||
69 | |||
70 | 2. In some cases, the lock will be held across some kernel API, | ||
71 | so that delaying the call_rcu() until the lock is released | ||
72 | requires that the data item be passed up via a common API. | ||
73 | It is far better to guarantee that callbacks are invoked | ||
74 | with no locks held than to have to modify such APIs to allow | ||
75 | arbitrary data items to be passed back up through them. | ||
76 | |||
77 | If call_rcu() directly invokes the callback, painful locking restrictions | ||
78 | or API changes would be required. | ||
79 | |||
80 | Quick Quiz #2: What locking restriction must RCU callbacks respect? | ||
49 | 81 | ||
50 | 82 | ||
51 | Summary | 83 | Summary |
@@ -53,12 +85,35 @@ Summary | |||
53 | Permitting call_rcu() to immediately invoke its arguments or permitting | 85 | Permitting call_rcu() to immediately invoke its arguments or permitting |
54 | synchronize_rcu() to immediately return breaks RCU, even on a UP system. | 86 | synchronize_rcu() to immediately return breaks RCU, even on a UP system. |
55 | So do not do it! Even on a UP system, the RCU infrastructure -must- | 87 | So do not do it! Even on a UP system, the RCU infrastructure -must- |
56 | respect grace periods. | 88 | respect grace periods, and -must- invoke callbacks from a known environment |
57 | 89 | in which no locks are held. | |
58 | 90 | ||
59 | Answer to Quick Quiz | 91 | |
60 | 92 | Answer to Quick Quiz #1: | |
61 | The calling function is scanning an RCU-protected linked list, and | 93 | Why is it -not- legal to invoke synchronize_rcu() in this case? |
62 | is therefore within an RCU read-side critical section. Therefore, | 94 | |
63 | the called function has been invoked within an RCU read-side critical | 95 | Because the calling function is scanning an RCU-protected linked |
64 | section, and is not permitted to block. | 96 | list, and is therefore within an RCU read-side critical section. |
97 | Therefore, the called function has been invoked within an RCU | ||
98 | read-side critical section, and is not permitted to block. | ||
99 | |||
100 | Answer to Quick Quiz #2: | ||
101 | What locking restriction must RCU callbacks respect? | ||
102 | |||
103 | Any lock that is acquired within an RCU callback must be | ||
104 | acquired elsewhere using an _irq variant of the spinlock | ||
105 | primitive. For example, if "mylock" is acquired by an | ||
106 | RCU callback, then a process-context acquisition of this | ||
107 | lock must use something like spin_lock_irqsave() to | ||
108 | acquire the lock. | ||
109 | |||
110 | If the process-context code were to simply use spin_lock(), | ||
111 | then, since RCU callbacks can be invoked from softirq context, | ||
112 | the callback might be called from a softirq that interrupted | ||
113 | the process-context critical section. This would result in | ||
114 | self-deadlock. | ||
115 | |||
116 | This restriction might seem gratuitous, since very few RCU | ||
117 | callbacks acquire locks directly. However, a great many RCU | ||
118 | callbacks do acquire locks -indirectly-, for example, via | ||
119 | the kfree() primitive. | ||