#ifndef __LINUX_RCU_ASSIGN_POINTER_H__
|
#define __LINUX_RCU_ASSIGN_POINTER_H__
|
#include <linux/compiler.h>
|
#include <asm/barrier.h>
|
|
/**
|
* 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) \
|
({ \
|
uintptr_t _r_a_p__v = (uintptr_t)(v); \
|
\
|
if (__builtin_constant_p(v) && (_r_a_p__v) == (uintptr_t)NULL) \
|
WRITE_ONCE((p), (typeof(p))(_r_a_p__v)); \
|
else \
|
smp_store_release(&p, RCU_INITIALIZER((typeof(p))_r_a_p__v)); \
|
_r_a_p__v; \
|
})
|
|
#endif
|