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 #pragma once
31
32 #include <sys/cdefs.h>
33 #include <sys/types.h>
34 #include <stdbool.h>
35
36 /*
37 * C: Do it ourselves.
38 * Note that the runtime representation defined here should be compatible
39 * with the C++ one, i.e. an _Atomic(T) needs to contain the same
40 * bits as a T.
41 */
42
43 #include <stddef.h> /* For ptrdiff_t. */
44 #include <stdint.h>
45 // Include uchar.h only when available. Bionic's stdatomic.h is also used for
46 // the host (via a copy in prebuilts/clang) and uchar.h is not available in the
47 // glibc used for the host.
48 #if defined(__BIONIC__)
49 # include <uchar.h> /* For char16_t and char32_t. */
50 #endif
51
52 /*
53 * 7.17.1 Atomic lock-free macros.
54 */
55
56 #define ATOMIC_BOOL_LOCK_FREE __CLANG_ATOMIC_BOOL_LOCK_FREE
57 #define ATOMIC_CHAR_LOCK_FREE __CLANG_ATOMIC_CHAR_LOCK_FREE
58 #define ATOMIC_CHAR16_T_LOCK_FREE __CLANG_ATOMIC_CHAR16_T_LOCK_FREE
59 #define ATOMIC_CHAR32_T_LOCK_FREE __CLANG_ATOMIC_CHAR32_T_LOCK_FREE
60 #define ATOMIC_WCHAR_T_LOCK_FREE __CLANG_ATOMIC_WCHAR_T_LOCK_FREE
61 #define ATOMIC_SHORT_LOCK_FREE __CLANG_ATOMIC_SHORT_LOCK_FREE
62 #define ATOMIC_INT_LOCK_FREE __CLANG_ATOMIC_INT_LOCK_FREE
63 #define ATOMIC_LONG_LOCK_FREE __CLANG_ATOMIC_LONG_LOCK_FREE
64 #define ATOMIC_LLONG_LOCK_FREE __CLANG_ATOMIC_LLONG_LOCK_FREE
65 #define ATOMIC_POINTER_LOCK_FREE __CLANG_ATOMIC_POINTER_LOCK_FREE
66
67 /*
68 * 7.17.2 Initialization.
69 */
70
71 #define ATOMIC_VAR_INIT(value) (value)
72 #define atomic_init(obj, value) __c11_atomic_init(obj, value)
73
74 /*
75 * 7.17.3 Order and consistency.
76 *
77 * The memory_order_* constants that denote the barrier behaviour of the
78 * atomic operations.
79 * The enum values must be identical to those used by the
80 * C++ <atomic> header.
81 */
82
83 typedef enum {
84 memory_order_relaxed = __ATOMIC_RELAXED,
85 memory_order_consume = __ATOMIC_CONSUME,
86 memory_order_acquire = __ATOMIC_ACQUIRE,
87 memory_order_release = __ATOMIC_RELEASE,
88 memory_order_acq_rel = __ATOMIC_ACQ_REL,
89 memory_order_seq_cst = __ATOMIC_SEQ_CST
90 } memory_order;
91
92 #define kill_dependency(y) (y)
93
94 /*
95 * 7.17.4 Fences.
96 */
97
atomic_thread_fence(memory_order __order)98 static __inline void atomic_thread_fence(memory_order __order) {
99 __c11_atomic_thread_fence(__order);
100 }
101
atomic_signal_fence(memory_order __order)102 static __inline void atomic_signal_fence(memory_order __order) {
103 __c11_atomic_signal_fence(__order);
104 }
105
106 /*
107 * 7.17.5 Lock-free property.
108 */
109
110 #define atomic_is_lock_free(obj) __c11_atomic_is_lock_free(sizeof(*(obj)))
111
112 /*
113 * 7.17.6 Atomic integer types.
114 */
115
116 typedef _Atomic(bool) atomic_bool;
117 typedef _Atomic(char) atomic_char;
118 typedef _Atomic(signed char) atomic_schar;
119 typedef _Atomic(unsigned char) atomic_uchar;
120 typedef _Atomic(short) atomic_short;
121 typedef _Atomic(unsigned short) atomic_ushort;
122 typedef _Atomic(int) atomic_int;
123 typedef _Atomic(unsigned int) atomic_uint;
124 typedef _Atomic(long) atomic_long;
125 typedef _Atomic(unsigned long) atomic_ulong;
126 typedef _Atomic(long long) atomic_llong;
127 typedef _Atomic(unsigned long long) atomic_ullong;
128 #if defined(__BIONIC__) || (defined(__cplusplus) && __cplusplus >= 201103L)
129 typedef _Atomic(char16_t) atomic_char16_t;
130 typedef _Atomic(char32_t) atomic_char32_t;
131 #endif
132 typedef _Atomic(wchar_t) atomic_wchar_t;
133 typedef _Atomic(int_least8_t) atomic_int_least8_t;
134 typedef _Atomic(uint_least8_t) atomic_uint_least8_t;
135 typedef _Atomic(int_least16_t) atomic_int_least16_t;
136 typedef _Atomic(uint_least16_t) atomic_uint_least16_t;
137 typedef _Atomic(int_least32_t) atomic_int_least32_t;
138 typedef _Atomic(uint_least32_t) atomic_uint_least32_t;
139 typedef _Atomic(int_least64_t) atomic_int_least64_t;
140 typedef _Atomic(uint_least64_t) atomic_uint_least64_t;
141 typedef _Atomic(int_fast8_t) atomic_int_fast8_t;
142 typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t;
143 typedef _Atomic(int_fast16_t) atomic_int_fast16_t;
144 typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t;
145 typedef _Atomic(int_fast32_t) atomic_int_fast32_t;
146 typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t;
147 typedef _Atomic(int_fast64_t) atomic_int_fast64_t;
148 typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t;
149 typedef _Atomic(intptr_t) atomic_intptr_t;
150 typedef _Atomic(uintptr_t) atomic_uintptr_t;
151 typedef _Atomic(size_t) atomic_size_t;
152 typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
153 typedef _Atomic(intmax_t) atomic_intmax_t;
154 typedef _Atomic(uintmax_t) atomic_uintmax_t;
155
156 /*
157 * 7.17.7 Operations on atomic types.
158 */
159
160 /*
161 * Compiler-specific operations.
162 */
163
164 #define atomic_compare_exchange_strong_explicit(object, expected, \
165 desired, success, failure) \
166 __c11_atomic_compare_exchange_strong(object, expected, desired, \
167 success, failure)
168 #define atomic_compare_exchange_weak_explicit(object, expected, \
169 desired, success, failure) \
170 __c11_atomic_compare_exchange_weak(object, expected, desired, \
171 success, failure)
172 #define atomic_exchange_explicit(object, desired, order) \
173 __c11_atomic_exchange(object, desired, order)
174 #define atomic_fetch_add_explicit(object, operand, order) \
175 __c11_atomic_fetch_add(object, operand, order)
176 #define atomic_fetch_and_explicit(object, operand, order) \
177 __c11_atomic_fetch_and(object, operand, order)
178 #define atomic_fetch_or_explicit(object, operand, order) \
179 __c11_atomic_fetch_or(object, operand, order)
180 #define atomic_fetch_sub_explicit(object, operand, order) \
181 __c11_atomic_fetch_sub(object, operand, order)
182 #define atomic_fetch_xor_explicit(object, operand, order) \
183 __c11_atomic_fetch_xor(object, operand, order)
184 #define atomic_load_explicit(object, order) \
185 __c11_atomic_load(object, order)
186 #define atomic_store_explicit(object, desired, order) \
187 __c11_atomic_store(object, desired, order)
188
189 /*
190 * Convenience functions.
191 */
192
193 #define atomic_compare_exchange_strong(object, expected, desired) \
194 atomic_compare_exchange_strong_explicit(object, expected, \
195 desired, memory_order_seq_cst, memory_order_seq_cst)
196 #define atomic_compare_exchange_weak(object, expected, desired) \
197 atomic_compare_exchange_weak_explicit(object, expected, \
198 desired, memory_order_seq_cst, memory_order_seq_cst)
199 #define atomic_exchange(object, desired) \
200 atomic_exchange_explicit(object, desired, memory_order_seq_cst)
201 #define atomic_fetch_add(object, operand) \
202 atomic_fetch_add_explicit(object, operand, memory_order_seq_cst)
203 #define atomic_fetch_and(object, operand) \
204 atomic_fetch_and_explicit(object, operand, memory_order_seq_cst)
205 #define atomic_fetch_or(object, operand) \
206 atomic_fetch_or_explicit(object, operand, memory_order_seq_cst)
207 #define atomic_fetch_sub(object, operand) \
208 atomic_fetch_sub_explicit(object, operand, memory_order_seq_cst)
209 #define atomic_fetch_xor(object, operand) \
210 atomic_fetch_xor_explicit(object, operand, memory_order_seq_cst)
211 #define atomic_load(object) \
212 atomic_load_explicit(object, memory_order_seq_cst)
213 #define atomic_store(object, desired) \
214 atomic_store_explicit(object, desired, memory_order_seq_cst)
215
216 /*
217 * 7.17.8 Atomic flag type and operations.
218 *
219 * atomic_bool can be used to provide a lock-free atomic flag type on every
220 * Android architecture, so this shouldn't be needed in new Android code,
221 * but is in ISO C, and available for portability to PA-RISC and
222 * microcontrollers.
223 */
224
225 typedef struct {
226 atomic_bool __flag;
227 } atomic_flag;
228
229 #define ATOMIC_FLAG_INIT {false}
230
atomic_flag_test_and_set_explicit(volatile atomic_flag * _Nonnull __object,memory_order __order)231 static __inline bool atomic_flag_test_and_set_explicit(volatile atomic_flag * _Nonnull __object, memory_order __order) {
232 return (atomic_exchange_explicit(&__object->__flag, 1, __order));
233 }
234
atomic_flag_clear_explicit(volatile atomic_flag * _Nonnull __object,memory_order __order)235 static __inline void atomic_flag_clear_explicit(volatile atomic_flag * _Nonnull __object, memory_order __order) {
236 atomic_store_explicit(&__object->__flag, 0, __order);
237 }
238
atomic_flag_test_and_set(volatile atomic_flag * _Nonnull __object)239 static __inline bool atomic_flag_test_and_set(volatile atomic_flag * _Nonnull __object) {
240 return (atomic_flag_test_and_set_explicit(__object, memory_order_seq_cst));
241 }
242
atomic_flag_clear(volatile atomic_flag * _Nonnull __object)243 static __inline void atomic_flag_clear(volatile atomic_flag * _Nonnull __object) {
244 atomic_flag_clear_explicit(__object, memory_order_seq_cst);
245 }
246