Loading Documentation/RCU/arrayRCU.txt +16 −4 Original line number Diff line number Diff line Loading @@ -10,7 +10,19 @@ also be used to protect arrays. Three situations are as follows: 3. Resizeable Arrays Each of these situations are discussed below. Each of these three situations involves an RCU-protected pointer to an array that is separately indexed. It might be tempting to consider use of RCU to instead protect the index into an array, however, this use case is -not- supported. The problem with RCU-protected indexes into arrays is that compilers can play way too many optimization games with integers, which means that the rules governing handling of these indexes are far more trouble than they are worth. If RCU-protected indexes into arrays prove to be particularly valuable (which they have not thus far), explicit cooperation from the compiler will be required to permit them to be safely used. That aside, each of the three RCU-protected pointer situations are described in the following sections. Situation 1: Hash Tables Loading @@ -36,9 +48,9 @@ Quick Quiz: Why is it so important that updates be rare when Situation 3: Resizeable Arrays Use of RCU for resizeable arrays is demonstrated by the grow_ary() function used by the System V IPC code. The array is used to map from semaphore, message-queue, and shared-memory IDs to the data structure that represents the corresponding IPC construct. The grow_ary() function formerly used by the System V IPC code. The array is used to map from semaphore, message-queue, and shared-memory IDs to the data structure that represents the corresponding IPC construct. The grow_ary() function does not acquire any locks; instead its caller must hold the ids->sem semaphore. Loading Documentation/RCU/lockdep.txt +0 −10 Original line number Diff line number Diff line Loading @@ -47,11 +47,6 @@ checking of rcu_dereference() primitives: Use explicit check expression "c" along with srcu_read_lock_held()(). This is useful in code that is invoked by both SRCU readers and updaters. rcu_dereference_index_check(p, c): Use explicit check expression "c", but the caller must supply one of the rcu_read_lock_held() functions. This is useful in code that uses RCU-protected arrays that is invoked by both RCU readers and updaters. rcu_dereference_raw(p): Don't check. (Use sparingly, if at all.) rcu_dereference_protected(p, c): Loading @@ -64,11 +59,6 @@ checking of rcu_dereference() primitives: but retain the compiler constraints that prevent duplicating or coalescsing. This is useful when when testing the value of the pointer itself, for example, against NULL. rcu_access_index(idx): Return the value of the index and omit all barriers, but retain the compiler constraints that prevent duplicating or coalescsing. This is useful when when testing the value of the index itself, for example, against -1. The rcu_dereference_check() check expression can be any boolean expression, but would normally include a lockdep expression. However, Loading Documentation/RCU/rcu_dereference.txt +12 −21 Original line number Diff line number Diff line Loading @@ -25,17 +25,6 @@ o You must use one of the rcu_dereference() family of primitives for an example where the compiler can in fact deduce the exact value of the pointer, and thus cause misordering. o Do not use single-element RCU-protected arrays. The compiler is within its right to assume that the value of an index into such an array must necessarily evaluate to zero. The compiler could then substitute the constant zero for the computation, so that the array index no longer depended on the value returned by rcu_dereference(). If the array index no longer depends on rcu_dereference(), then both the compiler and the CPU are within their rights to order the array access before the rcu_dereference(), which can cause the array access to return garbage. o Avoid cancellation when using the "+" and "-" infix arithmetic operators. For example, for a given variable "x", avoid "(x-x)". There are similar arithmetic pitfalls from other Loading Loading @@ -76,14 +65,15 @@ o Do not use the results from the boolean "&&" and "||" when dereferencing. For example, the following (rather improbable) code is buggy: int a[2]; int index; int force_zero_index = 1; int *p; int *q; ... r1 = rcu_dereference(i1) r2 = a[r1 && force_zero_index]; /* BUGGY!!! */ p = rcu_dereference(gp) q = &global_q; q += p != &oom_p1 && p != &oom_p2; r1 = *q; /* BUGGY!!! */ The reason this is buggy is that "&&" and "||" are often compiled using branches. While weak-memory machines such as ARM or PowerPC Loading @@ -94,14 +84,15 @@ o Do not use the results from relational operators ("==", "!=", ">", ">=", "<", or "<=") when dereferencing. For example, the following (quite strange) code is buggy: int a[2]; int index; int flip_index = 0; int *p; int *q; ... r1 = rcu_dereference(i1) r2 = a[r1 != flip_index]; /* BUGGY!!! */ p = rcu_dereference(gp) q = &global_q; q += p > &oom_p; r1 = *q; /* BUGGY!!! */ As before, the reason this is buggy is that relational operators are often compiled using branches. And as before, although Loading Documentation/RCU/whatisRCU.txt +0 −2 Original line number Diff line number Diff line Loading @@ -879,9 +879,7 @@ SRCU: Initialization/cleanup All: lockdep-checked RCU-protected pointer access rcu_access_index rcu_access_pointer rcu_dereference_index_check rcu_dereference_raw rcu_lockdep_assert rcu_sleep_check Loading Loading
Documentation/RCU/arrayRCU.txt +16 −4 Original line number Diff line number Diff line Loading @@ -10,7 +10,19 @@ also be used to protect arrays. Three situations are as follows: 3. Resizeable Arrays Each of these situations are discussed below. Each of these three situations involves an RCU-protected pointer to an array that is separately indexed. It might be tempting to consider use of RCU to instead protect the index into an array, however, this use case is -not- supported. The problem with RCU-protected indexes into arrays is that compilers can play way too many optimization games with integers, which means that the rules governing handling of these indexes are far more trouble than they are worth. If RCU-protected indexes into arrays prove to be particularly valuable (which they have not thus far), explicit cooperation from the compiler will be required to permit them to be safely used. That aside, each of the three RCU-protected pointer situations are described in the following sections. Situation 1: Hash Tables Loading @@ -36,9 +48,9 @@ Quick Quiz: Why is it so important that updates be rare when Situation 3: Resizeable Arrays Use of RCU for resizeable arrays is demonstrated by the grow_ary() function used by the System V IPC code. The array is used to map from semaphore, message-queue, and shared-memory IDs to the data structure that represents the corresponding IPC construct. The grow_ary() function formerly used by the System V IPC code. The array is used to map from semaphore, message-queue, and shared-memory IDs to the data structure that represents the corresponding IPC construct. The grow_ary() function does not acquire any locks; instead its caller must hold the ids->sem semaphore. Loading
Documentation/RCU/lockdep.txt +0 −10 Original line number Diff line number Diff line Loading @@ -47,11 +47,6 @@ checking of rcu_dereference() primitives: Use explicit check expression "c" along with srcu_read_lock_held()(). This is useful in code that is invoked by both SRCU readers and updaters. rcu_dereference_index_check(p, c): Use explicit check expression "c", but the caller must supply one of the rcu_read_lock_held() functions. This is useful in code that uses RCU-protected arrays that is invoked by both RCU readers and updaters. rcu_dereference_raw(p): Don't check. (Use sparingly, if at all.) rcu_dereference_protected(p, c): Loading @@ -64,11 +59,6 @@ checking of rcu_dereference() primitives: but retain the compiler constraints that prevent duplicating or coalescsing. This is useful when when testing the value of the pointer itself, for example, against NULL. rcu_access_index(idx): Return the value of the index and omit all barriers, but retain the compiler constraints that prevent duplicating or coalescsing. This is useful when when testing the value of the index itself, for example, against -1. The rcu_dereference_check() check expression can be any boolean expression, but would normally include a lockdep expression. However, Loading
Documentation/RCU/rcu_dereference.txt +12 −21 Original line number Diff line number Diff line Loading @@ -25,17 +25,6 @@ o You must use one of the rcu_dereference() family of primitives for an example where the compiler can in fact deduce the exact value of the pointer, and thus cause misordering. o Do not use single-element RCU-protected arrays. The compiler is within its right to assume that the value of an index into such an array must necessarily evaluate to zero. The compiler could then substitute the constant zero for the computation, so that the array index no longer depended on the value returned by rcu_dereference(). If the array index no longer depends on rcu_dereference(), then both the compiler and the CPU are within their rights to order the array access before the rcu_dereference(), which can cause the array access to return garbage. o Avoid cancellation when using the "+" and "-" infix arithmetic operators. For example, for a given variable "x", avoid "(x-x)". There are similar arithmetic pitfalls from other Loading Loading @@ -76,14 +65,15 @@ o Do not use the results from the boolean "&&" and "||" when dereferencing. For example, the following (rather improbable) code is buggy: int a[2]; int index; int force_zero_index = 1; int *p; int *q; ... r1 = rcu_dereference(i1) r2 = a[r1 && force_zero_index]; /* BUGGY!!! */ p = rcu_dereference(gp) q = &global_q; q += p != &oom_p1 && p != &oom_p2; r1 = *q; /* BUGGY!!! */ The reason this is buggy is that "&&" and "||" are often compiled using branches. While weak-memory machines such as ARM or PowerPC Loading @@ -94,14 +84,15 @@ o Do not use the results from relational operators ("==", "!=", ">", ">=", "<", or "<=") when dereferencing. For example, the following (quite strange) code is buggy: int a[2]; int index; int flip_index = 0; int *p; int *q; ... r1 = rcu_dereference(i1) r2 = a[r1 != flip_index]; /* BUGGY!!! */ p = rcu_dereference(gp) q = &global_q; q += p > &oom_p; r1 = *q; /* BUGGY!!! */ As before, the reason this is buggy is that relational operators are often compiled using branches. And as before, although Loading
Documentation/RCU/whatisRCU.txt +0 −2 Original line number Diff line number Diff line Loading @@ -879,9 +879,7 @@ SRCU: Initialization/cleanup All: lockdep-checked RCU-protected pointer access rcu_access_index rcu_access_pointer rcu_dereference_index_check rcu_dereference_raw rcu_lockdep_assert rcu_sleep_check Loading