net: force a reload of first item in hlist_nulls_for_each_entry_rcu
[pandora-kernel.git] / include / linux / rcupdate.h
index caf22e8..2cf4226 100644 (file)
@@ -134,16 +134,6 @@ extern void call_rcu_sched(struct rcu_head *head,
 
 extern void synchronize_sched(void);
 
-static inline void __rcu_read_lock_bh(void)
-{
-       local_bh_disable();
-}
-
-static inline void __rcu_read_unlock_bh(void)
-{
-       local_bh_enable();
-}
-
 #ifdef CONFIG_PREEMPT_RCU
 
 extern void __rcu_read_lock(void);
@@ -443,9 +433,7 @@ extern int rcu_my_thread_group_empty(void);
        })
 #define __rcu_assign_pointer(p, v, space) \
        ({ \
-               if (!__builtin_constant_p(v) || \
-                   ((v) != NULL)) \
-                       smp_wmb(); \
+               smp_wmb(); \
                (p) = (typeof(*v) __force space *)(v); \
        })
 
@@ -688,7 +676,7 @@ static inline void rcu_read_unlock(void)
  */
 static inline void rcu_read_lock_bh(void)
 {
-       __rcu_read_lock_bh();
+       local_bh_disable();
        __acquire(RCU_BH);
        rcu_read_acquire_bh();
 }
@@ -702,7 +690,7 @@ static inline void rcu_read_unlock_bh(void)
 {
        rcu_read_release_bh();
        __release(RCU_BH);
-       __rcu_read_unlock_bh();
+       local_bh_enable();
 }
 
 /**
@@ -756,11 +744,18 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
  * any prior initialization.  Returns the value assigned.
  *
  * Inserts memory barriers on architectures that require them
- * (pretty much all of them other than x86), and also prevents
- * the compiler from reordering the code that initializes the
- * structure after the pointer assignment.  More importantly, this
- * call documents which pointers will be dereferenced by RCU read-side
- * code.
+ * (which is most of them), and also prevents the compiler from
+ * reordering the code that initializes the structure after the pointer
+ * assignment.  More importantly, this call documents which pointers
+ * will be dereferenced by RCU read-side code.
+ *
+ * In some special cases, you may use RCU_INIT_POINTER() instead
+ * of rcu_assign_pointer().  RCU_INIT_POINTER() is a bit faster due
+ * to the fact that it does not constrain either the CPU or the compiler.
+ * That said, using RCU_INIT_POINTER() when you should have used
+ * rcu_assign_pointer() is a very bad thing that results in
+ * impossible-to-diagnose memory corruption.  So please be careful.
+ * See the RCU_INIT_POINTER() comment header for details.
  */
 #define rcu_assign_pointer(p, v) \
        __rcu_assign_pointer((p), (v), __rcu)
@@ -768,8 +763,34 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
 /**
  * RCU_INIT_POINTER() - initialize an RCU protected pointer
  *
- * Initialize an RCU-protected pointer in such a way to avoid RCU-lockdep
- * splats.
+ * Initialize an RCU-protected pointer in special cases where readers
+ * do not need ordering constraints on the CPU or the compiler.  These
+ * special cases are:
+ *
+ * 1.  This use of RCU_INIT_POINTER() is NULLing out the pointer -or-
+ * 2.  The caller has taken whatever steps are required to prevent
+ *     RCU readers from concurrently accessing this pointer -or-
+ * 3.  The referenced data structure has already been exposed to
+ *     readers either at compile time or via rcu_assign_pointer() -and-
+ *     a.      You have not made -any- reader-visible changes to
+ *             this structure since then -or-
+ *     b.      It is OK for readers accessing this structure from its
+ *             new location to see the old state of the structure.  (For
+ *             example, the changes were to statistical counters or to
+ *             other state where exact synchronization is not required.)
+ *
+ * Failure to follow these rules governing use of RCU_INIT_POINTER() will
+ * result in impossible-to-diagnose memory corruption.  As in the structures
+ * will look OK in crash dumps, but any concurrent RCU readers might
+ * see pre-initialized values of the referenced data structure.  So
+ * please be very careful how you use RCU_INIT_POINTER()!!!
+ *
+ * If you are creating an RCU-protected linked structure that is accessed
+ * by a single external-to-structure RCU-protected pointer, then you may
+ * use RCU_INIT_POINTER() to initialize the internal RCU-protected
+ * pointers, but you must use rcu_assign_pointer() to initialize the
+ * external-to-structure pointer -after- you have completely initialized
+ * the reader-accessible portions of the linked structure.
  */
 #define RCU_INIT_POINTER(p, v) \
                p = (typeof(*v) __force __rcu *)(v)