Commit | Line | Data |
---|---|---|
d3d3857f MJ |
1 | // SPDX-FileCopyrightText: 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
2 | // SPDX-FileCopyrightText: 2009 Paul E. McKenney, IBM Corporation. | |
3 | // | |
4 | // SPDX-License-Identifier: LGPL-2.1-or-later | |
5 | ||
fdee2e6d MD |
6 | #ifndef _URCU_BP_H |
7 | #define _URCU_BP_H | |
8 | ||
9 | /* | |
fdee2e6d MD |
10 | * Userspace RCU header, "bulletproof" version. |
11 | * | |
12 | * Slower RCU read-side adapted for tracing library. Does not require thread | |
13 | * registration nor unregistration. Also signal-safe. | |
14 | * | |
fdee2e6d MD |
15 | * LGPL-compatible code should include this header with : |
16 | * | |
17 | * #define _LGPL_SOURCE | |
18 | * #include <urcu.h> | |
19 | * | |
fdee2e6d MD |
20 | * IBM's contributions to this file may be relicensed under LGPLv2 or later. |
21 | */ | |
22 | ||
23 | #include <stdlib.h> | |
24 | #include <pthread.h> | |
111bda8f | 25 | #include <stdbool.h> |
fdee2e6d | 26 | |
ee6fabe1 | 27 | #include <urcu/map/urcu-bp.h> |
5e77fc1f | 28 | |
fdee2e6d MD |
29 | /* |
30 | * Important ! | |
31 | * | |
32 | * Each thread containing read-side critical sections must be registered | |
33 | * with rcu_register_thread() before calling rcu_read_lock(). | |
34 | * rcu_unregister_thread() should be called before the thread exits. | |
35 | */ | |
36 | ||
5efd3cd2 | 37 | /* |
6cd23d47 | 38 | * See urcu/pointer.h and urcu/static/pointer.h for pointer |
5efd3cd2 MD |
39 | * publication headers. |
40 | */ | |
6cd23d47 | 41 | #include <urcu/pointer.h> |
111bda8f | 42 | #include <urcu/urcu-poll.h> |
5efd3cd2 | 43 | |
2ad3cfeb SM |
44 | #ifdef __cplusplus |
45 | extern "C" { | |
46 | #endif | |
47 | ||
fdee2e6d MD |
48 | #ifdef _LGPL_SOURCE |
49 | ||
af7c2dbe | 50 | #include <urcu/static/urcu-bp.h> |
fdee2e6d MD |
51 | |
52 | /* | |
53 | * Mappings for static use of the userspace RCU library. | |
54 | * Should only be used in LGPL-compatible code. | |
55 | */ | |
56 | ||
57 | /* | |
58 | * rcu_read_lock() | |
59 | * rcu_read_unlock() | |
60 | * | |
61 | * Mark the beginning and end of a read-side critical section. | |
62 | */ | |
4477a870 MD |
63 | #define urcu_bp_read_lock _urcu_bp_read_lock |
64 | #define urcu_bp_read_unlock _urcu_bp_read_unlock | |
65 | #define urcu_bp_read_ongoing _urcu_bp_read_ongoing | |
fdee2e6d | 66 | |
4477a870 MD |
67 | #define urcu_bp_dereference rcu_dereference |
68 | #define urcu_bp_cmpxchg_pointer rcu_cmpxchg_pointer | |
69 | #define urcu_bp_xchg_pointer rcu_xchg_pointer | |
70 | #define urcu_bp_set_pointer rcu_set_pointer | |
5efd3cd2 | 71 | |
fdee2e6d MD |
72 | #else /* !_LGPL_SOURCE */ |
73 | ||
74 | /* | |
75 | * library wrappers to be used by non-LGPL compatible source code. | |
6cd23d47 | 76 | * See LGPL-only urcu/static/pointer.h for documentation. |
fdee2e6d MD |
77 | */ |
78 | ||
4477a870 MD |
79 | extern void urcu_bp_read_lock(void); |
80 | extern void urcu_bp_read_unlock(void); | |
81 | extern int urcu_bp_read_ongoing(void); | |
5efd3cd2 | 82 | |
4477a870 MD |
83 | extern void *urcu_bp_dereference_sym(void *p); |
84 | #define urcu_bp_dereference(p) \ | |
1b85da85 | 85 | __extension__ \ |
5efd3cd2 | 86 | ({ \ |
bdffa73a | 87 | __typeof__(p) _________p1 = URCU_FORCE_CAST(__typeof__(p), \ |
4477a870 | 88 | urcu_bp_dereference_sym(URCU_FORCE_CAST(void *, p))); \ |
5efd3cd2 MD |
89 | (_________p1); \ |
90 | }) | |
91 | ||
4477a870 MD |
92 | extern void *urcu_bp_cmpxchg_pointer_sym(void **p, void *old, void *_new); |
93 | #define urcu_bp_cmpxchg_pointer(p, old, _new) \ | |
1b85da85 | 94 | __extension__ \ |
5efd3cd2 | 95 | ({ \ |
bdffa73a MD |
96 | __typeof__(*(p)) _________pold = (old); \ |
97 | __typeof__(*(p)) _________pnew = (_new); \ | |
98 | __typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*(p)), \ | |
4477a870 | 99 | urcu_bp_cmpxchg_pointer_sym(URCU_FORCE_CAST(void **, p), \ |
5efd3cd2 MD |
100 | _________pold, \ |
101 | _________pnew)); \ | |
102 | (_________p1); \ | |
103 | }) | |
104 | ||
4477a870 MD |
105 | extern void *urcu_bp_xchg_pointer_sym(void **p, void *v); |
106 | #define urcu_bp_xchg_pointer(p, v) \ | |
1b85da85 | 107 | __extension__ \ |
5efd3cd2 | 108 | ({ \ |
bdffa73a MD |
109 | __typeof__(*(p)) _________pv = (v); \ |
110 | __typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*(p)),\ | |
4477a870 | 111 | urcu_bp_xchg_pointer_sym(URCU_FORCE_CAST(void **, p), \ |
5efd3cd2 MD |
112 | _________pv)); \ |
113 | (_________p1); \ | |
114 | }) | |
115 | ||
4477a870 MD |
116 | extern void *urcu_bp_set_pointer_sym(void **p, void *v); |
117 | #define urcu_bp_set_pointer(p, v) \ | |
1b85da85 | 118 | __extension__ \ |
5efd3cd2 | 119 | ({ \ |
bdffa73a MD |
120 | __typeof__(*(p)) _________pv = (v); \ |
121 | __typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*(p)), \ | |
4477a870 | 122 | urcu_bp_set_pointer_sym(URCU_FORCE_CAST(void **, p), \ |
5efd3cd2 MD |
123 | _________pv)); \ |
124 | (_________p1); \ | |
125 | }) | |
fdee2e6d MD |
126 | |
127 | #endif /* !_LGPL_SOURCE */ | |
128 | ||
4477a870 | 129 | extern void urcu_bp_synchronize_rcu(void); |
fdee2e6d | 130 | |
111bda8f MD |
131 | /* |
132 | * RCU grace period polling API. | |
133 | */ | |
134 | extern struct urcu_gp_poll_state urcu_bp_start_poll_synchronize_rcu(void); | |
135 | extern bool urcu_bp_poll_state_synchronize_rcu(struct urcu_gp_poll_state state); | |
136 | ||
4cf1675f | 137 | /* |
4477a870 | 138 | * urcu_bp_before_fork, urcu_bp_after_fork_parent and urcu_bp_after_fork_child |
4cf1675f MD |
139 | * should be called around fork() system calls when the child process is not |
140 | * expected to immediately perform an exec(). For pthread users, see | |
141 | * pthread_atfork(3). | |
142 | */ | |
4477a870 MD |
143 | extern void urcu_bp_before_fork(void); |
144 | extern void urcu_bp_after_fork_parent(void); | |
145 | extern void urcu_bp_after_fork_child(void); | |
4cf1675f | 146 | |
fdee2e6d | 147 | /* |
5b46e39d MD |
148 | * In the bulletproof version, thread registration is performed lazily, |
149 | * but it can be forced by issuing an explicit urcu_bp_register_thread(). | |
fdee2e6d | 150 | */ |
5b46e39d | 151 | extern void urcu_bp_register_thread(void); |
fdee2e6d | 152 | |
5b46e39d MD |
153 | /* |
154 | * In the bulletproof version, the following functions are no-ops. | |
155 | */ | |
4477a870 | 156 | static inline void urcu_bp_unregister_thread(void) |
fdee2e6d MD |
157 | { |
158 | } | |
159 | ||
4477a870 | 160 | static inline void urcu_bp_init(void) |
fdee2e6d MD |
161 | { |
162 | } | |
163 | ||
51b03c6f MD |
164 | /* |
165 | * Q.S. reporting are no-ops for these URCU flavors. | |
166 | */ | |
4477a870 | 167 | static inline void urcu_bp_quiescent_state(void) |
51b03c6f MD |
168 | { |
169 | } | |
170 | ||
4477a870 | 171 | static inline void urcu_bp_thread_offline(void) |
51b03c6f MD |
172 | { |
173 | } | |
174 | ||
4477a870 | 175 | static inline void urcu_bp_thread_online(void) |
51b03c6f MD |
176 | { |
177 | } | |
178 | ||
67ecffc0 | 179 | #ifdef __cplusplus |
36bc70a8 MD |
180 | } |
181 | #endif | |
182 | ||
6cd23d47 MD |
183 | #include <urcu/call-rcu.h> |
184 | #include <urcu/defer.h> | |
185 | #include <urcu/flavor.h> | |
5e77fc1f | 186 | |
4477a870 MD |
187 | #ifndef URCU_API_MAP |
188 | #include <urcu/map/clear.h> | |
189 | #endif | |
190 | ||
fdee2e6d | 191 | #endif /* _URCU_BP_H */ |