xref: /freebsd-src/sys/compat/linuxkpi/common/include/linux/rcupdate.h (revision 5c92f84bb607c692ce4fa762a7a3c4b86a2fa281)
1e10c4cc0SHans Petter Selasky /*-
21a01b4e5SHans Petter Selasky  * Copyright (c) 2016-2017 Mellanox Technologies, Ltd.
3e10c4cc0SHans Petter Selasky  * All rights reserved.
4*5c92f84bSBjoern A. Zeeb  * Copyright (c) 2024 The FreeBSD Foundation
5*5c92f84bSBjoern A. Zeeb  *
6*5c92f84bSBjoern A. Zeeb  * Portions of this software were developed by Björn Zeeb
7*5c92f84bSBjoern A. Zeeb  * under sponsorship from the FreeBSD Foundation.
8e10c4cc0SHans Petter Selasky  *
9e10c4cc0SHans Petter Selasky  * Redistribution and use in source and binary forms, with or without
10e10c4cc0SHans Petter Selasky  * modification, are permitted provided that the following conditions
11e10c4cc0SHans Petter Selasky  * are met:
12e10c4cc0SHans Petter Selasky  * 1. Redistributions of source code must retain the above copyright
13e10c4cc0SHans Petter Selasky  *    notice unmodified, this list of conditions, and the following
14e10c4cc0SHans Petter Selasky  *    disclaimer.
15e10c4cc0SHans Petter Selasky  * 2. Redistributions in binary form must reproduce the above copyright
16e10c4cc0SHans Petter Selasky  *    notice, this list of conditions and the following disclaimer in the
17e10c4cc0SHans Petter Selasky  *    documentation and/or other materials provided with the distribution.
18e10c4cc0SHans Petter Selasky  *
19e10c4cc0SHans Petter Selasky  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20e10c4cc0SHans Petter Selasky  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21e10c4cc0SHans Petter Selasky  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22e10c4cc0SHans Petter Selasky  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23e10c4cc0SHans Petter Selasky  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24e10c4cc0SHans Petter Selasky  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25e10c4cc0SHans Petter Selasky  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26e10c4cc0SHans Petter Selasky  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27e10c4cc0SHans Petter Selasky  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28e10c4cc0SHans Petter Selasky  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29e10c4cc0SHans Petter Selasky  */
30307f78f3SVladimir Kondratyev #ifndef	_LINUXKPI_LINUX_RCUPDATE_H_
31307f78f3SVladimir Kondratyev #define	_LINUXKPI_LINUX_RCUPDATE_H_
32e10c4cc0SHans Petter Selasky 
33*5c92f84bSBjoern A. Zeeb #include <sys/cdefs.h>
34*5c92f84bSBjoern A. Zeeb 
351a01b4e5SHans Petter Selasky #include <linux/compiler.h>
361a01b4e5SHans Petter Selasky #include <linux/types.h>
37*5c92f84bSBjoern A. Zeeb #include <linux/kernel.h>
38e10c4cc0SHans Petter Selasky 
391a01b4e5SHans Petter Selasky #include <machine/atomic.h>
40e10c4cc0SHans Petter Selasky 
41*5c92f84bSBjoern A. Zeeb extern int linuxkpi_rcu_debug;
42*5c92f84bSBjoern A. Zeeb #define	RCU_WARN_ONCE(c, ...)	do {					\
43*5c92f84bSBjoern A. Zeeb 	if (unlikely(linuxkpi_rcu_debug > 0))				\
44*5c92f84bSBjoern A. Zeeb 		WARN_ONCE((c), ##__VA_ARGS__);				\
45*5c92f84bSBjoern A. Zeeb } while(0)
46*5c92f84bSBjoern A. Zeeb 
471a01b4e5SHans Petter Selasky #define	LINUX_KFREE_RCU_OFFSET_MAX	4096	/* exclusive */
48e10c4cc0SHans Petter Selasky 
49eae5868cSHans Petter Selasky /* BSD specific defines */
50eae5868cSHans Petter Selasky #define	RCU_TYPE_REGULAR 0
51eae5868cSHans Petter Selasky #define	RCU_TYPE_SLEEPABLE 1
52eae5868cSHans Petter Selasky #define	RCU_TYPE_MAX 2
53eae5868cSHans Petter Selasky 
541a01b4e5SHans Petter Selasky #define	RCU_INITIALIZER(v)			\
55a1be2eadSHans Petter Selasky 	((__typeof(*(v)) *)(v))
56e10c4cc0SHans Petter Selasky 
571a01b4e5SHans Petter Selasky #define	RCU_INIT_POINTER(p, v) do {		\
581a01b4e5SHans Petter Selasky 	(p) = (v);				\
59c7c96d10SHans Petter Selasky } while (0)
60c7c96d10SHans Petter Selasky 
611a01b4e5SHans Petter Selasky #define	call_rcu(ptr, func) do {		\
62eae5868cSHans Petter Selasky 	linux_call_rcu(RCU_TYPE_REGULAR, ptr, func);	\
63c7c96d10SHans Petter Selasky } while (0)
64c7c96d10SHans Petter Selasky 
651a01b4e5SHans Petter Selasky #define	rcu_barrier(void) do {			\
66eae5868cSHans Petter Selasky 	linux_rcu_barrier(RCU_TYPE_REGULAR);	\
67c7c96d10SHans Petter Selasky } while (0)
68c7c96d10SHans Petter Selasky 
691a01b4e5SHans Petter Selasky #define	rcu_read_lock(void) do {		\
70eae5868cSHans Petter Selasky 	linux_rcu_read_lock(RCU_TYPE_REGULAR);	\
711a01b4e5SHans Petter Selasky } while (0)
721a01b4e5SHans Petter Selasky 
731a01b4e5SHans Petter Selasky #define	rcu_read_unlock(void) do {		\
74eae5868cSHans Petter Selasky 	linux_rcu_read_unlock(RCU_TYPE_REGULAR);\
751a01b4e5SHans Petter Selasky } while (0)
761a01b4e5SHans Petter Selasky 
77*5c92f84bSBjoern A. Zeeb #define	rcu_read_lock_held(void)					\
78*5c92f84bSBjoern A. Zeeb 	linux_rcu_read_lock_held(RCU_TYPE_REGULAR)
79*5c92f84bSBjoern A. Zeeb 
801a01b4e5SHans Petter Selasky #define	synchronize_rcu(void) do {	\
81eae5868cSHans Petter Selasky 	linux_synchronize_rcu(RCU_TYPE_REGULAR);	\
821a01b4e5SHans Petter Selasky } while (0)
831a01b4e5SHans Petter Selasky 
841a01b4e5SHans Petter Selasky #define	synchronize_rcu_expedited(void) do {	\
85eae5868cSHans Petter Selasky 	linux_synchronize_rcu(RCU_TYPE_REGULAR);	\
861a01b4e5SHans Petter Selasky } while (0)
871a01b4e5SHans Petter Selasky 
881a01b4e5SHans Petter Selasky #define	kfree_rcu(ptr, rcu_head) do {				\
891a01b4e5SHans Petter Selasky 	CTASSERT(offsetof(__typeof(*(ptr)), rcu_head) <		\
901a01b4e5SHans Petter Selasky 	    LINUX_KFREE_RCU_OFFSET_MAX);			\
911a01b4e5SHans Petter Selasky 	call_rcu(&(ptr)->rcu_head, (rcu_callback_t)(uintptr_t)	\
921a01b4e5SHans Petter Selasky 	    offsetof(__typeof(*(ptr)), rcu_head));		\
931a01b4e5SHans Petter Selasky } while (0)
941a01b4e5SHans Petter Selasky 
951a01b4e5SHans Petter Selasky #define	rcu_access_pointer(p)			\
960597ffb0SHans Petter Selasky 	((__typeof(*p) *)READ_ONCE(p))
971a01b4e5SHans Petter Selasky 
98*5c92f84bSBjoern A. Zeeb #define	rcu_dereference(p)			\
990597ffb0SHans Petter Selasky 	((__typeof(*p) *)READ_ONCE(p))
1001a01b4e5SHans Petter Selasky 
101*5c92f84bSBjoern A. Zeeb #define	__rcu_var_name(n, f, l)						\
102*5c92f84bSBjoern A. Zeeb 	__CONCAT(__CONCAT(__CONCAT(rcu_, n), _), __COUNTER__)
103*5c92f84bSBjoern A. Zeeb 
104*5c92f84bSBjoern A. Zeeb #define	__rcu_dereference_protected(p, c, n)				\
105*5c92f84bSBjoern A. Zeeb ({									\
106*5c92f84bSBjoern A. Zeeb     RCU_WARN_ONCE(!(c), "%s:%d: condition for %s failed\n",		\
107*5c92f84bSBjoern A. Zeeb 	__func__, __LINE__, __XSTRING(n));				\
108*5c92f84bSBjoern A. Zeeb     rcu_dereference(p);							\
109*5c92f84bSBjoern A. Zeeb })
110*5c92f84bSBjoern A. Zeeb 
111*5c92f84bSBjoern A. Zeeb #define	rcu_dereference_protected(p, c)					\
112*5c92f84bSBjoern A. Zeeb     __rcu_dereference_protected((p), (c),				\
113*5c92f84bSBjoern A. Zeeb 	__rcu_var_name(protected, __func__, __LINE__))
114*5c92f84bSBjoern A. Zeeb 
115*5c92f84bSBjoern A. Zeeb #define	__rcu_dereference_check(p, c, n)				\
116*5c92f84bSBjoern A. Zeeb ({									\
117*5c92f84bSBjoern A. Zeeb     __typeof(*p) *n = rcu_dereference(p);				\
118*5c92f84bSBjoern A. Zeeb     RCU_WARN_ONCE(!(c), "%s:%d: condition for %s failed\n",		\
119*5c92f84bSBjoern A. Zeeb 	__func__, __LINE__, __XSTRING(n));				\
120*5c92f84bSBjoern A. Zeeb     n;									\
121*5c92f84bSBjoern A. Zeeb })
1221a01b4e5SHans Petter Selasky 
123fa58da02SBjoern A. Zeeb #define	rcu_dereference_check(p, c)					\
124*5c92f84bSBjoern A. Zeeb     __rcu_dereference_check((p), (c) || rcu_read_lock_held(),		\
125*5c92f84bSBjoern A. Zeeb 	__rcu_var_name(check, __func__, __LINE__))
126fa58da02SBjoern A. Zeeb 
1270597ffb0SHans Petter Selasky #define	rcu_dereference_raw(p)			\
1280597ffb0SHans Petter Selasky 	((__typeof(*p) *)READ_ONCE(p))
1290597ffb0SHans Petter Selasky 
1301a01b4e5SHans Petter Selasky #define	rcu_pointer_handoff(p) (p)
1311a01b4e5SHans Petter Selasky 
1321a01b4e5SHans Petter Selasky #define	rcu_assign_pointer(p, v) do {				\
1331a01b4e5SHans Petter Selasky 	atomic_store_rel_ptr((volatile uintptr_t *)&(p),	\
1341a01b4e5SHans Petter Selasky 	    (uintptr_t)(v));					\
1351a01b4e5SHans Petter Selasky } while (0)
1361a01b4e5SHans Petter Selasky 
137efe7f12cSNeel Chauhan #define	rcu_replace_pointer(rcu, ptr, c)			\
138efe7f12cSNeel Chauhan ({								\
139efe7f12cSNeel Chauhan 	typeof(ptr) __tmp = rcu_dereference_protected(rcu, c);	\
140efe7f12cSNeel Chauhan 	rcu_assign_pointer(rcu, ptr);				\
141efe7f12cSNeel Chauhan 	__tmp;							\
142efe7f12cSNeel Chauhan })
143efe7f12cSNeel Chauhan 
1449b703f30SEmmanuel Vadot #define	rcu_swap_protected(rcu, ptr, c) do {			\
1459b703f30SEmmanuel Vadot 	typeof(ptr) p = rcu_dereference_protected(rcu, c);	\
1469b703f30SEmmanuel Vadot 	rcu_assign_pointer(rcu, ptr);				\
1479b703f30SEmmanuel Vadot 	(ptr) = p;						\
1489b703f30SEmmanuel Vadot } while (0)
1499b703f30SEmmanuel Vadot 
1501a01b4e5SHans Petter Selasky /* prototypes */
1511a01b4e5SHans Petter Selasky 
152*5c92f84bSBjoern A. Zeeb void linux_call_rcu(unsigned type, struct rcu_head *ptr, rcu_callback_t func);
153*5c92f84bSBjoern A. Zeeb void linux_rcu_barrier(unsigned type);
154*5c92f84bSBjoern A. Zeeb void linux_rcu_read_lock(unsigned type);
155*5c92f84bSBjoern A. Zeeb void linux_rcu_read_unlock(unsigned type);
156*5c92f84bSBjoern A. Zeeb bool linux_rcu_read_lock_held(unsigned);
157*5c92f84bSBjoern A. Zeeb void linux_synchronize_rcu(unsigned type);
1581a01b4e5SHans Petter Selasky 
159856b815dSHans Petter Selasky /* Empty implementation for !DEBUG */
160856b815dSHans Petter Selasky #define	init_rcu_head(...)
161856b815dSHans Petter Selasky #define	destroy_rcu_head(...)
162856b815dSHans Petter Selasky #define	init_rcu_head_on_stack(...)
163856b815dSHans Petter Selasky #define	destroy_rcu_head_on_stack(...)
164856b815dSHans Petter Selasky 
165307f78f3SVladimir Kondratyev #endif					/* _LINUXKPI_LINUX_RCUPDATE_H_ */
166