Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | RCU on Uniprocessor Systems |
| 2 | |
| 3 | |
| 4 | A common misconception is that, on UP systems, the call_rcu() primitive |
Paul E. McKenney | a83f1fe | 2005-05-01 08:59:05 -0700 | [diff] [blame] | 5 | may immediately invoke its function, and that the synchronize_rcu() |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |
Paul E. McKenney | a83f1fe | 2005-05-01 08:59:05 -0700 | [diff] [blame] | 9 | anything else to be happening on. Although this approach will -sort- -of- |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | |
Paul E. McKenney | a83f1fe | 2005-05-01 08:59:05 -0700 | [diff] [blame] | 47 | Quick Quiz: why is it -not- legal to invoke synchronize_rcu() in |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 48 | this case? |
| 49 | |
| 50 | |
| 51 | Summary |
| 52 | |
| 53 | Permitting call_rcu() to immediately invoke its arguments or permitting |
Paul E. McKenney | a83f1fe | 2005-05-01 08:59:05 -0700 | [diff] [blame] | 54 | synchronize_rcu() to immediately return breaks RCU, even on a UP system. |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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. |