urcu-pointer-static.h | urcu-pointer-static.h | |||
---|---|---|---|---|
skipping to change at line 74 | skipping to change at line 74 | |||
}) | }) | |||
/** | /** | |||
* _rcu_cmpxchg_pointer - same as rcu_assign_pointer, but tests if the poin ter | * _rcu_cmpxchg_pointer - same as rcu_assign_pointer, but tests if the poin ter | |||
* is as expected by "old". If succeeds, returns the previous pointer to th e | * is as expected by "old". If succeeds, returns the previous pointer to th e | |||
* data structure, which can be safely freed after waiting for a quiescent state | * data structure, which can be safely freed after waiting for a quiescent state | |||
* using synchronize_rcu(). If fails (unexpected value), returns old (which | * using synchronize_rcu(). If fails (unexpected value), returns old (which | |||
* should not be freed !). | * should not be freed !). | |||
*/ | */ | |||
#define _rcu_cmpxchg_pointer(p, old, _new) \ | #define _rcu_cmpxchg_pointer(p, old, _new) \ | |||
({ \ | ({ \ | |||
if (!__builtin_constant_p(_new) || \ | typeof(*p) _________pold = (old); \ | |||
((_new) != NULL)) \ | typeof(*p) _________pnew = (_new); \ | |||
wmb(); \ | if (!__builtin_constant_p(_new) || \ | |||
uatomic_cmpxchg(p, old, _new); \ | ((_new) != NULL)) \ | |||
wmb(); \ | ||||
uatomic_cmpxchg(p, _________pold, _________pnew); \ | ||||
}) | }) | |||
/** | /** | |||
* _rcu_xchg_pointer - same as rcu_assign_pointer, but returns the previous | * _rcu_xchg_pointer - same as rcu_assign_pointer, but returns the previous | |||
* pointer to the data structure, which can be safely freed after waiting f or a | * pointer to the data structure, which can be safely freed after waiting f or a | |||
* quiescent state using synchronize_rcu(). | * quiescent state using synchronize_rcu(). | |||
*/ | */ | |||
#define _rcu_xchg_pointer(p, v) \ | #define _rcu_xchg_pointer(p, v) \ | |||
({ \ | ({ \ | |||
typeof(*p) _________pv = (v); \ | ||||
if (!__builtin_constant_p(v) || \ | if (!__builtin_constant_p(v) || \ | |||
((v) != NULL)) \ | ((v) != NULL)) \ | |||
wmb(); \ | wmb(); \ | |||
uatomic_xchg(p, v); \ | uatomic_xchg(p, _________pv); \ | |||
}) | }) | |||
#define _rcu_set_pointer(p, v) \ | #define _rcu_set_pointer(p, v) \ | |||
({ \ | ({ \ | |||
typeof(*p) _________pv = (v); \ | ||||
if (!__builtin_constant_p(v) || \ | if (!__builtin_constant_p(v) || \ | |||
((v) != NULL)) \ | ((v) != NULL)) \ | |||
wmb(); \ | wmb(); \ | |||
STORE_SHARED(*(p), v); \ | STORE_SHARED(*(p), _________pv); \ | |||
}) | ||||
/* | ||||
* _rcu_publish_content - Exchanges the pointer and waits for quiescent sta | ||||
te. | ||||
* | ||||
* The pointer returned can be freed. | ||||
*/ | ||||
#define _rcu_publish_content(p, v) \ | ||||
({ \ | ||||
void *oldptr; \ | ||||
oldptr = _rcu_xchg_pointer(p, v); \ | ||||
synchronize_rcu(); \ | ||||
oldptr; \ | ||||
}) | }) | |||
/** | /** | |||
* _rcu_assign_pointer - assign (publicize) a pointer to a new data structu re | * _rcu_assign_pointer - assign (publicize) a pointer to a new data structu re | |||
* meant to be read by RCU read-side critical sections. Returns the assigne d | * meant to be read by RCU read-side critical sections. Returns the assigne d | |||
* value. | * value. | |||
* | * | |||
* Documents which pointers will be dereferenced by RCU read-side critical | * Documents which pointers will be dereferenced by RCU read-side critical | |||
* sections and adds the required memory barriers on architectures requirin g | * sections and adds the required memory barriers on architectures requirin g | |||
* them. It also makes sure the compiler does not reorder code initializing the | * them. It also makes sure the compiler does not reorder code initializing the | |||
End of changes. 5 change blocks. | ||||
22 lines changed or deleted | 12 lines changed or added | |||
urcu-pointer.h | urcu-pointer.h | |||
---|---|---|---|---|
skipping to change at line 61 | skipping to change at line 61 | |||
* @ptr: address of the pointer to modify | * @ptr: address of the pointer to modify | |||
* @new: new pointer value | * @new: new pointer value | |||
* @old: old pointer value (expected) | * @old: old pointer value (expected) | |||
* | * | |||
* return: old pointer value | * return: old pointer value | |||
*/ | */ | |||
#define rcu_cmpxchg_pointer _rcu_cmpxchg_pointer | #define rcu_cmpxchg_pointer _rcu_cmpxchg_pointer | |||
#define rcu_xchg_pointer _rcu_xchg_pointer | #define rcu_xchg_pointer _rcu_xchg_pointer | |||
#define rcu_set_pointer _rcu_set_pointer | #define rcu_set_pointer _rcu_set_pointer | |||
/* | ||||
* type *rcu_publish_content(type **ptr, type *new) | ||||
* | ||||
* Exchanges the pointer and waits for quiescent state. The pointer returne | ||||
d | ||||
* can be freed. You are encouraged to use either | ||||
* - rcu_cmpxchg_pointer | ||||
* - rcu_xchg_pointer | ||||
* - rcu_set_pointer | ||||
* with call_rcu(free, ptr) instead to deal with reclamation more efficient | ||||
ly. | ||||
*/ | ||||
#define rcu_publish_content _rcu_publish_content | ||||
#else /* !_LGPL_SOURCE */ | #else /* !_LGPL_SOURCE */ | |||
extern void *rcu_dereference(void *p); | extern void *rcu_dereference_sym(void *p); | |||
#define rcu_dereference(p) | ||||
\ | ||||
({ | ||||
\ | ||||
typeof(p) _________p1 = | ||||
\ | ||||
rcu_dereference_sym((void *)(p)); | ||||
\ | ||||
(_________p1); | ||||
\ | ||||
}) | ||||
extern void *rcu_cmpxchg_pointer_sym(void **p, void *old, void *_new); | extern void *rcu_cmpxchg_pointer_sym(void **p, void *old, void *_new); | |||
#define rcu_cmpxchg_pointer(p, old, _new) \ | #define rcu_cmpxchg_pointer(p, old, _new) | |||
rcu_cmpxchg_pointer_sym((void **)(p), (old), (_new)) | \ | |||
({ | ||||
\ | ||||
typeof(*p) _________pold = (old); | ||||
\ | ||||
typeof(*p) _________pnew = (_new); | ||||
\ | ||||
typeof(*p) _________p1 = | ||||
\ | ||||
rcu_cmpxchg_pointer_sym((void **)(p), _________pold, | ||||
\ | ||||
_________pnew); | ||||
\ | ||||
(_________p1); | ||||
\ | ||||
}) | ||||
extern void *rcu_xchg_pointer_sym(void **p, void *v); | extern void *rcu_xchg_pointer_sym(void **p, void *v); | |||
#define rcu_xchg_pointer(p, v) \ | #define rcu_xchg_pointer(p, v) | |||
rcu_xchg_pointer_sym((void **)(p), (v)) | \ | |||
({ | ||||
\ | ||||
typeof(*p) _________pv = (v); | ||||
\ | ||||
typeof(*p) _________p1 = | ||||
\ | ||||
rcu_xchg_pointer_sym((void **)(p), _________pv); | ||||
\ | ||||
(_________p1); | ||||
\ | ||||
}) | ||||
extern void *rcu_set_pointer_sym(void **p, void *v); | extern void *rcu_set_pointer_sym(void **p, void *v); | |||
#define rcu_set_pointer(p, v) \ | #define rcu_set_pointer(p, v) | |||
rcu_set_pointer_sym((void **)(p), (v)) | \ | |||
({ | ||||
extern void *rcu_publish_content_sym(void **p, void *v); | \ | |||
#define rcu_publish_content(p, v) \ | typeof(*p) _________pv = (v); | |||
rcu_publish_content_sym((void **)(p), (v)) | \ | |||
typeof(*p) _________p1 = | ||||
extern void *rcu_assign_pointer_sym(void **p, void *v); | \ | |||
rcu_set_pointer_sym((void **)(p), _________pv); | ||||
\ | ||||
}) | ||||
#endif /* !_LGPL_SOURCE */ | #endif /* !_LGPL_SOURCE */ | |||
/* | /* | |||
* rcu_assign_pointer(type *ptr, type *new) | * rcu_assign_pointer(type *ptr, type *new) | |||
* | * | |||
* Same as rcu_set_pointer, but takes the pointer to assign to rather than its | * Same as rcu_set_pointer, but takes the pointer to assign to rather than its | |||
* address as first parameter. Provided for compatibility with the Linux ke rnel | * address as first parameter. Provided for compatibility with the Linux ke rnel | |||
* RCU semantic. | * RCU semantic. | |||
*/ | */ | |||
End of changes. 5 change blocks. | ||||
27 lines changed or deleted | 53 lines changed or added | |||