PatchworkOS
Loading...
Searching...
No Matches
stdatomic.h
Go to the documentation of this file.
1/*-
2 * Copyright (c) 2011 Ed Schouten <ed@FreeBSD.org>
3 * David Chisnall <theraven@FreeBSD.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD$
28 */
29
30#ifndef _STDATOMIC_H_
31#define _STDATOMIC_H_ 1
32
33#include <stdbool.h>
34#include <stddef.h>
35#include <stdint.h>
36
37#ifndef __GNUC_PREREQ
38#if defined __GNUC__ && defined __GNUC_MINOR__
39#define __GNUC_PREREQ(maj, min) ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
40#else
41#define __GNUC_PREREQ(maj, min) 0
42#endif
43#endif
44#define __GNUC_PREREQ__(ma, mi) __GNUC_PREREQ(ma, mi)
45
46#ifndef __has_feature
47#define __has_feature(x) 0
48#endif
49
50#if __has_feature(cxx_atomic)
51#define __CLANG_ATOMICS
52#elif __GNUC_PREREQ__(4, 7)
53#define __GNUC_ATOMICS
54#elif !defined(__GNUC__)
55#error "stdatomic.h does not support your compiler"
56#endif
57
58#if !defined(__CLANG_ATOMICS)
59#define _Atomic(T) \
60 struct \
61 { \
62 volatile T __val; \
63 }
64#endif
65
66/*
67 * 7.17.2 Initialization.
68 */
69
70#if defined(__CLANG_ATOMICS)
71#define ATOMIC_VAR_INIT(value) (value)
72#define atomic_init(obj, value) __c11_atomic_init(obj, value)
73#else
74#define ATOMIC_VAR_INIT(value) {.__val = (value)}
75#define atomic_init(obj, value) \
76 do \
77 { \
78 (obj)->__val = (value); \
79 } while (0)
80#endif
81
82/*
83 * Clang and recent GCC both provide predefined macros for the memory
84 * orderings. If we are using a compiler that doesn't define them, use the
85 * clang values - these will be ignored in the fallback path.
86 */
87
88#ifndef __ATOMIC_RELAXED
89#define __ATOMIC_RELAXED 0
90#endif
91#ifndef __ATOMIC_CONSUME
92#define __ATOMIC_CONSUME 1
93#endif
94#ifndef __ATOMIC_ACQUIRE
95#define __ATOMIC_ACQUIRE 2
96#endif
97#ifndef __ATOMIC_RELEASE
98#define __ATOMIC_RELEASE 3
99#endif
100#ifndef __ATOMIC_ACQ_REL
101#define __ATOMIC_ACQ_REL 4
102#endif
103#ifndef __ATOMIC_SEQ_CST
104#define __ATOMIC_SEQ_CST 5
105#endif
106
107/*
108 * 7.17.3 Order and consistency.
109 *
110 * The memory_order_* constants that denote the barrier behaviour of the
111 * atomic operations.
112 */
113
123
124/*
125 * 7.17.4 Fences.
126 */
127
128#ifdef __CLANG_ATOMICS
129#define atomic_thread_fence(order) __c11_atomic_thread_fence(order)
130#define atomic_signal_fence(order) __c11_atomic_signal_fence(order)
131#elif defined(__GNUC_ATOMICS)
132#define atomic_thread_fence(order) __atomic_thread_fence(order)
133#define atomic_signal_fence(order) __atomic_signal_fence(order)
134#else
135#define atomic_thread_fence(order) __sync_synchronize()
136#define atomic_signal_fence(order) __asm volatile("" : : : "memory")
137#endif
138
139/*
140 * 7.17.5 Lock-free property.
141 */
142
143#if defined(__CLANG_ATOMICS)
144#define atomic_is_lock_free(obj) __c11_atomic_is_lock_free(sizeof(obj))
145#elif defined(__GNUC_ATOMICS)
146#define atomic_is_lock_free(obj) __atomic_is_lock_free(sizeof((obj)->__val))
147#else
148#define atomic_is_lock_free(obj) (sizeof((obj)->__val) <= sizeof(void*))
149#endif
150
151/*
152 * 7.17.6 Atomic integer types.
153 */
154
155typedef _Atomic(_Bool) atomic_bool;
156typedef _Atomic(char) atomic_char;
157typedef _Atomic(signed char) atomic_schar;
158typedef _Atomic(unsigned char) atomic_uchar;
159typedef _Atomic(short) atomic_short;
160typedef _Atomic(unsigned short) atomic_ushort;
161typedef _Atomic(int) atomic_int;
162typedef _Atomic(unsigned int) atomic_uint;
163typedef _Atomic(long) atomic_long;
164typedef _Atomic(unsigned long) atomic_ulong;
165typedef _Atomic(long long) atomic_llong;
166typedef _Atomic(unsigned long long) atomic_ullong;
167#if 0
168 typedef _Atomic(__char16_t) atomic_char16_t;
169 typedef _Atomic(__char32_t) atomic_char32_t;
170#endif
171typedef _Atomic(wchar_t) atomic_wchar_t;
172typedef _Atomic(int_least8_t) atomic_int_least8_t;
173typedef _Atomic(uint_least8_t) atomic_uint_least8_t;
174typedef _Atomic(int_least16_t) atomic_int_least16_t;
175typedef _Atomic(uint_least16_t) atomic_uint_least16_t;
176typedef _Atomic(int_least32_t) atomic_int_least32_t;
177typedef _Atomic(uint_least32_t) atomic_uint_least32_t;
178typedef _Atomic(int_least64_t) atomic_int_least64_t;
179typedef _Atomic(uint_least64_t) atomic_uint_least64_t;
180typedef _Atomic(int_fast8_t) atomic_int_fast8_t;
181typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t;
182typedef _Atomic(int_fast16_t) atomic_int_fast16_t;
183typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t;
184typedef _Atomic(int_fast32_t) atomic_int_fast32_t;
185typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t;
186typedef _Atomic(int_fast64_t) atomic_int_fast64_t;
187typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t;
188typedef _Atomic(intptr_t) atomic_intptr_t;
189typedef _Atomic(uintptr_t) atomic_uintptr_t;
190typedef _Atomic(size_t) atomic_size_t;
191typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
192typedef _Atomic(intmax_t) atomic_intmax_t;
193typedef _Atomic(uintmax_t) atomic_uintmax_t;
194
195/*
196 * 7.17.7 Operations on atomic types.
197 */
198
199/*
200 * Compiler-specific operations.
201 */
202
203#if defined(__CLANG_ATOMICS)
204#define atomic_compare_exchange_strong_explicit(object, expected, desired, success, failure) \
205 __c11_atomic_compare_exchange_strong(object, expected, desired, success, failure)
206#define atomic_compare_exchange_weak_explicit(object, expected, desired, success, failure) \
207 __c11_atomic_compare_exchange_weak(object, expected, desired, success, failure)
208#define atomic_exchange_explicit(object, desired, order) __c11_atomic_exchange(object, desired, order)
209#define atomic_fetch_add_explicit(object, operand, order) __c11_atomic_fetch_add(object, operand, order)
210#define atomic_fetch_and_explicit(object, operand, order) __c11_atomic_fetch_and(object, operand, order)
211#define atomic_fetch_or_explicit(object, operand, order) __c11_atomic_fetch_or(object, operand, order)
212#define atomic_fetch_sub_explicit(object, operand, order) __c11_atomic_fetch_sub(object, operand, order)
213#define atomic_fetch_xor_explicit(object, operand, order) __c11_atomic_fetch_xor(object, operand, order)
214#define atomic_load_explicit(object, order) __c11_atomic_load(object, order)
215#define atomic_store_explicit(object, desired, order) __c11_atomic_store(object, desired, order)
216#elif defined(__GNUC_ATOMICS)
217#define atomic_compare_exchange_strong_explicit(object, expected, desired, success, failure) \
218 __atomic_compare_exchange_n(&(object)->__val, expected, desired, 0, success, failure)
219#define atomic_compare_exchange_weak_explicit(object, expected, desired, success, failure) \
220 __atomic_compare_exchange_n(&(object)->__val, expected, desired, 1, success, failure)
221#define atomic_exchange_explicit(object, desired, order) __atomic_exchange_n(&(object)->__val, desired, order)
222#define atomic_fetch_add_explicit(object, operand, order) __atomic_fetch_add(&(object)->__val, operand, order)
223#define atomic_fetch_and_explicit(object, operand, order) __atomic_fetch_and(&(object)->__val, operand, order)
224#define atomic_fetch_or_explicit(object, operand, order) __atomic_fetch_or(&(object)->__val, operand, order)
225#define atomic_fetch_sub_explicit(object, operand, order) __atomic_fetch_sub(&(object)->__val, operand, order)
226#define atomic_fetch_xor_explicit(object, operand, order) __atomic_fetch_xor(&(object)->__val, operand, order)
227#define atomic_load_explicit(object, order) __atomic_load_n(&(object)->__val, order)
228#define atomic_store_explicit(object, desired, order) __atomic_store_n(&(object)->__val, desired, order)
229#else
230#define atomic_compare_exchange_strong_explicit(object, expected, desired, success, failure) \
231 ({ \
232 __typeof__((object)->__val) __v; \
233 _Bool __r; \
234 __v = __sync_val_compare_and_swap(&(object)->__val, *(expected), desired); \
235 __r = *(expected) == __v; \
236 *(expected) = __v; \
237 __r; \
238 })
239
240#define atomic_compare_exchange_weak_explicit(object, expected, desired, success, failure) \
241 atomic_compare_exchange_strong_explicit(object, expected, desired, success, failure)
242#if __has_builtin(__sync_swap)
243/* Clang provides a full-barrier atomic exchange - use it if available. */
244#define atomic_exchange_explicit(object, desired, order) __sync_swap(&(object)->__val, desired)
245#else
246/*
247 * __sync_lock_test_and_set() is only an acquire barrier in theory (although in
248 * practice it is usually a full barrier) so we need an explicit barrier after
249 * it.
250 */
251#define atomic_exchange_explicit(object, desired, order) \
252 ({ \
253 __typeof__((object)->__val) __v; \
254 __v = __sync_lock_test_and_set(&(object)->__val, desired); \
255 __sync_synchronize(); \
256 __v; \
257 })
258#endif
259#define atomic_fetch_add_explicit(object, operand, order) __sync_fetch_and_add(&(object)->__val, operand)
260#define atomic_fetch_and_explicit(object, operand, order) __sync_fetch_and_and(&(object)->__val, operand)
261#define atomic_fetch_or_explicit(object, operand, order) __sync_fetch_and_or(&(object)->__val, operand)
262#define atomic_fetch_sub_explicit(object, operand, order) __sync_fetch_and_sub(&(object)->__val, operand)
263#define atomic_fetch_xor_explicit(object, operand, order) __sync_fetch_and_xor(&(object)->__val, operand)
264#define atomic_load_explicit(object, order) __sync_fetch_and_add(&(object)->__val, 0)
265#define atomic_store_explicit(object, desired, order) \
266 do \
267 { \
268 __sync_synchronize(); \
269 (object)->__val = (desired); \
270 __sync_synchronize(); \
271 } while (0)
272#endif
273
274/*
275 * Convenience functions.
276 */
277
278#define atomic_compare_exchange_strong(object, expected, desired) \
279 atomic_compare_exchange_strong_explicit(object, expected, desired, memory_order_seq_cst, memory_order_seq_cst)
280#define atomic_compare_exchange_weak(object, expected, desired) \
281 atomic_compare_exchange_weak_explicit(object, expected, desired, memory_order_seq_cst, memory_order_seq_cst)
282#define atomic_exchange(object, desired) atomic_exchange_explicit(object, desired, memory_order_seq_cst)
283#define atomic_fetch_add(object, operand) atomic_fetch_add_explicit(object, operand, memory_order_seq_cst)
284#define atomic_fetch_and(object, operand) atomic_fetch_and_explicit(object, operand, memory_order_seq_cst)
285#define atomic_fetch_or(object, operand) atomic_fetch_or_explicit(object, operand, memory_order_seq_cst)
286#define atomic_fetch_sub(object, operand) atomic_fetch_sub_explicit(object, operand, memory_order_seq_cst)
287#define atomic_fetch_xor(object, operand) atomic_fetch_xor_explicit(object, operand, memory_order_seq_cst)
288#define atomic_load(object) atomic_load_explicit(object, memory_order_seq_cst)
289#define atomic_store(object, desired) atomic_store_explicit(object, desired, memory_order_seq_cst)
290
291/*
292 * 7.17.8 Atomic flag type and operations.
293 */
294
295typedef atomic_bool atomic_flag;
296
297#define ATOMIC_FLAG_INIT ATOMIC_VAR_INIT(0)
298
299#define atomic_flag_clear_explicit(object, order) atomic_store_explicit(object, 0, order)
300#define atomic_flag_test_and_set_explicit(object, order) \
301 atomic_compare_exchange_strong_explicit(object, 0, 1, order, order)
302
303#define atomic_flag_clear(object) atomic_flag_clear_explicit(object, memory_order_seq_cst)
304#define atomic_flag_test_and_set(object) atomic_flag_test_and_set_explicit(object, memory_order_seq_cst)
305
306/*
307 * Atomic integers for C11
308 */
309
310typedef _Atomic(uint64_t) atomic_uint64_t;
311typedef _Atomic(uint32_t) atomic_uint32_t;
312typedef _Atomic(uint16_t) atomic_uint16_t;
313typedef _Atomic(uint8_t) atomic_uint8_t;
314
315typedef _Atomic(int64_t) atomic_int64_t;
316typedef _Atomic(int32_t) atomic_int32_t;
317typedef _Atomic(int16_t) atomic_int16_t;
318typedef _Atomic(int8_t) atomic_int8_t;
319
320#endif /* !_STDATOMIC_H_ */
__UINTMAX_TYPE__ uintmax_t
Definition inttypes.h:12
__INTMAX_TYPE__ intmax_t
Definition inttypes.h:11
__PTRDIFF_TYPE__ ptrdiff_t
Definition ptrdiff_t.h:4
#define __ATOMIC_SEQ_CST
Definition stdatomic.h:104
memory_order
Definition stdatomic.h:115
@ memory_order_consume
Definition stdatomic.h:117
@ memory_order_seq_cst
Definition stdatomic.h:121
@ memory_order_release
Definition stdatomic.h:119
@ memory_order_relaxed
Definition stdatomic.h:116
@ memory_order_acq_rel
Definition stdatomic.h:120
@ memory_order_acquire
Definition stdatomic.h:118
#define _Atomic(T)
Definition stdatomic.h:59
atomic_bool atomic_flag
Definition stdatomic.h:295
#define __ATOMIC_RELEASE
Definition stdatomic.h:98
#define __ATOMIC_ACQUIRE
Definition stdatomic.h:95
#define __ATOMIC_CONSUME
Definition stdatomic.h:92
#define __ATOMIC_RELAXED
Definition stdatomic.h:89
#define __ATOMIC_ACQ_REL
Definition stdatomic.h:101
__UINT32_TYPE__ uint32_t
Definition stdint.h:15
__INTPTR_TYPE__ intptr_t
Definition stdint.h:42
__INT32_TYPE__ int32_t
Definition stdint.h:14
__UINT_LEAST16_TYPE__ uint_least16_t
Definition stdint.h:26
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINT_FAST8_TYPE__ uint_fast8_t
Definition stdint.h:36
__INT_LEAST16_TYPE__ int_least16_t
Definition stdint.h:21
__UINT8_TYPE__ uint8_t
Definition stdint.h:11
__INT_LEAST32_TYPE__ int_least32_t
Definition stdint.h:22
__UINTPTR_TYPE__ uintptr_t
Definition stdint.h:43
__INT_FAST32_TYPE__ int_fast32_t
Definition stdint.h:33
__UINT16_TYPE__ uint16_t
Definition stdint.h:13
__UINT_LEAST8_TYPE__ uint_least8_t
Definition stdint.h:25
__UINT_FAST64_TYPE__ uint_fast64_t
Definition stdint.h:39
__UINT_LEAST32_TYPE__ uint_least32_t
Definition stdint.h:27
__INT_FAST16_TYPE__ int_fast16_t
Definition stdint.h:32
__INT_LEAST64_TYPE__ int_least64_t
Definition stdint.h:23
__INT_FAST8_TYPE__ int_fast8_t
Definition stdint.h:31
__UINT_FAST32_TYPE__ uint_fast32_t
Definition stdint.h:38
__UINT_FAST16_TYPE__ uint_fast16_t
Definition stdint.h:37
__UINT_LEAST64_TYPE__ uint_least64_t
Definition stdint.h:28
__INT_FAST64_TYPE__ int_fast64_t
Definition stdint.h:34
__INT64_TYPE__ int64_t
Definition stdint.h:16
__INT8_TYPE__ int8_t
Definition stdint.h:10
__INT_LEAST8_TYPE__ int_least8_t
Definition stdint.h:20
__INT16_TYPE__ int16_t
Definition stdint.h:12