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
src
util-atomic.h
Generated on Wed Nov 20 2024 23:30:38 for suricata by
1.8.18