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
src
util-atomic.h
Generated on Wed May 31 2023 23:30:39 for suricata by
1.8.18