]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/sys/stdatomic.h
Update dialog to 1.2-20130523
[FreeBSD/FreeBSD.git] / sys / sys / stdatomic.h
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_
32
33 #include <sys/cdefs.h>
34 #include <sys/_types.h>
35
36 #if __has_extension(c_atomic) || __has_extension(cxx_atomic)
37 #define __CLANG_ATOMICS
38 #elif __GNUC_PREREQ__(4, 7)
39 #define __GNUC_ATOMICS
40 #elif defined(__GNUC__)
41 #define __SYNC_ATOMICS
42 #else
43 #error "stdatomic.h does not support your compiler"
44 #endif
45
46 /*
47  * 7.17.1 Atomic lock-free macros.
48  */
49
50 #ifdef __GCC_ATOMIC_BOOL_LOCK_FREE
51 #define ATOMIC_BOOL_LOCK_FREE           __GCC_ATOMIC_BOOL_LOCK_FREE
52 #endif
53 #ifdef __GCC_ATOMIC_CHAR_LOCK_FREE
54 #define ATOMIC_CHAR_LOCK_FREE           __GCC_ATOMIC_CHAR_LOCK_FREE
55 #endif
56 #ifdef __GCC_ATOMIC_CHAR16_T_LOCK_FREE
57 #define ATOMIC_CHAR16_T_LOCK_FREE       __GCC_ATOMIC_CHAR16_T_LOCK_FREE
58 #endif
59 #ifdef __GCC_ATOMIC_CHAR32_T_LOCK_FREE
60 #define ATOMIC_CHAR32_T_LOCK_FREE       __GCC_ATOMIC_CHAR32_T_LOCK_FREE
61 #endif
62 #ifdef __GCC_ATOMIC_WCHAR_T_LOCK_FREE
63 #define ATOMIC_WCHAR_T_LOCK_FREE        __GCC_ATOMIC_WCHAR_T_LOCK_FREE
64 #endif
65 #ifdef __GCC_ATOMIC_SHORT_LOCK_FREE
66 #define ATOMIC_SHORT_LOCK_FREE          __GCC_ATOMIC_SHORT_LOCK_FREE
67 #endif
68 #ifdef __GCC_ATOMIC_INT_LOCK_FREE
69 #define ATOMIC_INT_LOCK_FREE            __GCC_ATOMIC_INT_LOCK_FREE
70 #endif
71 #ifdef __GCC_ATOMIC_LONG_LOCK_FREE
72 #define ATOMIC_LONG_LOCK_FREE           __GCC_ATOMIC_LONG_LOCK_FREE
73 #endif
74 #ifdef __GCC_ATOMIC_LLONG_LOCK_FREE
75 #define ATOMIC_LLONG_LOCK_FREE          __GCC_ATOMIC_LLONG_LOCK_FREE
76 #endif
77 #ifdef __GCC_ATOMIC_POINTER_LOCK_FREE
78 #define ATOMIC_POINTER_LOCK_FREE        __GCC_ATOMIC_POINTER_LOCK_FREE
79 #endif
80
81 /*
82  * 7.17.2 Initialization.
83  */
84
85 #if defined(__CLANG_ATOMICS)
86 #define ATOMIC_VAR_INIT(value)          (value)
87 #define atomic_init(obj, value)         __c11_atomic_init(obj, value)
88 #else
89 #define ATOMIC_VAR_INIT(value)          { .__val = (value) }
90 #define atomic_init(obj, value)         ((void)((obj)->__val = (value)))
91 #endif
92
93 /*
94  * Clang and recent GCC both provide predefined macros for the memory
95  * orderings.  If we are using a compiler that doesn't define them, use the
96  * clang values - these will be ignored in the fallback path.
97  */
98
99 #ifndef __ATOMIC_RELAXED
100 #define __ATOMIC_RELAXED                0
101 #endif
102 #ifndef __ATOMIC_CONSUME
103 #define __ATOMIC_CONSUME                1
104 #endif
105 #ifndef __ATOMIC_ACQUIRE
106 #define __ATOMIC_ACQUIRE                2
107 #endif
108 #ifndef __ATOMIC_RELEASE
109 #define __ATOMIC_RELEASE                3
110 #endif
111 #ifndef __ATOMIC_ACQ_REL
112 #define __ATOMIC_ACQ_REL                4
113 #endif
114 #ifndef __ATOMIC_SEQ_CST
115 #define __ATOMIC_SEQ_CST                5
116 #endif
117
118 /*
119  * 7.17.3 Order and consistency.
120  *
121  * The memory_order_* constants that denote the barrier behaviour of the
122  * atomic operations.
123  */
124
125 enum memory_order {
126         memory_order_relaxed = __ATOMIC_RELAXED,
127         memory_order_consume = __ATOMIC_CONSUME,
128         memory_order_acquire = __ATOMIC_ACQUIRE,
129         memory_order_release = __ATOMIC_RELEASE,
130         memory_order_acq_rel = __ATOMIC_ACQ_REL,
131         memory_order_seq_cst = __ATOMIC_SEQ_CST
132 };
133
134 /*
135  * 7.17.4 Fences.
136  */
137
138 #ifdef __CLANG_ATOMICS
139 #define atomic_thread_fence(order)      __c11_atomic_thread_fence(order)
140 #define atomic_signal_fence(order)      __c11_atomic_signal_fence(order)
141 #elif defined(__GNUC_ATOMICS)
142 #define atomic_thread_fence(order)      __atomic_thread_fence(order)
143 #define atomic_signal_fence(order)      __atomic_signal_fence(order)
144 #else
145 #define atomic_thread_fence(order)      ((void)(order), __sync_synchronize())
146 #define atomic_signal_fence(order)      __extension__ ({                \
147         (void)(order);                                                  \
148         __asm volatile ("" ::: "memory");                               \
149         (void)0;                                                        \
150 })
151 #endif
152
153 /*
154  * 7.17.5 Lock-free property.
155  */
156
157 #if defined(_KERNEL)
158 /* Atomics in kernelspace are always lock-free. */
159 #define atomic_is_lock_free(obj) \
160         ((void)(obj), (_Bool)1)
161 #elif defined(__CLANG_ATOMICS)
162 #define atomic_is_lock_free(obj) \
163         __atomic_is_lock_free(sizeof(*(obj)), obj)
164 #elif defined(__GNUC_ATOMICS)
165 #define atomic_is_lock_free(obj) \
166         __atomic_is_lock_free(sizeof((obj)->__val), &(obj)->__val)
167 #else
168 #define atomic_is_lock_free(obj) \
169         ((void)(obj), sizeof((obj)->__val) <= sizeof(void *))
170 #endif
171
172 /*
173  * 7.17.6 Atomic integer types.
174  */
175
176 typedef _Atomic(_Bool)                  atomic_bool;
177 typedef _Atomic(char)                   atomic_char;
178 typedef _Atomic(signed char)            atomic_schar;
179 typedef _Atomic(unsigned char)          atomic_uchar;
180 typedef _Atomic(short)                  atomic_short;
181 typedef _Atomic(unsigned short)         atomic_ushort;
182 typedef _Atomic(int)                    atomic_int;
183 typedef _Atomic(unsigned int)           atomic_uint;
184 typedef _Atomic(long)                   atomic_long;
185 typedef _Atomic(unsigned long)          atomic_ulong;
186 typedef _Atomic(long long)              atomic_llong;
187 typedef _Atomic(unsigned long long)     atomic_ullong;
188 typedef _Atomic(__char16_t)             atomic_char16_t;
189 typedef _Atomic(__char32_t)             atomic_char32_t;
190 typedef _Atomic(__wchar_t)              atomic_wchar_t;
191 typedef _Atomic(__int_least8_t)         atomic_int_least8_t;
192 typedef _Atomic(__uint_least8_t)        atomic_uint_least8_t;
193 typedef _Atomic(__int_least16_t)        atomic_int_least16_t;
194 typedef _Atomic(__uint_least16_t)       atomic_uint_least16_t;
195 typedef _Atomic(__int_least32_t)        atomic_int_least32_t;
196 typedef _Atomic(__uint_least32_t)       atomic_uint_least32_t;
197 typedef _Atomic(__int_least64_t)        atomic_int_least64_t;
198 typedef _Atomic(__uint_least64_t)       atomic_uint_least64_t;
199 typedef _Atomic(__int_fast8_t)          atomic_int_fast8_t;
200 typedef _Atomic(__uint_fast8_t)         atomic_uint_fast8_t;
201 typedef _Atomic(__int_fast16_t)         atomic_int_fast16_t;
202 typedef _Atomic(__uint_fast16_t)        atomic_uint_fast16_t;
203 typedef _Atomic(__int_fast32_t)         atomic_int_fast32_t;
204 typedef _Atomic(__uint_fast32_t)        atomic_uint_fast32_t;
205 typedef _Atomic(__int_fast64_t)         atomic_int_fast64_t;
206 typedef _Atomic(__uint_fast64_t)        atomic_uint_fast64_t;
207 typedef _Atomic(__intptr_t)             atomic_intptr_t;
208 typedef _Atomic(__uintptr_t)            atomic_uintptr_t;
209 typedef _Atomic(__size_t)               atomic_size_t;
210 typedef _Atomic(__ptrdiff_t)            atomic_ptrdiff_t;
211 typedef _Atomic(__intmax_t)             atomic_intmax_t;
212 typedef _Atomic(__uintmax_t)            atomic_uintmax_t;
213
214 /*
215  * 7.17.7 Operations on atomic types.
216  */
217
218 /*
219  * Compiler-specific operations.
220  */
221
222 #if defined(__CLANG_ATOMICS)
223 #define atomic_compare_exchange_strong_explicit(object, expected,       \
224     desired, success, failure)                                          \
225         __c11_atomic_compare_exchange_strong(object, expected, desired, \
226             success, failure)
227 #define atomic_compare_exchange_weak_explicit(object, expected,         \
228     desired, success, failure)                                          \
229         __c11_atomic_compare_exchange_weak(object, expected, desired,   \
230             success, failure)
231 #define atomic_exchange_explicit(object, desired, order)                \
232         __c11_atomic_exchange(object, desired, order)
233 #define atomic_fetch_add_explicit(object, operand, order)               \
234         __c11_atomic_fetch_add(object, operand, order)
235 #define atomic_fetch_and_explicit(object, operand, order)               \
236         __c11_atomic_fetch_and(object, operand, order)
237 #define atomic_fetch_or_explicit(object, operand, order)                \
238         __c11_atomic_fetch_or(object, operand, order)
239 #define atomic_fetch_sub_explicit(object, operand, order)               \
240         __c11_atomic_fetch_sub(object, operand, order)
241 #define atomic_fetch_xor_explicit(object, operand, order)               \
242         __c11_atomic_fetch_xor(object, operand, order)
243 #define atomic_load_explicit(object, order)                             \
244         __c11_atomic_load(object, order)
245 #define atomic_store_explicit(object, desired, order)                   \
246         __c11_atomic_store(object, desired, order)
247 #elif defined(__GNUC_ATOMICS)
248 #define atomic_compare_exchange_strong_explicit(object, expected,       \
249     desired, success, failure)                                          \
250         __atomic_compare_exchange_n(&(object)->__val, expected,         \
251             desired, 0, success, failure)
252 #define atomic_compare_exchange_weak_explicit(object, expected,         \
253     desired, success, failure)                                          \
254         __atomic_compare_exchange_n(&(object)->__val, expected,         \
255             desired, 1, success, failure)
256 #define atomic_exchange_explicit(object, desired, order)                \
257         __atomic_exchange_n(&(object)->__val, desired, order)
258 #define atomic_fetch_add_explicit(object, operand, order)               \
259         __atomic_fetch_add(&(object)->__val, operand, order)
260 #define atomic_fetch_and_explicit(object, operand, order)               \
261         __atomic_fetch_and(&(object)->__val, operand, order)
262 #define atomic_fetch_or_explicit(object, operand, order)                \
263         __atomic_fetch_or(&(object)->__val, operand, order)
264 #define atomic_fetch_sub_explicit(object, operand, order)               \
265         __atomic_fetch_sub(&(object)->__val, operand, order)
266 #define atomic_fetch_xor_explicit(object, operand, order)               \
267         __atomic_fetch_xor(&(object)->__val, operand, order)
268 #define atomic_load_explicit(object, order)                             \
269         __atomic_load_n(&(object)->__val, order)
270 #define atomic_store_explicit(object, desired, order)                   \
271         __atomic_store_n(&(object)->__val, desired, order)
272 #else
273 #define atomic_compare_exchange_strong_explicit(object, expected,       \
274     desired, success, failure)  __extension__ ({                        \
275         __typeof__(expected) __ep = (expected);                         \
276         __typeof__(*__ep) __e = *__ep;                                  \
277         (void)(success); (void)(failure);                               \
278         (*__ep = __sync_val_compare_and_swap(&(object)->__val,          \
279             __e, desired)) == __e;                                      \
280 })
281 #define atomic_compare_exchange_weak_explicit(object, expected,         \
282     desired, success, failure)                                          \
283         atomic_compare_exchange_strong_explicit(object, expected,       \
284                 desired, success, failure)
285 #if __has_builtin(__sync_swap)
286 /* Clang provides a full-barrier atomic exchange - use it if available. */
287 #define atomic_exchange_explicit(object, desired, order)                \
288         ((void)(order), __sync_swap(&(object)->__val, desired))
289 #else
290 /*
291  * __sync_lock_test_and_set() is only an acquire barrier in theory (although in
292  * practice it is usually a full barrier) so we need an explicit barrier before
293  * it.
294  */
295 #define atomic_exchange_explicit(object, desired, order)                \
296 __extension__ ({                                                        \
297         __typeof__(object) __o = (object);                              \
298         __typeof__(desired) __d = (desired);                            \
299         (void)(order);                                                  \
300         __sync_synchronize();                                           \
301         __sync_lock_test_and_set(&(__o)->__val, __d);                   \
302 })
303 #endif
304 #define atomic_fetch_add_explicit(object, operand, order)               \
305         ((void)(order), __sync_fetch_and_add(&(object)->__val, operand))
306 #define atomic_fetch_and_explicit(object, operand, order)               \
307         ((void)(order), __sync_fetch_and_and(&(object)->__val, operand))
308 #define atomic_fetch_or_explicit(object, operand, order)                \
309         ((void)(order), __sync_fetch_and_or(&(object)->__val, operand))
310 #define atomic_fetch_sub_explicit(object, operand, order)               \
311         ((void)(order), __sync_fetch_and_sub(&(object)->__val, operand))
312 #define atomic_fetch_xor_explicit(object, operand, order)               \
313         ((void)(order), __sync_fetch_and_xor(&(object)->__val, operand))
314 #define atomic_load_explicit(object, order)                             \
315         ((void)(order), __sync_fetch_and_add(&(object)->__val, 0))
316 #define atomic_store_explicit(object, desired, order)                   \
317         ((void)atomic_exchange_explicit(object, desired, order))
318 #endif
319
320 /*
321  * Convenience functions.
322  */
323
324 #define atomic_compare_exchange_strong(object, expected, desired)       \
325         atomic_compare_exchange_strong_explicit(object, expected,       \
326             desired, memory_order_seq_cst, memory_order_seq_cst)
327 #define atomic_compare_exchange_weak(object, expected, desired)         \
328         atomic_compare_exchange_weak_explicit(object, expected,         \
329             desired, memory_order_seq_cst, memory_order_seq_cst)
330 #define atomic_exchange(object, desired)                                \
331         atomic_exchange_explicit(object, desired, memory_order_seq_cst)
332 #define atomic_fetch_add(object, operand)                               \
333         atomic_fetch_add_explicit(object, operand, memory_order_seq_cst)
334 #define atomic_fetch_and(object, operand)                               \
335         atomic_fetch_and_explicit(object, operand, memory_order_seq_cst)
336 #define atomic_fetch_or(object, operand)                                \
337         atomic_fetch_or_explicit(object, operand, memory_order_seq_cst)
338 #define atomic_fetch_sub(object, operand)                               \
339         atomic_fetch_sub_explicit(object, operand, memory_order_seq_cst)
340 #define atomic_fetch_xor(object, operand)                               \
341         atomic_fetch_xor_explicit(object, operand, memory_order_seq_cst)
342 #define atomic_load(object)                                             \
343         atomic_load_explicit(object, memory_order_seq_cst)
344 #define atomic_store(object, desired)                                   \
345         atomic_store_explicit(object, desired, memory_order_seq_cst)
346
347 /*
348  * 7.17.8 Atomic flag type and operations.
349  */
350
351 typedef atomic_bool                     atomic_flag;
352
353 #define ATOMIC_FLAG_INIT                ATOMIC_VAR_INIT(0)
354
355 #define atomic_flag_clear_explicit(object, order)                       \
356         atomic_store_explicit(object, 0, order)
357 #define atomic_flag_test_and_set_explicit(object, order)                \
358         atomic_compare_exchange_strong_explicit(object, 0, 1, order, order)
359
360 #define atomic_flag_clear(object)                                       \
361         atomic_flag_clear_explicit(object, memory_order_seq_cst)
362 #define atomic_flag_test_and_set(object)                                \
363         atomic_flag_test_and_set_explicit(object, memory_order_seq_cst)
364
365 #endif /* !_STDATOMIC_H_ */