#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 */

#endif /* __BACKPORT_LINUX_RCUPDATE_H */
