blob: 0bbfd615eee894fde922803644ad5b00eee73767 [file] [log] [blame]
#ifndef __BACKPORT_LINUX_RCUPDATE_H
#define __BACKPORT_LINUX_RCUPDATE_H
#include_next <linux/rcupdate.h>
/*
* This adds a nested function everywhere kfree_rcu() was called. This
* function frees the memory and is given as a function to call_rcu().
* The rcu callback could happen every time also after the module was
* unloaded and this will cause problems. To address that problem, we
* put rcu_barrier() into each module_exit() in module.h.
*/
#if !defined(kfree_rcu)
#define kfree_rcu(data, rcuhead) do { \
void __kfree_rcu_fn(struct rcu_head *rcu_head) \
{ \
void *___ptr; \
___ptr = container_of(rcu_head, typeof(*(data)), rcuhead);\
kfree(___ptr); \
} \
call_rcu(&(data)->rcuhead, __kfree_rcu_fn); \
} while (0)
#endif
#ifndef RCU_INIT_POINTER
#define RCU_INIT_POINTER(p, v) \
p = (typeof(*v) __force __rcu *)(v)
#endif
#ifndef rcu_dereference_check
#define rcu_dereference_check(p, c) rcu_dereference(p)
#endif
#ifndef rcu_dereference_protected
#define rcu_dereference_protected(p, c) (p)
#endif
#ifndef rcu_access_pointer
#define rcu_access_pointer(p) ACCESS_ONCE(p)
#endif
#ifndef rcu_dereference_raw
#define rcu_dereference_raw(p) rcu_dereference(p)
#endif
#if LINUX_VERSION_IS_LESS(4,20,0)
typedef void (*rcu_callback_t)(struct rcu_head *head);
static inline void rcu_head_init(struct rcu_head *rhp)
{
rhp->func = (rcu_callback_t)~0L;
}
static inline bool
rcu_head_after_call_rcu(struct rcu_head *rhp, rcu_callback_t f)
{
if (READ_ONCE(rhp->func) == f)
return true;
WARN_ON_ONCE(READ_ONCE(rhp->func) != (rcu_callback_t)~0L);
return false;
}
#endif /* < 4.20 */
#ifndef rcu_swap_protected
/**
* rcu_swap_protected() - swap an RCU and a regular pointer
* @rcu_ptr: RCU pointer
* @ptr: regular pointer
* @c: the conditions under which the dereference will take place
*
* Perform swap(@rcu_ptr, @ptr) where @rcu_ptr is an RCU-annotated pointer and
* @c is the argument that is passed to the rcu_dereference_protected() call
* used to read that pointer.
*/
#define rcu_swap_protected(rcu_ptr, ptr, c) do { \
typeof(ptr) __tmp = rcu_dereference_protected((rcu_ptr), (c)); \
rcu_assign_pointer((rcu_ptr), (ptr)); \
(ptr) = __tmp; \
} while (0)
#endif
#ifndef rcu_replace_pointer
/**
* rcu_replace_pointer() - replace an RCU pointer, returning its old value
* @rcu_ptr: RCU pointer, whose old value is returned
* @ptr: regular pointer
* @c: the lockdep conditions under which the dereference will take place
*
* Perform a replacement, where @rcu_ptr is an RCU-annotated
* pointer and @c is the lockdep argument that is passed to the
* rcu_dereference_protected() call used to read that pointer. The old
* value of @rcu_ptr is returned, and @rcu_ptr is set to @ptr.
*/
#define rcu_replace_pointer(rcu_ptr, ptr, c) \
({ \
typeof(ptr) __tmp = rcu_dereference_protected((rcu_ptr), (c)); \
rcu_assign_pointer((rcu_ptr), (ptr)); \
__tmp; \
})
#endif
#endif /* __BACKPORT_LINUX_RCUPDATE_H */