rcutils  master
C API providing common utilities and data structures.
stdatomic.h
Go to the documentation of this file.
1 // Copyright 2015 Open Source Robotics Foundation, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 /* This file was taken from:
16  * https://gist.github.com/nhatminhle/5181506
17  * It is a modification of the FreeBSD stdatomic header with some modifications
18  * so that it will work with gcc 4.7+ and Clang 3.1+.
19  * The original FreeBSD header can be found here:
20  * https://github.com/freebsd/freebsd/blob/release/10.2.0/sys/sys/stdatomic.h
21  */
22 
23 // *INDENT-OFF* (disable uncrustify)
24 
25 /**** Start included file. ****/
26 
27 /*
28  * An implementation of C11 stdatomic.h directly borrowed from FreeBSD
29  * (original copyright follows), with minor modifications for
30  * portability to other systems. Works for recent Clang (that
31  * implement the feature c_atomic) and GCC 4.7+; includes
32  * compatibility for GCC below 4.7 but I wouldn't recommend it.
33  *
34  * Caveats and limitations:
35  * - Only the ``_Atomic parentheses'' notation is implemented, while
36  * the ``_Atomic space'' one is not.
37  * - _Atomic types must be typedef'ed, or programs using them will
38  * not type check correctly (incompatible anonymous structure
39  * types).
40  * - Non-scalar _Atomic types would require runtime support for
41  * runtime locking, which, as far as I know, is not currently
42  * available on any system.
43  */
44 
45 /*-
46  * Copyright (c) 2011 Ed Schouten <ed@FreeBSD.org>
47  * David Chisnall <theraven@FreeBSD.org>
48  * All rights reserved.
49  *
50  * Redistribution and use in source and binary forms, with or without
51  * modification, are permitted provided that the following conditions
52  * are met:
53  * 1. Redistributions of source code must retain the above copyright
54  * notice, this list of conditions and the following disclaimer.
55  * 2. Redistributions in binary form must reproduce the above copyright
56  * notice, this list of conditions and the following disclaimer in the
57  * documentation and/or other materials provided with the distribution.
58  *
59  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
60  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
63  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69  * SUCH DAMAGE.
70  *
71  * $FreeBSD: src/include/stdatomic.h,v 1.10.2.2 2012/05/30 19:21:54 theraven Exp $
72  */
73 
74 #ifndef _STDATOMIC_H_ // NOLINT
75 #define _STDATOMIC_H_
76 
77 #ifdef __cplusplus
78 // This will suppress warnings about _Bool not being defined.
79 typedef bool _Bool;
80 #endif
81 
82 #include <stddef.h>
83 #include <stdint.h>
84 
85 #if !defined(__has_feature)
86 #define __has_feature(x) 0
87 #endif
88 #if !defined(__has_builtin)
89 #define __has_builtin(x) 0
90 #endif
91 #if !defined(__GNUC_PREREQ__)
92 #if defined(__GNUC__) && defined(__GNUC_MINOR__)
93 #define __GNUC_PREREQ__(maj, min) \
94  ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
95 #else
96 #define __GNUC_PREREQ__(maj, min) 0
97 #endif
98 #endif
99 
100 #if !defined(__CLANG_ATOMICS) && !defined(__GNUC_ATOMICS)
101 #if __has_feature(c_atomic)
102 #define __CLANG_ATOMICS
103 #elif __GNUC_PREREQ__(4, 7)
104 #define __GNUC_ATOMICS
105 #elif !defined(__GNUC__)
106 #error "stdatomic.h does not support your compiler"
107 #endif
108 #endif
109 
110 #if !defined(__CLANG_ATOMICS)
111 #define _Atomic(T) struct { volatile __typeof__(T) __val; }
112 #endif
113 
114 /*
115  * 7.17.2 Initialization.
116  */
117 
118 #if defined(__CLANG_ATOMICS)
119 #define ATOMIC_VAR_INIT(value) (value)
120 #define atomic_init(obj, value) __c11_atomic_init(obj, value)
121 #else
122 #define ATOMIC_VAR_INIT(value) { .__val = (value) }
123 #define atomic_init(obj, value) do { \
124  (obj)->__val = (value); \
125 } while (0)
126 #endif
127 
128 /*
129  * Clang and recent GCC both provide predefined macros for the memory
130  * orderings. If we are using a compiler that doesn't define them, use the
131  * clang values - these will be ignored in the fallback path.
132  */
133 
134 #ifndef __ATOMIC_RELAXED
135 #define __ATOMIC_RELAXED 0
136 #endif
137 #ifndef __ATOMIC_CONSUME
138 #define __ATOMIC_CONSUME 1
139 #endif
140 #ifndef __ATOMIC_ACQUIRE
141 #define __ATOMIC_ACQUIRE 2
142 #endif
143 #ifndef __ATOMIC_RELEASE
144 #define __ATOMIC_RELEASE 3
145 #endif
146 #ifndef __ATOMIC_ACQ_REL
147 #define __ATOMIC_ACQ_REL 4
148 #endif
149 #ifndef __ATOMIC_SEQ_CST
150 #define __ATOMIC_SEQ_CST 5
151 #endif
152 
153 /*
154  * 7.17.3 Order and consistency.
155  *
156  * The memory_order_* constants that denote the barrier behaviour of the
157  * atomic operations.
158  */
159 
167 };
168 
170 
171 /*
172  * 7.17.4 Fences.
173  */
174 
175 #ifdef __CLANG_ATOMICS
176 #define atomic_thread_fence(order) __c11_atomic_thread_fence(order)
177 #define atomic_signal_fence(order) __c11_atomic_signal_fence(order)
178 #elif defined(__GNUC_ATOMICS)
179 #define atomic_thread_fence(order) __atomic_thread_fence(order)
180 #define atomic_signal_fence(order) __atomic_signal_fence(order)
181 #else
182 #define atomic_thread_fence(order) __sync_synchronize()
183 #define atomic_signal_fence(order) __asm volatile ("" : : : "memory")
184 #endif
185 
186 /*
187  * 7.17.5 Lock-free property.
188  */
189 
190 #if defined(__CLANG_ATOMICS)
191 #define atomic_is_lock_free(obj) \
192  __c11_atomic_is_lock_free(sizeof(obj))
193 #elif defined(__GNUC_ATOMICS)
194 #define atomic_is_lock_free(obj) \
195  __atomic_is_lock_free(sizeof((obj)->__val))
196 #else
197 #define atomic_is_lock_free(obj) \
198  (sizeof((obj)->__val) <= sizeof(void *))
199 #endif
200 
201 /*
202  * 7.17.6 Atomic integer types.
203  */
204 
205 typedef _Atomic(_Bool) atomic_bool;
206 typedef _Atomic(char) atomic_char;
207 typedef _Atomic(signed char) atomic_schar;
208 typedef _Atomic(unsigned char) atomic_uchar;
209 typedef _Atomic(short) atomic_short; // NOLINT
210 typedef _Atomic(unsigned short) atomic_ushort; // NOLINT
211 typedef _Atomic(int) atomic_int;
212 typedef _Atomic(unsigned int) atomic_uint;
213 typedef _Atomic(long) atomic_long; // NOLINT
214 typedef _Atomic(unsigned long) atomic_ulong; // NOLINT
215 typedef _Atomic(long long) atomic_llong; // NOLINT
216 typedef _Atomic(unsigned long long) atomic_ullong; // NOLINT
217 #if 0
218 typedef _Atomic(char16_t) atomic_char16_t;
219 typedef _Atomic(char32_t) atomic_char32_t;
220 #endif
221 typedef _Atomic(wchar_t) atomic_wchar_t;
222 typedef _Atomic(int_least8_t) atomic_int_least8_t;
223 typedef _Atomic(uint_least8_t) atomic_uint_least8_t;
224 typedef _Atomic(int_least16_t) atomic_int_least16_t;
225 typedef _Atomic(uint_least16_t) atomic_uint_least16_t;
226 typedef _Atomic(int_least32_t) atomic_int_least32_t;
227 typedef _Atomic(uint_least32_t) atomic_uint_least32_t;
228 typedef _Atomic(int_least64_t) atomic_int_least64_t;
229 typedef _Atomic(uint_least64_t) atomic_uint_least64_t;
230 typedef _Atomic(int_fast8_t) atomic_int_fast8_t;
231 typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t;
232 typedef _Atomic(int_fast16_t) atomic_int_fast16_t;
233 typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t;
234 typedef _Atomic(int_fast32_t) atomic_int_fast32_t;
235 typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t;
236 typedef _Atomic(int_fast64_t) atomic_int_fast64_t;
237 typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t;
238 typedef _Atomic(intptr_t) atomic_intptr_t;
239 typedef _Atomic(uintptr_t) atomic_uintptr_t;
240 typedef _Atomic(size_t) atomic_size_t;
241 typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
242 typedef _Atomic(intmax_t) atomic_intmax_t;
243 typedef _Atomic(uintmax_t) atomic_uintmax_t;
244 
245 /*
246  * 7.17.7 Operations on atomic types.
247  */
248 
249 /*
250  * Compiler-specific operations.
251  */
252 
253 #if defined(__CLANG_ATOMICS)
254 #define atomic_compare_exchange_strong_explicit(object, expected, \
255  desired, success, failure) \
256  __c11_atomic_compare_exchange_strong(object, expected, desired, \
257  success, failure)
258 #define atomic_compare_exchange_weak_explicit(object, expected, \
259  desired, success, failure) \
260  __c11_atomic_compare_exchange_weak(object, expected, desired, \
261  success, failure)
262 #define atomic_exchange_explicit(object, desired, order) \
263  __c11_atomic_exchange(object, desired, order)
264 #define atomic_fetch_add_explicit(object, operand, order) \
265  __c11_atomic_fetch_add(object, operand, order)
266 #define atomic_fetch_and_explicit(object, operand, order) \
267  __c11_atomic_fetch_and(object, operand, order)
268 #define atomic_fetch_or_explicit(object, operand, order) \
269  __c11_atomic_fetch_or(object, operand, order)
270 #define atomic_fetch_sub_explicit(object, operand, order) \
271  __c11_atomic_fetch_sub(object, operand, order)
272 #define atomic_fetch_xor_explicit(object, operand, order) \
273  __c11_atomic_fetch_xor(object, operand, order)
274 #define atomic_load_explicit(object, order) \
275  __c11_atomic_load(object, order)
276 #define atomic_store_explicit(object, desired, order) \
277  __c11_atomic_store(object, desired, order)
278 #elif defined(__GNUC_ATOMICS)
279 #define atomic_compare_exchange_strong_explicit(object, expected, \
280  desired, success, failure) \
281  __atomic_compare_exchange_n(&(object)->__val, expected, \
282  desired, 0, success, failure)
283 #define atomic_compare_exchange_weak_explicit(object, expected, \
284  desired, success, failure) \
285  __atomic_compare_exchange_n(&(object)->__val, expected, \
286  desired, 1, success, failure)
287 #define atomic_exchange_explicit(object, desired, order) \
288  __atomic_exchange_n(&(object)->__val, desired, order)
289 #define atomic_fetch_add_explicit(object, operand, order) \
290  __atomic_fetch_add(&(object)->__val, operand, order)
291 #define atomic_fetch_and_explicit(object, operand, order) \
292  __atomic_fetch_and(&(object)->__val, operand, order)
293 #define atomic_fetch_or_explicit(object, operand, order) \
294  __atomic_fetch_or(&(object)->__val, operand, order)
295 #define atomic_fetch_sub_explicit(object, operand, order) \
296  __atomic_fetch_sub(&(object)->__val, operand, order)
297 #define atomic_fetch_xor_explicit(object, operand, order) \
298  __atomic_fetch_xor(&(object)->__val, operand, order)
299 #define atomic_load_explicit(object, order) \
300  __atomic_load_n(&(object)->__val, order)
301 #define atomic_store_explicit(object, desired, order) \
302  __atomic_store_n(&(object)->__val, desired, order)
303 #else
304 #define atomic_compare_exchange_strong_explicit(object, expected, \
305  desired, success, failure) ({ \
306  __typeof__((object)->__val) __v; \
307  _Bool __r; \
308  __v = __sync_val_compare_and_swap(&(object)->__val, \
309  *(expected), desired); \
310  __r = *(expected) == __v; \
311  *(expected) = __v; \
312  __r; \
313 })
314 
315 #define atomic_compare_exchange_weak_explicit(object, expected, \
316  desired, success, failure) \
317  atomic_compare_exchange_strong_explicit(object, expected, \
318  desired, success, failure)
319 #if __has_builtin(__sync_swap)
320 /* Clang provides a full-barrier atomic exchange - use it if available. */
321 #define atomic_exchange_explicit(object, desired, order) \
322  __sync_swap(&(object)->__val, desired)
323 #else
324 /*
325  * __sync_lock_test_and_set() is only an acquire barrier in theory (although in
326  * practice it is usually a full barrier) so we need an explicit barrier after
327  * it.
328  */
329 #define atomic_exchange_explicit(object, desired, order) ({ \
330  __typeof__((object)->__val) __v; \
331  __v = __sync_lock_test_and_set(&(object)->__val, desired); \
332  __sync_synchronize(); \
333  __v; \
334 })
335 #endif
336 #define atomic_fetch_add_explicit(object, operand, order) \
337  __sync_fetch_and_add(&(object)->__val, operand)
338 #define atomic_fetch_and_explicit(object, operand, order) \
339  __sync_fetch_and_and(&(object)->__val, operand)
340 #define atomic_fetch_or_explicit(object, operand, order) \
341  __sync_fetch_and_or(&(object)->__val, operand)
342 #define atomic_fetch_sub_explicit(object, operand, order) \
343  __sync_fetch_and_sub(&(object)->__val, operand)
344 #define atomic_fetch_xor_explicit(object, operand, order) \
345  __sync_fetch_and_xor(&(object)->__val, operand)
346 #define atomic_load_explicit(object, order) \
347  __sync_fetch_and_add(&(object)->__val, 0)
348 #define atomic_store_explicit(object, desired, order) do { \
349  __sync_synchronize(); \
350  (object)->__val = (desired); \
351  __sync_synchronize(); \
352 } while (0)
353 #endif
354 
355 /*
356  * Convenience functions.
357  */
358 
359 #define atomic_compare_exchange_strong(object, expected, desired) \
360  atomic_compare_exchange_strong_explicit(object, expected, \
361  desired, memory_order_seq_cst, memory_order_seq_cst)
362 #define atomic_compare_exchange_weak(object, expected, desired) \
363  atomic_compare_exchange_weak_explicit(object, expected, \
364  desired, memory_order_seq_cst, memory_order_seq_cst)
365 #define atomic_exchange(object, desired) \
366  atomic_exchange_explicit(object, desired, memory_order_seq_cst)
367 #define atomic_fetch_add(object, operand) \
368  atomic_fetch_add_explicit(object, operand, memory_order_seq_cst)
369 #define atomic_fetch_and(object, operand) \
370  atomic_fetch_and_explicit(object, operand, memory_order_seq_cst)
371 #define atomic_fetch_or(object, operand) \
372  atomic_fetch_or_explicit(object, operand, memory_order_seq_cst)
373 #define atomic_fetch_sub(object, operand) \
374  atomic_fetch_sub_explicit(object, operand, memory_order_seq_cst)
375 #define atomic_fetch_xor(object, operand) \
376  atomic_fetch_xor_explicit(object, operand, memory_order_seq_cst)
377 #define atomic_load(object) \
378  atomic_load_explicit(object, memory_order_seq_cst)
379 #define atomic_store(object, desired) \
380  atomic_store_explicit(object, desired, memory_order_seq_cst)
381 
382 /*
383  * 7.17.8 Atomic flag type and operations.
384  */
385 
386 typedef atomic_bool atomic_flag;
387 
388 #define ATOMIC_FLAG_INIT ATOMIC_VAR_INIT(0)
389 
390 #define atomic_flag_clear_explicit(object, order) \
391  atomic_store_explicit(object, 0, order)
392 #define atomic_flag_test_and_set_explicit(object, order) \
393  atomic_compare_exchange_strong_explicit(object, 0, 1, order, order)
394 
395 #define atomic_flag_clear(object) \
396  atomic_flag_clear_explicit(object, memory_order_seq_cst)
397 #define atomic_flag_test_and_set(object) \
398  atomic_flag_test_and_set_explicit(object, memory_order_seq_cst)
399 
400 #endif /* !_STDATOMIC_H_ */ // NOLINT
Definition: stdatomic.h:163
#define __ATOMIC_ACQUIRE
Definition: stdatomic.h:141
Definition: stdatomic.h:164
Definition: stdatomic.h:165
#define __ATOMIC_RELAXED
Definition: stdatomic.h:135
Definition: stdatomic.h:166
memory_order
Definition: stdatomic.h:160
Definition: stdatomic.h:161
atomic_bool atomic_flag
Definition: stdatomic.h:386
#define __ATOMIC_SEQ_CST
Definition: stdatomic.h:150
#define _Atomic(T)
Definition: stdatomic.h:111
#define __ATOMIC_CONSUME
Definition: stdatomic.h:138
Definition: stdatomic.h:162
#define __ATOMIC_ACQ_REL
Definition: stdatomic.h:147
#define __ATOMIC_RELEASE
Definition: stdatomic.h:144