Home | History | Annotate | Line # | Download | only in urcu
      1 // SPDX-FileCopyrightText: 2009 Mathieu Desnoyers <mathieu.desnoyers (at) efficios.com>
      2 // SPDX-FileCopyrightText: 2009 Paul E. McKenney, IBM Corporation.
      3 //
      4 // SPDX-License-Identifier: LGPL-2.1-or-later
      5 
      6 #ifndef _URCU_POINTER_H
      7 #define _URCU_POINTER_H
      8 
      9 /*
     10  * Userspace RCU header. Operations on pointers.
     11  *
     12  * IBM's contributions to this file may be relicensed under LGPLv2 or later.
     13  */
     14 
     15 #include <urcu/compiler.h>
     16 #include <urcu/arch.h>
     17 #include <urcu/uatomic.h>
     18 
     19 #ifdef __cplusplus
     20 extern "C" {
     21 #endif
     22 
     23 #if defined(_LGPL_SOURCE) || defined(URCU_INLINE_SMALL_FUNCTIONS)
     24 
     25 #include <urcu/static/pointer.h>
     26 
     27 /*
     28  * rcu_dereference(ptr)
     29  *
     30  * Fetch a RCU-protected pointer. Typically used to copy the variable ptr to a
     31  * local variable.
     32  */
     33 #define rcu_dereference		_rcu_dereference
     34 
     35 /*
     36  * type *rcu_cmpxchg_pointer(type **ptr, type *old, type *new)
     37  * type *rcu_xchg_pointer(type **ptr, type *new)
     38  * void rcu_set_pointer(type **ptr, type *new)
     39  *
     40  * RCU pointer updates.
     41  * @ptr: address of the pointer to modify
     42  * @new: new pointer value
     43  * @old: old pointer value (expected)
     44  *
     45  * return: old pointer value
     46  */
     47 #define rcu_cmpxchg_pointer	_rcu_cmpxchg_pointer
     48 #define rcu_xchg_pointer	_rcu_xchg_pointer
     49 #define rcu_set_pointer		_rcu_set_pointer
     50 
     51 #else /* !(defined(_LGPL_SOURCE) || defined(URCU_INLINE_SMALL_FUNCTIONS)) */
     52 
     53 extern void *rcu_dereference_sym(void *p);
     54 #define rcu_dereference(p)						     \
     55 	__extension__							     \
     56 	({								     \
     57 		__typeof__(p) _________p1 =	URCU_FORCE_CAST(__typeof__(p), \
     58 			rcu_dereference_sym(URCU_FORCE_CAST(void *, p)));    \
     59 		(_________p1);						     \
     60 	})
     61 
     62 extern void *rcu_cmpxchg_pointer_sym(void **p, void *old, void *_new);
     63 #define rcu_cmpxchg_pointer(p, old, _new)				     \
     64 	__extension__							     \
     65 	({								     \
     66 		__typeof__(*(p)) _________pold = (old);			     \
     67 		__typeof__(*(p)) _________pnew = (_new);		     \
     68 		__typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*(p)), \
     69 			rcu_cmpxchg_pointer_sym(URCU_FORCE_CAST(void **, p), \
     70 						_________pold,		     \
     71 						_________pnew));	     \
     72 		(_________p1);						     \
     73 	})
     74 
     75 extern void *rcu_xchg_pointer_sym(void **p, void *v);
     76 #define rcu_xchg_pointer(p, v)						     \
     77 	__extension__							     \
     78 	({								     \
     79 		__typeof__(*(p)) _________pv = (v);		             \
     80 		__typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*(p)), \
     81 			rcu_xchg_pointer_sym(URCU_FORCE_CAST(void **, p),    \
     82 					     _________pv));		     \
     83 		(_________p1);						     \
     84 	})
     85 
     86 /*
     87  * Note: rcu_set_pointer_sym returns @v because we don't want to break
     88  * the ABI. At the API level, rcu_set_pointer() now returns void. Use of
     89  * the return value is therefore deprecated, and will cause a build
     90  * error.
     91  */
     92 extern void *rcu_set_pointer_sym(void **p, void *v);
     93 #define rcu_set_pointer(p, v)						     \
     94 	do {								     \
     95 		__typeof__(*(p)) _________pv = (v);		             \
     96 		(void) rcu_set_pointer_sym(URCU_FORCE_CAST(void **, p),	     \
     97 					    _________pv);		     \
     98 	} while (0)
     99 
    100 #endif /* !(defined(_LGPL_SOURCE) || defined(URCU_INLINE_SMALL_FUNCTIONS)) */
    101 
    102 /*
    103  * void rcu_assign_pointer(type *ptr, type *new)
    104  *
    105  * Same as rcu_set_pointer, but takes the pointer to assign to rather than its
    106  * address as first parameter. Provided for compatibility with the Linux kernel
    107  * RCU semantic.
    108  */
    109 #define rcu_assign_pointer(p, v)	rcu_set_pointer((&p), (v))
    110 
    111 #ifdef __cplusplus
    112 }
    113 #endif
    114 
    115 #endif /* _URCU_POINTER_H */
    116