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 #ifndef SURICATA_UTIL_ATOMIC_H
34 #define SURICATA_UTIL_ATOMIC_H
35 
36 #if HAVE_STDATOMIC_H==1
37 
38 #include <stdatomic.h>
39 
40 #define SC_ATOMIC_MEMORY_ORDER_RELAXED memory_order_relaxed
41 #define SC_ATOMIC_MEMORY_ORDER_CONSUME memory_order_consume
42 #define SC_ATOMIC_MEMORY_ORDER_ACQUIRE memory_order_acquire
43 #define SC_ATOMIC_MEMORY_ORDER_RELEASE memory_order_release
44 #define SC_ATOMIC_MEMORY_ORDER_ACQ_REL memory_order_acq_rel
45 #define SC_ATOMIC_MEMORY_ORDER_SEQ_CST memory_order_seq_cst
46 
47 /**
48  * \brief wrapper for declaring atomic variables.
49  *
50  * \param type Type of the variable (char, short, int, long, long long)
51  * \param name Name of the variable.
52  *
53  * We just declare the variable here as we rely on atomic operations
54  * to modify it, so no need for locks.
55  *
56  * \warning variable is not initialized
57  */
58 #define SC_ATOMIC_DECLARE(type, name) \
59  _Atomic(type) name ## _sc_atomic__
60 
61 /**
62  * \brief wrapper for referencing an atomic variable declared on another file.
63  *
64  * \param type Type of the variable (char, short, int, long, long long)
65  * \param name Name of the variable.
66  *
67  * We just declare the variable here as we rely on atomic operations
68  * to modify it, so no need for locks.
69  *
70  */
71 #define SC_ATOMIC_EXTERN(type, name) \
72  extern _Atomic(type) (name ## _sc_atomic__)
73 
74 /**
75  * \brief wrapper for declaring an atomic variable and initializing it.
76  **/
77 #define SC_ATOMIC_DECL_AND_INIT(type, name) \
78  _Atomic(type) (name ## _sc_atomic__) = 0
79 
80 /**
81  * \brief wrapper for declaring an atomic variable and initializing it
82  * to a specific value
83  **/
84 #define SC_ATOMIC_DECL_AND_INIT_WITH_VAL(type, name, val) _Atomic(type)(name##_sc_atomic__) = val
85 
86 /**
87  * \brief wrapper for initializing an atomic variable.
88  **/
89 #define SC_ATOMIC_INIT(name) \
90  (name ## _sc_atomic__) = 0
91 #define SC_ATOMIC_INITPTR(name) \
92  (name ## _sc_atomic__) = NULL
93 
94 /**
95  * \brief wrapper for reinitializing an atomic variable.
96  **/
97 #define SC_ATOMIC_RESET(name) \
98  SC_ATOMIC_INIT(name)
99 
100 /**
101  * \brief add a value to our atomic variable
102  *
103  * \param name the atomic variable
104  * \param val the value to add to the variable
105  */
106 #define SC_ATOMIC_ADD(name, val) \
107  atomic_fetch_add(&(name ## _sc_atomic__), (val))
108 
109 /**
110  * \brief sub a value from our atomic variable
111  *
112  * \param name the atomic variable
113  * \param val the value to sub from the variable
114  */
115 #define SC_ATOMIC_SUB(name, val) \
116  atomic_fetch_sub(&(name ## _sc_atomic__), (val))
117 
118 /**
119  * \brief Bitwise OR a value to our atomic variable
120  *
121  * \param name the atomic variable
122  * \param val the value to OR to the variable
123  */
124 #define SC_ATOMIC_OR(name, val) \
125  atomic_fetch_or(&(name ## _sc_atomic__), (val))
126 
127 /**
128  * \brief Bitwise AND a value to our atomic variable
129  *
130  * \param name the atomic variable
131  * \param val the value to AND to the variable
132  */
133 #define SC_ATOMIC_AND(name, val) \
134  atomic_fetch_and(&(name ## _sc_atomic__), (val))
135 
136 /**
137  * \brief atomic Compare and Switch
138  *
139  * \warning "name" is passed to us as "&var"
140  */
141 #define SC_ATOMIC_CAS(name, cmpval, newval) \
142  atomic_compare_exchange_strong((name ## _sc_atomic__), &(cmpval), (newval))
143 
144 /**
145  * \brief Get the value from the atomic variable.
146  *
147  * \retval var value
148  */
149 #define SC_ATOMIC_GET(name) \
150  atomic_load(&(name ## _sc_atomic__))
151 
152 #define SC_ATOMIC_LOAD_EXPLICIT(name, order) \
153  atomic_load_explicit(&(name ## _sc_atomic__), (order))
154 
155 /**
156  * \brief Set the value for the atomic variable.
157  *
158  * \retval var value
159  */
160 #define SC_ATOMIC_SET(name, val) \
161  atomic_store(&(name ## _sc_atomic__), (val))
162 
163 #else
164 
165 #define SC_ATOMIC_MEMORY_ORDER_RELAXED
166 #define SC_ATOMIC_MEMORY_ORDER_CONSUME
167 #define SC_ATOMIC_MEMORY_ORDER_ACQUIRE
168 #define SC_ATOMIC_MEMORY_ORDER_RELEASE
169 #define SC_ATOMIC_MEMORY_ORDER_ACQ_REL
170 #define SC_ATOMIC_MEMORY_ORDER_SEQ_CST
171 
172 /**
173  * \brief wrapper for OS/compiler specific atomic compare and swap (CAS)
174  * function.
175  *
176  * \param addr Address of the variable to CAS
177  * \param tv Test value to compare the value at address against
178  * \param nv New value to set the variable at addr to
179  *
180  * \retval 0 CAS failed
181  * \retval 1 CAS succeeded
182  */
183 #define SCAtomicCompareAndSwap(addr, tv, nv) \
184  __sync_bool_compare_and_swap((addr), (tv), (nv))
185 
186 /**
187  * \brief wrapper for OS/compiler specific atomic fetch and add
188  * function.
189  *
190  * \param addr Address of the variable to add to
191  * \param value Value to add to the variable at addr
192  */
193 #define SCAtomicFetchAndAdd(addr, value) \
194  __sync_fetch_and_add((addr), (value))
195 
196 /**
197  * \brief wrapper for OS/compiler specific atomic fetch and sub
198  * function.
199  *
200  * \param addr Address of the variable to add to
201  * \param value Value to sub from the variable at addr
202  */
203 #define SCAtomicFetchAndSub(addr, value) \
204  __sync_fetch_and_sub((addr), (value))
205 
206 /**
207  * \brief wrapper for OS/compiler specific atomic fetch and add
208  * function.
209  *
210  * \param addr Address of the variable to add to
211  * \param value Value to add to the variable at addr
212  */
213 #define SCAtomicAddAndFetch(addr, value) \
214  __sync_add_and_fetch((addr), (value))
215 
216 /**
217  * \brief wrapper for OS/compiler specific atomic fetch and sub
218  * function.
219  *
220  * \param addr Address of the variable to add to
221  * \param value Value to sub from the variable at addr
222  */
223 #define SCAtomicSubAndFetch(addr, value) \
224  __sync_sub_and_fetch((addr), (value))
225 
226 /**
227  * \brief wrapper for OS/compiler specific atomic fetch and "AND"
228  * function.
229  *
230  * \param addr Address of the variable to AND to
231  * \param value Value to add to the variable at addr
232  */
233 #define SCAtomicFetchAndAnd(addr, value) \
234  __sync_fetch_and_and((addr), (value))
235 
236 /**
237  * \brief wrapper for OS/compiler specific atomic fetch and "NAND"
238  * function.
239  *
240  * \param addr Address of the variable to NAND to
241  * \param value Value to add to the variable at addr
242  */
243 #define SCAtomicFetchAndNand(addr, value) \
244  __sync_fetch_and_nand((addr), (value))
245 
246 /**
247  * \brief wrapper for OS/compiler specific atomic fetch and "XOR"
248  * function.
249  *
250  * \param addr Address of the variable to XOR to
251  * \param value Value to add to the variable at addr
252  */
253 #define SCAtomicFetchAndXor(addr, value) \
254  __sync_fetch_and_xor((addr), (value))
255 
256 /**
257  * \brief wrapper for OS/compiler specific atomic fetch and or
258  * function.
259  *
260  * \param addr Address of the variable to or to
261  * \param value Value to add to the variable at addr
262  */
263 #define SCAtomicFetchAndOr(addr, value) \
264  __sync_fetch_and_or((addr), (value))
265 
266 /**
267  * \brief wrapper for declaring atomic variables.
268  *
269  * \warning Only char, short, int, long, long long and their unsigned
270  * versions are supported.
271  *
272  * \param type Type of the variable (char, short, int, long, long long)
273  * \param name Name of the variable.
274  *
275  * We just declare the variable here as we rely on atomic operations
276  * to modify it, so no need for locks.
277  *
278  * \warning variable is not initialized
279  */
280 #define SC_ATOMIC_DECLARE(type, name) \
281  type name ## _sc_atomic__
282 
283 /**
284  * \brief wrapper for referencing an atomic variable declared on another file.
285  *
286  * \warning Only char, short, int, long, long long and their unsigned
287  * versions are supported.
288  *
289  * \param type Type of the variable (char, short, int, long, long long)
290  * \param name Name of the variable.
291  *
292  * We just declare the variable here as we rely on atomic operations
293  * to modify it, so no need for locks.
294  *
295  */
296 #define SC_ATOMIC_EXTERN(type, name) \
297  extern type name ## _sc_atomic__
298 
299 /**
300  * \brief wrapper for declaring an atomic variable and initializing it
301  * to a specific value
302  **/
303 #define SC_ATOMIC_DECL_AND_INIT_WITH_VAL(type, name, val) type name##_sc_atomic__ = val
304 
305 /**
306  * \brief wrapper for declaring an atomic variable and initializing it.
307  **/
308 #define SC_ATOMIC_DECL_AND_INIT(type, name) \
309  type name ## _sc_atomic__ = 0
310 
311 /**
312  * \brief wrapper for initializing an atomic variable.
313  **/
314 #define SC_ATOMIC_INIT(name) \
315  (name ## _sc_atomic__) = 0
316 
317 #define SC_ATOMIC_INITPTR(name) \
318  (name ## _sc_atomic__) = NULL
319 
320 /**
321  * \brief wrapper for reinitializing an atomic variable.
322  **/
323 #define SC_ATOMIC_RESET(name) \
324  (name ## _sc_atomic__) = 0
325 
326 /**
327  * \brief add a value to our atomic variable
328  *
329  * \param name the atomic variable
330  * \param val the value to add to the variable
331  */
332 #define SC_ATOMIC_ADD(name, val) \
333  SCAtomicFetchAndAdd(&(name ## _sc_atomic__), (val))
334 
335 /**
336  * \brief sub a value from our atomic variable
337  *
338  * \param name the atomic variable
339  * \param val the value to sub from the variable
340  */
341 #define SC_ATOMIC_SUB(name, val) \
342  SCAtomicFetchAndSub(&(name ## _sc_atomic__), (val))
343 
344 /**
345  * \brief Bitwise OR a value to our atomic variable
346  *
347  * \param name the atomic variable
348  * \param val the value to OR to the variable
349  */
350 #define SC_ATOMIC_OR(name, val) \
351  SCAtomicFetchAndOr(&(name ## _sc_atomic__), (val))
352 
353 /**
354  * \brief Bitwise AND a value to our atomic variable
355  *
356  * \param name the atomic variable
357  * \param val the value to AND to the variable
358  */
359 #define SC_ATOMIC_AND(name, val) \
360  SCAtomicFetchAndAnd(&(name ## _sc_atomic__), (val))
361 
362 /**
363  * \brief atomic Compare and Switch
364  *
365  * \warning "name" is passed to us as "&var"
366  */
367 #define SC_ATOMIC_CAS(name, cmpval, newval) \
368  SCAtomicCompareAndSwap((name ## _sc_atomic__), cmpval, newval)
369 
370 /**
371  * \brief Get the value from the atomic variable.
372  *
373  * \retval var value
374  */
375 #define SC_ATOMIC_GET(name) \
376  (name ## _sc_atomic__)
377 
378 #define SC_ATOMIC_LOAD_EXPLICIT(name, order) \
379  (name ## _sc_atomic__)
380 
381 /**
382  * \brief Set the value for the atomic variable.
383  *
384  * \retval var value
385  */
386 #define SC_ATOMIC_SET(name, val) ({ \
387  while (SC_ATOMIC_CAS(&name, SC_ATOMIC_GET(name), val) == 0) \
388  ; \
389  })
390 
391 #endif /* no c11 atomics */
392 
393 void SCAtomicRegisterTests(void);
394 
395 #endif /* SURICATA_UTIL_ATOMIC_H */
SCAtomicRegisterTests
void SCAtomicRegisterTests(void)
Definition: util-atomic.c:67