PageRenderTime 3ms CodeModel.GetById 1ms app.highlight 0ms RepoModel.GetById 1ms app.codeStats 1ms

Plain Text | 64 lines | 47 code | 17 blank | 0 comment | 0 complexity | e4b53ae361d9d6095ace342d7d30cd29 MD5 | raw file
 1RCU on Uniprocessor Systems
 4A common misconception is that, on UP systems, the call_rcu() primitive
 5may immediately invoke its function, and that the synchronize_kernel
 6primitive may return immediately.  The basis of this misconception
 7is that since there is only one CPU, it should not be necessary to
 8wait for anything else to get done, since there are no other CPUs for
 9anything else to be happening on.  Although this approach will sort of
10work a surprising amount of the time, it is a very bad idea in general.
11This document presents two examples that demonstrate exactly how bad an
12idea this is.
15Example 1: softirq Suicide
17Suppose that an RCU-based algorithm scans a linked list containing
18elements A, B, and C in process context, and can delete elements from
19this same list in softirq context.  Suppose that the process-context scan
20is referencing element B when it is interrupted by softirq processing,
21which deletes element B, and then invokes call_rcu() to free element B
22after a grace period.
24Now, if call_rcu() were to directly invoke its arguments, then upon return
25from softirq, the list scan would find itself referencing a newly freed
26element B.  This situation can greatly decrease the life expectancy of
27your kernel.
30Example 2: Function-Call Fatality
32Of course, one could avert the suicide described in the preceding example
33by having call_rcu() directly invoke its arguments only if it was called
34from process context.  However, this can fail in a similar manner.
36Suppose that an RCU-based algorithm again scans a linked list containing
37elements A, B, and C in process contexts, but that it invokes a function
38on each element as it is scanned.  Suppose further that this function
39deletes element B from the list, then passes it to call_rcu() for deferred
40freeing.  This may be a bit unconventional, but it is perfectly legal
41RCU usage, since call_rcu() must wait for a grace period to elapse.
42Therefore, in this case, allowing call_rcu() to immediately invoke
43its arguments would cause it to fail to make the fundamental guarantee
44underlying RCU, namely that call_rcu() defers invoking its arguments until
45all RCU read-side critical sections currently executing have completed.
47Quick Quiz: why is it -not- legal to invoke synchronize_kernel() in
48this case?
53Permitting call_rcu() to immediately invoke its arguments or permitting
54synchronize_kernel() to immediately return breaks RCU, even on a UP system.
55So do not do it!  Even on a UP system, the RCU infrastructure -must-
56respect grace periods.
59Answer to Quick Quiz
61The calling function is scanning an RCU-protected linked list, and
62is therefore within an RCU read-side critical section.  Therefore,
63the called function has been invoked within an RCU read-side critical
64section, and is not permitted to block.