Browse Source

documentation: RCU-protected array indexes no longer supported

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Paul E. McKenney 10 years ago
parent
commit
cf9fbf8017

+ 16 - 4
Documentation/RCU/arrayRCU.txt

@@ -10,7 +10,19 @@ also be used to protect arrays.  Three situations are as follows:
 
 
 3.  Resizeable Arrays
 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
 Situation 1: Hash Tables
@@ -36,9 +48,9 @@ Quick Quiz:  Why is it so important that updates be rare when
 Situation 3: Resizeable Arrays
 Situation 3: Resizeable Arrays
 
 
 Use of RCU for resizeable arrays is demonstrated by the grow_ary()
 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
 function does not acquire any locks; instead its caller must hold the
 ids->sem semaphore.
 ids->sem semaphore.
 
 

+ 0 - 10
Documentation/RCU/lockdep.txt

@@ -47,11 +47,6 @@ checking of rcu_dereference() primitives:
 		Use explicit check expression "c" along with
 		Use explicit check expression "c" along with
 		srcu_read_lock_held()().  This is useful in code that
 		srcu_read_lock_held()().  This is useful in code that
 		is invoked by both SRCU readers and updaters.
 		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):
 	rcu_dereference_raw(p):
 		Don't check.  (Use sparingly, if at all.)
 		Don't check.  (Use sparingly, if at all.)
 	rcu_dereference_protected(p, c):
 	rcu_dereference_protected(p, c):
@@ -64,11 +59,6 @@ checking of rcu_dereference() primitives:
 		but retain the compiler constraints that prevent duplicating
 		but retain the compiler constraints that prevent duplicating
 		or coalescsing.  This is useful when when testing the
 		or coalescsing.  This is useful when when testing the
 		value of the pointer itself, for example, against NULL.
 		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
 The rcu_dereference_check() check expression can be any boolean
 expression, but would normally include a lockdep expression.  However,
 expression, but would normally include a lockdep expression.  However,

+ 12 - 21
Documentation/RCU/rcu_dereference.txt

@@ -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
 	for an example where the compiler can in fact deduce the exact
 	value of the pointer, and thus cause misordering.
 	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
 o	Avoid cancellation when using the "+" and "-" infix arithmetic
 	operators.  For example, for a given variable "x", avoid
 	operators.  For example, for a given variable "x", avoid
 	"(x-x)".  There are similar arithmetic pitfalls from other
 	"(x-x)".  There are similar arithmetic pitfalls from other
@@ -76,14 +65,15 @@ o	Do not use the results from the boolean "&&" and "||" when
 	dereferencing.	For example, the following (rather improbable)
 	dereferencing.	For example, the following (rather improbable)
 	code is buggy:
 	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
 	The reason this is buggy is that "&&" and "||" are often compiled
 	using branches.  While weak-memory machines such as ARM or PowerPC
 	using branches.  While weak-memory machines such as ARM or PowerPC
@@ -94,14 +84,15 @@ o	Do not use the results from relational operators ("==", "!=",
 	">", ">=", "<", or "<=") when dereferencing.  For example,
 	">", ">=", "<", or "<=") when dereferencing.  For example,
 	the following (quite strange) code is buggy:
 	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
 	As before, the reason this is buggy is that relational operators
 	are often compiled using branches.  And as before, although
 	are often compiled using branches.  And as before, although

+ 0 - 2
Documentation/RCU/whatisRCU.txt

@@ -879,9 +879,7 @@ SRCU:	Initialization/cleanup
 
 
 All:  lockdep-checked RCU-protected pointer access
 All:  lockdep-checked RCU-protected pointer access
 
 
-	rcu_access_index
 	rcu_access_pointer
 	rcu_access_pointer
-	rcu_dereference_index_check
 	rcu_dereference_raw
 	rcu_dereference_raw
 	rcu_lockdep_assert
 	rcu_lockdep_assert
 	rcu_sleep_check
 	rcu_sleep_check