]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - Documentation/RCU/rcu_dereference.txt
doc: No longer allowed to use rcu_dereference on non-pointers
[mirror_ubuntu-bionic-kernel.git] / Documentation / RCU / rcu_dereference.txt
index b2a613f16d747828e35fd182a0c9fe06c1107d0f..1acb26b09b48bf2877c0bd4b96a72f9d9758c045 100644 (file)
@@ -25,35 +25,35 @@ 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      You are only permitted to use rcu_dereference on pointer values.
+       The compiler simply knows too much about integral values to
+       trust it to carry dependencies through integer operations.
+       There are a very few exceptions, namely that you can temporarily
+       cast the pointer to uintptr_t in order to:
+
+       o       Set bits and clear bits down in the must-be-zero low-order
+               bits of that pointer.  This clearly means that the pointer
+               must have alignment constraints, for example, this does
+               -not- work in general for char* pointers.
+
+       o       XOR bits to translate pointers, as is done in some
+               classic buddy-allocator algorithms.
+
+       It is important to cast the value back to pointer before
+       doing much of anything else with it.
+
 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 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
-       to misordering.
+       "(x-(uintptr_t)x)" for char* pointers.  The compiler is within its
+       rights to substitute zero for this sort of expression, so that
+       subsequent accesses no longer depend on the rcu_dereference(),
+       again possibly resulting in bugs due to misordering.
 
        Of course, if "p" is a pointer from rcu_dereference(), and "a"
        and "b" are integers that happen to be equal, the expression
        "p+a-b" is safe because its value still necessarily depends on
        the rcu_dereference(), thus maintaining proper ordering.
 
-o      Avoid all-zero operands to the bitwise "&" operator, and
-       similarly avoid all-ones operands to the bitwise "|" operator.
-       If the compiler is able to deduce the value of such operands,
-       it is within its rights to substitute the corresponding constant
-       for the bitwise operation.  Once again, this causes subsequent
-       accesses to no longer depend on the rcu_dereference(), causing
-       bugs due to misordering.
-
-       Please note that single-bit operands to bitwise "&" can also
-       be dangerous.  At this point, the compiler knows that the
-       resulting value can only take on one of two possible values.
-       Therefore, a very small amount of additional information will
-       allow the compiler to deduce the exact value, which again can
-       result in misordering.
-
 o      If you are using RCU to protect JITed functions, so that the
        "()" function-invocation operator is applied to a value obtained
        (directly or indirectly) from rcu_dereference(), you may need to
@@ -61,25 +61,6 @@ o    If you are using RCU to protect JITed functions, so that the
        This issue arises on some systems when a newly JITed function is
        using the same memory that was used by an earlier JITed function.
 
-o      Do not use the results from the boolean "&&" and "||" when
-       dereferencing.  For example, the following (rather improbable)
-       code is buggy:
-
-               int *p;
-               int *q;
-
-               ...
-
-               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
-       do order stores after such branches, they can speculate loads,
-       which can result in misordering bugs.
-
 o      Do not use the results from relational operators ("==", "!=",
        ">", ">=", "<", or "<=") when dereferencing.  For example,
        the following (quite strange) code is buggy: