diff options
Diffstat (limited to 'Documentation/RCU/UP.txt')
-rw-r--r-- | Documentation/RCU/UP.txt | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/Documentation/RCU/UP.txt b/Documentation/RCU/UP.txt new file mode 100644 index 000000000000..551a803d82a8 --- /dev/null +++ b/Documentation/RCU/UP.txt | |||
@@ -0,0 +1,64 @@ | |||
1 | RCU on Uniprocessor Systems | ||
2 | |||
3 | |||
4 | A common misconception is that, on UP systems, the call_rcu() primitive | ||
5 | may immediately invoke its function, and that the synchronize_kernel | ||
6 | primitive may return immediately. The basis of this misconception | ||
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 | ||
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. | ||
11 | This document presents two examples that demonstrate exactly how bad an | ||
12 | idea this is. | ||
13 | |||
14 | |||
15 | Example 1: softirq Suicide | ||
16 | |||
17 | Suppose that an RCU-based algorithm scans a linked list containing | ||
18 | elements A, B, and C in process context, and can delete elements from | ||
19 | this same list in softirq context. Suppose that the process-context scan | ||
20 | is referencing element B when it is interrupted by softirq processing, | ||
21 | which deletes element B, and then invokes call_rcu() to free element B | ||
22 | after a grace period. | ||
23 | |||
24 | Now, if call_rcu() were to directly invoke its arguments, then upon return | ||
25 | from softirq, the list scan would find itself referencing a newly freed | ||
26 | element B. This situation can greatly decrease the life expectancy of | ||
27 | your kernel. | ||
28 | |||
29 | |||
30 | Example 2: Function-Call Fatality | ||
31 | |||
32 | Of course, one could avert the suicide described in the preceding example | ||
33 | by having call_rcu() directly invoke its arguments only if it was called | ||
34 | from process context. However, this can fail in a similar manner. | ||
35 | |||
36 | Suppose that an RCU-based algorithm again scans a linked list containing | ||
37 | elements A, B, and C in process contexts, but that it invokes a function | ||
38 | on each element as it is scanned. Suppose further that this function | ||
39 | deletes element B from the list, then passes it to call_rcu() for deferred | ||
40 | freeing. This may be a bit unconventional, but it is perfectly legal | ||
41 | RCU usage, since call_rcu() must wait for a grace period to elapse. | ||
42 | Therefore, in this case, allowing call_rcu() to immediately invoke | ||
43 | its arguments would cause it to fail to make the fundamental guarantee | ||
44 | underlying RCU, namely that call_rcu() defers invoking its arguments until | ||
45 | all RCU read-side critical sections currently executing have completed. | ||
46 | |||
47 | Quick Quiz: why is it -not- legal to invoke synchronize_kernel() in | ||
48 | this case? | ||
49 | |||
50 | |||
51 | Summary | ||
52 | |||
53 | Permitting call_rcu() to immediately invoke its arguments or permitting | ||
54 | synchronize_kernel() 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- | ||
56 | respect grace periods. | ||
57 | |||
58 | |||
59 | Answer to Quick Quiz | ||
60 | |||
61 | The calling function is scanning an RCU-protected linked list, and | ||
62 | is therefore within an RCU read-side critical section. Therefore, | ||
63 | the called function has been invoked within an RCU read-side critical | ||
64 | section, and is not permitted to block. | ||