rcu: Add an RCU_INITIALIZER for global RCU-protected pointers
There is currently no way to initialize a global RCU-protected pointer without either putting up with sparse complaints or open-coding an obscure cast. This commit therefore creates RCU_INITIALIZER(), which is intended to be used as follows: struct foo __rcu *p = RCU_INITIALIZER(&my_rcu_structure); This commit also applies RCU_INITIALIZER() to eliminate repeated open-coded obscure casts in __rcu_assign_pointer(), RCU_INIT_POINTER(), and RCU_POINTER_INITIALIZER(). This commit also inlines __rcu_assign_pointer() into its only caller, rcu_assign_pointer(). Suggested-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Reviewed-by: Josh Triplett <josh@joshtriplett.org>
This commit is contained in:
parent
9d162cd063
commit
462225ae47
|
@ -548,10 +548,48 @@ static inline void rcu_preempt_sleep_check(void)
|
|||
smp_read_barrier_depends(); \
|
||||
(_________p1); \
|
||||
})
|
||||
#define __rcu_assign_pointer(p, v, space) \
|
||||
|
||||
/**
|
||||
* RCU_INITIALIZER() - statically initialize an RCU-protected global variable
|
||||
* @v: The value to statically initialize with.
|
||||
*/
|
||||
#define RCU_INITIALIZER(v) (typeof(*(v)) __force __rcu *)(v)
|
||||
|
||||
/**
|
||||
* rcu_assign_pointer() - assign to RCU-protected pointer
|
||||
* @p: pointer to assign to
|
||||
* @v: value to assign (publish)
|
||||
*
|
||||
* Assigns the specified value to the specified RCU-protected
|
||||
* pointer, ensuring that any concurrent RCU readers will see
|
||||
* any prior initialization.
|
||||
*
|
||||
* Inserts memory barriers on architectures that require them
|
||||
* (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.
|
||||
*
|
||||
* Note that rcu_assign_pointer() evaluates each of its arguments only
|
||||
* once, appearances notwithstanding. One of the "extra" evaluations
|
||||
* is in typeof() and the other visible only to sparse (__CHECKER__),
|
||||
* neither of which actually execute the argument. As with most cpp
|
||||
* macros, this execute-arguments-only-once property is important, so
|
||||
* please be careful when making changes to rcu_assign_pointer() and the
|
||||
* other macros that it invokes.
|
||||
*/
|
||||
#define rcu_assign_pointer(p, v) \
|
||||
do { \
|
||||
smp_wmb(); \
|
||||
ACCESS_ONCE(p) = (typeof(*(v)) __force space *)(v); \
|
||||
ACCESS_ONCE(p) = RCU_INITIALIZER(v); \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
@ -889,40 +927,6 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
|
|||
preempt_enable_notrace();
|
||||
}
|
||||
|
||||
/**
|
||||
* rcu_assign_pointer() - assign to RCU-protected pointer
|
||||
* @p: pointer to assign to
|
||||
* @v: value to assign (publish)
|
||||
*
|
||||
* Assigns the specified value to the specified RCU-protected
|
||||
* pointer, ensuring that any concurrent RCU readers will see
|
||||
* any prior initialization.
|
||||
*
|
||||
* Inserts memory barriers on architectures that require them
|
||||
* (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.
|
||||
*
|
||||
* Note that rcu_assign_pointer() evaluates each of its arguments only
|
||||
* once, appearances notwithstanding. One of the "extra" evaluations
|
||||
* is in typeof() and the other visible only to sparse (__CHECKER__),
|
||||
* neither of which actually execute the argument. As with most cpp
|
||||
* macros, this execute-arguments-only-once property is important, so
|
||||
* please be careful when making changes to rcu_assign_pointer() and the
|
||||
* other macros that it invokes.
|
||||
*/
|
||||
#define rcu_assign_pointer(p, v) \
|
||||
__rcu_assign_pointer((p), (v), __rcu)
|
||||
|
||||
/**
|
||||
* RCU_INIT_POINTER() - initialize an RCU protected pointer
|
||||
*
|
||||
|
@ -957,7 +961,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
|
|||
*/
|
||||
#define RCU_INIT_POINTER(p, v) \
|
||||
do { \
|
||||
p = (typeof(*v) __force __rcu *)(v); \
|
||||
p = RCU_INITIALIZER(v); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
|
@ -966,7 +970,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
|
|||
* GCC-style initialization for an RCU-protected pointer in a structure field.
|
||||
*/
|
||||
#define RCU_POINTER_INITIALIZER(p, v) \
|
||||
.p = (typeof(*v) __force __rcu *)(v)
|
||||
.p = RCU_INITIALIZER(v)
|
||||
|
||||
/*
|
||||
* Does the specified offset indicate that the corresponding rcu_head
|
||||
|
|
Loading…
Reference in New Issue