Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

documentation: RCU-protected array indexes no longer supported

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>

+28 -37
+16 -4
Documentation/RCU/arrayRCU.txt
··· 10 10 11 11 3. Resizeable Arrays 12 12 13 - Each of these situations are discussed below. 13 + Each of these three situations involves an RCU-protected pointer to an 14 + array that is separately indexed. It might be tempting to consider use 15 + of RCU to instead protect the index into an array, however, this use 16 + case is -not- supported. The problem with RCU-protected indexes into 17 + arrays is that compilers can play way too many optimization games with 18 + integers, which means that the rules governing handling of these indexes 19 + are far more trouble than they are worth. If RCU-protected indexes into 20 + arrays prove to be particularly valuable (which they have not thus far), 21 + explicit cooperation from the compiler will be required to permit them 22 + to be safely used. 23 + 24 + That aside, each of the three RCU-protected pointer situations are 25 + described in the following sections. 14 26 15 27 16 28 Situation 1: Hash Tables ··· 48 36 Situation 3: Resizeable Arrays 49 37 50 38 Use of RCU for resizeable arrays is demonstrated by the grow_ary() 51 - function used by the System V IPC code. The array is used to map from 52 - semaphore, message-queue, and shared-memory IDs to the data structure 53 - that represents the corresponding IPC construct. The grow_ary() 39 + function formerly used by the System V IPC code. The array is used 40 + to map from semaphore, message-queue, and shared-memory IDs to the data 41 + structure that represents the corresponding IPC construct. The grow_ary() 54 42 function does not acquire any locks; instead its caller must hold the 55 43 ids->sem semaphore. 56 44
-10
Documentation/RCU/lockdep.txt
··· 47 47 Use explicit check expression "c" along with 48 48 srcu_read_lock_held()(). This is useful in code that 49 49 is invoked by both SRCU readers and updaters. 50 - rcu_dereference_index_check(p, c): 51 - Use explicit check expression "c", but the caller 52 - must supply one of the rcu_read_lock_held() functions. 53 - This is useful in code that uses RCU-protected arrays 54 - that is invoked by both RCU readers and updaters. 55 50 rcu_dereference_raw(p): 56 51 Don't check. (Use sparingly, if at all.) 57 52 rcu_dereference_protected(p, c): ··· 59 64 but retain the compiler constraints that prevent duplicating 60 65 or coalescsing. This is useful when when testing the 61 66 value of the pointer itself, for example, against NULL. 62 - rcu_access_index(idx): 63 - Return the value of the index and omit all barriers, but 64 - retain the compiler constraints that prevent duplicating 65 - or coalescsing. This is useful when when testing the 66 - value of the index itself, for example, against -1. 67 67 68 68 The rcu_dereference_check() check expression can be any boolean 69 69 expression, but would normally include a lockdep expression. However,
+12 -21
Documentation/RCU/rcu_dereference.txt
··· 25 25 for an example where the compiler can in fact deduce the exact 26 26 value of the pointer, and thus cause misordering. 27 27 28 - o Do not use single-element RCU-protected arrays. The compiler 29 - is within its right to assume that the value of an index into 30 - such an array must necessarily evaluate to zero. The compiler 31 - could then substitute the constant zero for the computation, so 32 - that the array index no longer depended on the value returned 33 - by rcu_dereference(). If the array index no longer depends 34 - on rcu_dereference(), then both the compiler and the CPU 35 - are within their rights to order the array access before the 36 - rcu_dereference(), which can cause the array access to return 37 - garbage. 38 - 39 28 o Avoid cancellation when using the "+" and "-" infix arithmetic 40 29 operators. For example, for a given variable "x", avoid 41 30 "(x-x)". There are similar arithmetic pitfalls from other ··· 65 76 dereferencing. For example, the following (rather improbable) 66 77 code is buggy: 67 78 68 - int a[2]; 69 - int index; 70 - int force_zero_index = 1; 79 + int *p; 80 + int *q; 71 81 72 82 ... 73 83 74 - r1 = rcu_dereference(i1) 75 - r2 = a[r1 && force_zero_index]; /* BUGGY!!! */ 84 + p = rcu_dereference(gp) 85 + q = &global_q; 86 + q += p != &oom_p1 && p != &oom_p2; 87 + r1 = *q; /* BUGGY!!! */ 76 88 77 89 The reason this is buggy is that "&&" and "||" are often compiled 78 90 using branches. While weak-memory machines such as ARM or PowerPC ··· 84 94 ">", ">=", "<", or "<=") when dereferencing. For example, 85 95 the following (quite strange) code is buggy: 86 96 87 - int a[2]; 88 - int index; 89 - int flip_index = 0; 97 + int *p; 98 + int *q; 90 99 91 100 ... 92 101 93 - r1 = rcu_dereference(i1) 94 - r2 = a[r1 != flip_index]; /* BUGGY!!! */ 102 + p = rcu_dereference(gp) 103 + q = &global_q; 104 + q += p > &oom_p; 105 + r1 = *q; /* BUGGY!!! */ 95 106 96 107 As before, the reason this is buggy is that relational operators 97 108 are often compiled using branches. And as before, although
-2
Documentation/RCU/whatisRCU.txt
··· 879 879 880 880 All: lockdep-checked RCU-protected pointer access 881 881 882 - rcu_access_index 883 882 rcu_access_pointer 884 - rcu_dereference_index_check 885 883 rcu_dereference_raw 886 884 rcu_lockdep_assert 887 885 rcu_sleep_check