blob: 8717e15270390a75d792e0281d10a816782afaa4 [file] [log] [blame]
Tom Cherry76e2b152019-07-18 13:15:47 -07001/*-
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. */
Tom Cherry6f2e8102020-04-10 10:50:09 -070044#include <stdint.h>
Tom Cherry76e2b152019-07-18 13:15:47 -070045// 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
Elliott Hugheseb53f072025-03-05 12:49:09 -080056#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
Tom Cherry76e2b152019-07-18 13:15:47 -070066
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/*
Tom Cherry76e2b152019-07-18 13:15:47 -070075 * 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
83typedef 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
Elliott Hughes5b5bab52024-10-17 16:38:05 +000092#define kill_dependency(y) (y)
93
Tom Cherry76e2b152019-07-18 13:15:47 -070094/*
95 * 7.17.4 Fences.
96 */
97
Dan Albert2237fcf2024-05-14 17:53:58 +000098static __inline void atomic_thread_fence(memory_order __order __attribute__((__unused__))) {
Tom Cherry76e2b152019-07-18 13:15:47 -070099 __c11_atomic_thread_fence(__order);
100}
101
Dan Albert2237fcf2024-05-14 17:53:58 +0000102static __inline void atomic_signal_fence(memory_order __order __attribute__((__unused__))) {
Tom Cherry76e2b152019-07-18 13:15:47 -0700103 __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
116typedef _Atomic(bool) atomic_bool;
117typedef _Atomic(char) atomic_char;
118typedef _Atomic(signed char) atomic_schar;
119typedef _Atomic(unsigned char) atomic_uchar;
120typedef _Atomic(short) atomic_short;
121typedef _Atomic(unsigned short) atomic_ushort;
122typedef _Atomic(int) atomic_int;
123typedef _Atomic(unsigned int) atomic_uint;
124typedef _Atomic(long) atomic_long;
125typedef _Atomic(unsigned long) atomic_ulong;
126typedef _Atomic(long long) atomic_llong;
127typedef _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
132typedef _Atomic(wchar_t) atomic_wchar_t;
133typedef _Atomic(int_least8_t) atomic_int_least8_t;
134typedef _Atomic(uint_least8_t) atomic_uint_least8_t;
135typedef _Atomic(int_least16_t) atomic_int_least16_t;
136typedef _Atomic(uint_least16_t) atomic_uint_least16_t;
137typedef _Atomic(int_least32_t) atomic_int_least32_t;
138typedef _Atomic(uint_least32_t) atomic_uint_least32_t;
139typedef _Atomic(int_least64_t) atomic_int_least64_t;
140typedef _Atomic(uint_least64_t) atomic_uint_least64_t;
141typedef _Atomic(int_fast8_t) atomic_int_fast8_t;
142typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t;
143typedef _Atomic(int_fast16_t) atomic_int_fast16_t;
144typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t;
145typedef _Atomic(int_fast32_t) atomic_int_fast32_t;
146typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t;
147typedef _Atomic(int_fast64_t) atomic_int_fast64_t;
148typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t;
149typedef _Atomic(intptr_t) atomic_intptr_t;
150typedef _Atomic(uintptr_t) atomic_uintptr_t;
151typedef _Atomic(size_t) atomic_size_t;
152typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
153typedef _Atomic(intmax_t) atomic_intmax_t;
154typedef _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 * XXX: Assume atomic_bool can be used as an atomic_flag. Is there some
220 * kind of compiler built-in type we could use?
221 */
222
223typedef struct {
224 atomic_bool __flag;
225} atomic_flag;
226
Elliott Hugheseb53f072025-03-05 12:49:09 -0800227#define ATOMIC_FLAG_INIT {false}
Tom Cherry76e2b152019-07-18 13:15:47 -0700228
Dan Albert2237fcf2024-05-14 17:53:58 +0000229static __inline bool atomic_flag_test_and_set_explicit(volatile atomic_flag * _Nonnull __object, memory_order __order) {
Tom Cherry76e2b152019-07-18 13:15:47 -0700230 return (atomic_exchange_explicit(&__object->__flag, 1, __order));
231}
232
Dan Albert2237fcf2024-05-14 17:53:58 +0000233static __inline void atomic_flag_clear_explicit(volatile atomic_flag * _Nonnull __object, memory_order __order) {
Tom Cherry76e2b152019-07-18 13:15:47 -0700234 atomic_store_explicit(&__object->__flag, 0, __order);
235}
236
Dan Albert2237fcf2024-05-14 17:53:58 +0000237static __inline bool atomic_flag_test_and_set(volatile atomic_flag * _Nonnull __object) {
Tom Cherry76e2b152019-07-18 13:15:47 -0700238 return (atomic_flag_test_and_set_explicit(__object, memory_order_seq_cst));
239}
240
Dan Albert2237fcf2024-05-14 17:53:58 +0000241static __inline void atomic_flag_clear(volatile atomic_flag * _Nonnull __object) {
Tom Cherry76e2b152019-07-18 13:15:47 -0700242 atomic_flag_clear_explicit(__object, memory_order_seq_cst);
243}