These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / Documentation / RCU / rcu_dereference.txt
index ceb05da..c0bf244 100644 (file)
@@ -25,21 +25,10 @@ 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
-       arithmetic operatiors, such as "(x*0)", "(x/(x+1))" or "(x%1)".
+       arithmetic operators, such as "(x*0)", "(x/(x+1))" or "(x%1)".
        The compiler is within its rights to substitute zero for all of
        these expressions, so that subsequent accesses no longer depend
        on the rcu_dereference(), again possibly resulting in bugs due
@@ -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
@@ -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
@@ -193,6 +184,11 @@ o  Be very careful about comparing pointers obtained from
                pointer.  Note that the volatile cast in rcu_dereference()
                will normally prevent the compiler from knowing too much.
 
+               However, please note that if the compiler knows that the
+               pointer takes on only one of two values, a not-equal
+               comparison will provide exactly the information that the
+               compiler needs to deduce the value of the pointer.
+
 o      Disable any value-speculation optimizations that your compiler
        might provide, especially if you are making use of feedback-based
        optimizations that take data collected from prior runs.  Such