suricata
util-atomic.h
Go to the documentation of this file.
1 /* Copyright (C) 2007-2020 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  * \author Pablo Rincon <pablo.rincon.crespo@gmail.com>
23  *
24  * API for atomic operations. Uses C11 atomic instructions
25  * where available, GCC/clang specific (gnu99) operations otherwise.
26  *
27  * To prevent developers from accidentally working with the atomic variables
28  * directly instead of through the proper macro's, a marco trick is performed
29  * that exposes different variable names than the developer uses. So if the dev
30  * uses "somevar", internally "somevar_sc_atomic__" is used.
31  */
32 
33 
34 #ifndef __UTIL_ATOMIC_H__
35 #define __UTIL_ATOMIC_H__
36 
37 #if HAVE_STDATOMIC_H==1
38 
39 #include <stdatomic.h>
40 
41 #define SC_ATOMIC_MEMORY_ORDER_RELAXED memory_order_relaxed
42 #define SC_ATOMIC_MEMORY_ORDER_CONSUME memory_order_consume
43 #define SC_ATOMIC_MEMORY_ORDER_ACQUIRE memory_order_acquire
44 #define SC_ATOMIC_MEMORY_ORDER_RELEASE memory_order_release
45 #define SC_ATOMIC_MEMORY_ORDER_ACQ_REL memory_order_acq_rel
46 #define SC_ATOMIC_MEMORY_ORDER_SEQ_CST memory_order_seq_cst
47 
48 /**
49  * \brief wrapper for declaring atomic variables.
50  *
51  * \param type Type of the variable (char, short, int, long, long long)
52  * \param name Name of the variable.
53  *
54  * We just declare the variable here as we rely on atomic operations
55  * to modify it, so no need for locks.
56  *
57  * \warning variable is not initialized
58  */
59 #define SC_ATOMIC_DECLARE(type, name) \
60  _Atomic(type) name ## _sc_atomic__
61 
62 /**
63  * \brief wrapper for referencing an atomic variable declared on another file.
64  *
65  * \param type Type of the variable (char, short, int, long, long long)
66  * \param name Name of the variable.
67  *
68  * We just declare the variable here as we rely on atomic operations
69  * to modify it, so no need for locks.
70  *
71  */
72 #define SC_ATOMIC_EXTERN(type, name) \
73  extern _Atomic(type) (name ## _sc_atomic__)
74 
75 /**
76  * \brief wrapper for declaring an atomic variable and initializing it.
77  **/
78 #define SC_ATOMIC_DECL_AND_INIT(type, name) \
79  _Atomic(type) (name ## _sc_atomic__) = 0
80 
81 /**
82  * \brief wrapper for declaring an atomic variable and initializing it
83  * to a specific value
84  **/
85 #define SC_ATOMIC_DECL_AND_INIT_WITH_VAL(type, name, val) _Atomic(type)(name##_sc_atomic__) = val
86 
87 /**
88  * \brief wrapper for initializing an atomic variable.
89  **/
90 #define SC_ATOMIC_INIT(name) \
91  (name ## _sc_atomic__) = 0
92 #define SC_ATOMIC_INITPTR(name) \
93  (name ## _sc_atomic__) = NULL
94 
95 /**
96  * \brief wrapper for reinitializing an atomic variable.
97  **/
98 #define SC_ATOMIC_RESET(name) \
99  SC_ATOMIC_INIT(name)
100 
101 /**
102  * \brief add a value to our atomic variable
103  *
104  * \param name the atomic variable
105  * \param val the value to add to the variable
106  */
107 #define SC_ATOMIC_ADD(name, val) \
108  atomic_fetch_add(&(name ## _sc_atomic__), (val))
109 
110 /**
111  * \brief sub a value from our atomic variable
112  *
113  * \param name the atomic variable
114  * \param val the value to sub from the variable
115  */
116 #define SC_ATOMIC_SUB(name, val) \
117  atomic_fetch_sub(&(name ## _sc_atomic__), (val))
118 
119 /**
120  * \brief Bitwise OR a value to our atomic variable
121  *
122  * \param name the atomic variable
123  * \param val the value to OR to the variable
124  */
125 #define SC_ATOMIC_OR(name, val) \
126  atomic_fetch_or(&(name ## _sc_atomic__), (val))
127 
128 /**
129  * \brief Bitwise AND a value to our atomic variable
130  *
131  * \param name the atomic variable
132  * \param val the value to AND to the variable
133  */
134 #define SC_ATOMIC_AND(name, val) \
135  atomic_fetch_and(&(name ## _sc_atomic__), (val))
136 
137 /**
138  * \brief atomic Compare and Switch
139  *
140  * \warning "name" is passed to us as "&var"
141  */
142 #define SC_ATOMIC_CAS(name, cmpval, newval) \
143  atomic_compare_exchange_strong((name ## _sc_atomic__), &(cmpval), (newval))
144 
145 /**
146  * \brief Get the value from the atomic variable.
147  *
148  * \retval var value
149  */
150 #define SC_ATOMIC_GET(name) \
151  atomic_load(&(name ## _sc_atomic__))
152 
153 #define SC_ATOMIC_LOAD_EXPLICIT(name, order) \
154  atomic_load_explicit(&(name ## _sc_atomic__), (order))
155 
156 /**
157  * \brief Set the value for the atomic variable.
158  *
159  * \retval var value
160  */
161 #define SC_ATOMIC_SET(name, val) \
162  atomic_store(&(name ## _sc_atomic__), (val))
163 
164 #else
165 
166 #define SC_ATOMIC_MEMORY_ORDER_RELAXED
167 #define SC_ATOMIC_MEMORY_ORDER_CONSUME
168 #define SC_ATOMIC_MEMORY_ORDER_ACQUIRE
169 #define SC_ATOMIC_MEMORY_ORDER_RELEASE
170 #define SC_ATOMIC_MEMORY_ORDER_ACQ_REL
171 #define SC_ATOMIC_MEMORY_ORDER_SEQ_CST
172 
173 /**
174  * \brief wrapper for OS/compiler specific atomic compare and swap (CAS)
175  * function.
176  *
177  * \param addr Address of the variable to CAS
178  * \param tv Test value to compare the value at address against
179  * \param nv New value to set the variable at addr to
180  *
181  * \retval 0 CAS failed
182  * \retval 1 CAS succeeded
183  */
184 #define SCAtomicCompareAndSwap(addr, tv, nv) \
185  __sync_bool_compare_and_swap((addr), (tv), (nv))
186 
187 /**
188  * \brief wrapper for OS/compiler specific atomic fetch and add
189  * function.
190  *
191  * \param addr Address of the variable to add to
192  * \param value Value to add to the variable at addr
193  */
194 #define SCAtomicFetchAndAdd(addr, value) \
195  __sync_fetch_and_add((addr), (value))
196 
197 /**
198  * \brief wrapper for OS/compiler specific atomic fetch and sub
199  * function.
200  *
201  * \param addr Address of the variable to add to
202  * \param value Value to sub from the variable at addr
203  */
204 #define SCAtomicFetchAndSub(addr, value) \
205  __sync_fetch_and_sub((addr), (value))
206 
207 /**
208  * \brief wrapper for OS/compiler specific atomic fetch and add
209  * function.
210  *
211  * \param addr Address of the variable to add to
212  * \param value Value to add to the variable at addr
213  */
214 #define SCAtomicAddAndFetch(addr, value) \
215  __sync_add_and_fetch((addr), (value))
216 
217 /**
218  * \brief wrapper for OS/compiler specific atomic fetch and sub
219  * function.
220  *
221  * \param addr Address of the variable to add to
222  * \param value Value to sub from the variable at addr
223  */
224 #define SCAtomicSubAndFetch(addr, value) \
225  __sync_sub_and_fetch((addr), (value))
226 
227 /**
228  * \brief wrapper for OS/compiler specific atomic fetch and "AND"
229  * function.
230  *
231  * \param addr Address of the variable to AND to
232  * \param value Value to add to the variable at addr
233  */
234 #define SCAtomicFetchAndAnd(addr, value) \
235  __sync_fetch_and_and((addr), (value))
236 
237 /**
238  * \brief wrapper for OS/compiler specific atomic fetch and "NAND"
239  * function.
240  *
241  * \param addr Address of the variable to NAND to
242  * \param value Value to add to the variable at addr
243  */
244 #define SCAtomicFetchAndNand(addr, value) \
245  __sync_fetch_and_nand((addr), (value))
246 
247 /**
248  * \brief wrapper for OS/compiler specific atomic fetch and "XOR"
249  * function.
250  *
251  * \param addr Address of the variable to XOR to
252  * \param value Value to add to the variable at addr
253  */
254 #define SCAtomicFetchAndXor(addr, value) \
255  __sync_fetch_and_xor((addr), (value))
256 
257 /**
258  * \brief wrapper for OS/compiler specific atomic fetch and or
259  * function.
260  *
261  * \param addr Address of the variable to or to
262  * \param value Value to add to the variable at addr
263  */
264 #define SCAtomicFetchAndOr(addr, value) \
265  __sync_fetch_and_or((addr), (value))
266 
267 /**
268  * \brief wrapper for declaring atomic variables.
269  *
270  * \warning Only char, short, int, long, long long and their unsigned
271  * versions are supported.
272  *
273  * \param type Type of the variable (char, short, int, long, long long)
274  * \param name Name of the variable.
275  *
276  * We just declare the variable here as we rely on atomic operations
277  * to modify it, so no need for locks.
278  *
279  * \warning variable is not initialized
280  */
281 #define SC_ATOMIC_DECLARE(type, name) \
282  type name ## _sc_atomic__
283 
284 /**
285  * \brief wrapper for referencing an atomic variable declared on another file.
286  *
287  * \warning Only char, short, int, long, long long and their unsigned
288  * versions are supported.
289  *
290  * \param type Type of the variable (char, short, int, long, long long)
291  * \param name Name of the variable.
292  *
293  * We just declare the variable here as we rely on atomic operations
294  * to modify it, so no need for locks.
295  *
296  */
297 #define SC_ATOMIC_EXTERN(type, name) \
298  extern type name ## _sc_atomic__
299 
300 /**
301  * \brief wrapper for declaring an atomic variable and initializing it
302  * to a specific value
303  **/
304 #define SC_ATOMIC_DECL_AND_INIT_WITH_VAL(type, name, val) type name##_sc_atomic__ = val
305 
306 /**
307  * \brief wrapper for declaring an atomic variable and initializing it.
308  **/
309 #define SC_ATOMIC_DECL_AND_INIT(type, name) \
310  type name ## _sc_atomic__ = 0
311 
312 /**
313  * \brief wrapper for initializing an atomic variable.
314  **/
315 #define SC_ATOMIC_INIT(name) \
316  (name ## _sc_atomic__) = 0
317 
318 #define SC_ATOMIC_INITPTR(name) \
319  (name ## _sc_atomic__) = NULL
320 
321 /**
322  * \brief wrapper for reinitializing an atomic variable.
323  **/
324 #define SC_ATOMIC_RESET(name) \
325  (name ## _sc_atomic__) = 0
326 
327 /**
328  * \brief add a value to our atomic variable
329  *
330  * \param name the atomic variable
331  * \param val the value to add to the variable
332  */
333 #define SC_ATOMIC_ADD(name, val) \
334  SCAtomicFetchAndAdd(&(name ## _sc_atomic__), (val))
335 
336 /**
337  * \brief sub a value from our atomic variable
338  *
339  * \param name the atomic variable
340  * \param val the value to sub from the variable
341  */
342 #define SC_ATOMIC_SUB(name, val) \
343  SCAtomicFetchAndSub(&(name ## _sc_atomic__), (val))
344 
345 /**
346  * \brief Bitwise OR a value to our atomic variable
347  *
348  * \param name the atomic variable
349  * \param val the value to OR to the variable
350  */
351 #define SC_ATOMIC_OR(name, val) \
352  SCAtomicFetchAndOr(&(name ## _sc_atomic__), (val))
353 
354 /**
355  * \brief Bitwise AND a value to our atomic variable
356  *
357  * \param name the atomic variable
358  * \param val the value to AND to the variable
359  */
360 #define SC_ATOMIC_AND(name, val) \
361  SCAtomicFetchAndAnd(&(name ## _sc_atomic__), (val))
362 
363 /**
364  * \brief atomic Compare and Switch
365  *
366  * \warning "name" is passed to us as "&var"
367  */
368 #define SC_ATOMIC_CAS(name, cmpval, newval) \
369  SCAtomicCompareAndSwap((name ## _sc_atomic__), cmpval, newval)
370 
371 /**
372  * \brief Get the value from the atomic variable.
373  *
374  * \retval var value
375  */
376 #define SC_ATOMIC_GET(name) \
377  (name ## _sc_atomic__)
378 
379 #define SC_ATOMIC_LOAD_EXPLICIT(name, order) \
380  (name ## _sc_atomic__)
381 
382 /**
383  * \brief Set the value for the atomic variable.
384  *
385  * \retval var value
386  */
387 #define SC_ATOMIC_SET(name, val) ({ \
388  while (SC_ATOMIC_CAS(&name, SC_ATOMIC_GET(name), val) == 0) \
389  ; \
390  })
391 
392 #endif /* no c11 atomics */
393 
394 void SCAtomicRegisterTests(void);
395 
396 #endif /* __UTIL_ATOMIC_H__ */
397 
SCAtomicRegisterTests
void SCAtomicRegisterTests(void)
Definition: util-atomic.c:67