1da0c48c4Sopenharmony_ci/*-
2da0c48c4Sopenharmony_ci * Copyright (c) 2011 Ed Schouten <ed@FreeBSD.org>
3da0c48c4Sopenharmony_ci *                    David Chisnall <theraven@FreeBSD.org>
4da0c48c4Sopenharmony_ci * All rights reserved.
5da0c48c4Sopenharmony_ci *
6da0c48c4Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
7da0c48c4Sopenharmony_ci * modification, are permitted provided that the following conditions
8da0c48c4Sopenharmony_ci * are met:
9da0c48c4Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
10da0c48c4Sopenharmony_ci *    notice, this list of conditions and the following disclaimer.
11da0c48c4Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
12da0c48c4Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in the
13da0c48c4Sopenharmony_ci *    documentation and/or other materials provided with the distribution.
14da0c48c4Sopenharmony_ci *
15da0c48c4Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16da0c48c4Sopenharmony_ci * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17da0c48c4Sopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18da0c48c4Sopenharmony_ci * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19da0c48c4Sopenharmony_ci * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20da0c48c4Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21da0c48c4Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22da0c48c4Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23da0c48c4Sopenharmony_ci * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24da0c48c4Sopenharmony_ci * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25da0c48c4Sopenharmony_ci * SUCH DAMAGE.
26da0c48c4Sopenharmony_ci *
27da0c48c4Sopenharmony_ci * $FreeBSD$
28da0c48c4Sopenharmony_ci */
29da0c48c4Sopenharmony_ci
30da0c48c4Sopenharmony_ci#ifndef _STDATOMIC_H_
31da0c48c4Sopenharmony_ci#define	_STDATOMIC_H_
32da0c48c4Sopenharmony_ci
33da0c48c4Sopenharmony_ci#include <stddef.h>
34da0c48c4Sopenharmony_ci#include <stdint.h>
35da0c48c4Sopenharmony_ci
36da0c48c4Sopenharmony_ci#if !defined(__has_feature)
37da0c48c4Sopenharmony_ci#define __has_feature(x) 0
38da0c48c4Sopenharmony_ci#endif
39da0c48c4Sopenharmony_ci#if !defined(__has_builtin)
40da0c48c4Sopenharmony_ci#define __has_builtin(x) 0
41da0c48c4Sopenharmony_ci#endif
42da0c48c4Sopenharmony_ci#if !defined(__GNUC_PREREQ__)
43da0c48c4Sopenharmony_ci#if defined(__GNUC__) && defined(__GNUC_MINOR__)
44da0c48c4Sopenharmony_ci#define __GNUC_PREREQ__(maj, min)					\
45da0c48c4Sopenharmony_ci	((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
46da0c48c4Sopenharmony_ci#else
47da0c48c4Sopenharmony_ci#define __GNUC_PREREQ__(maj, min) 0
48da0c48c4Sopenharmony_ci#endif
49da0c48c4Sopenharmony_ci#endif
50da0c48c4Sopenharmony_ci
51da0c48c4Sopenharmony_ci#if !defined(__CLANG_ATOMICS) && !defined(__GNUC_ATOMICS)
52da0c48c4Sopenharmony_ci#if __has_feature(c_atomic)
53da0c48c4Sopenharmony_ci#define	__CLANG_ATOMICS
54da0c48c4Sopenharmony_ci#elif __GNUC_PREREQ__(4, 7)
55da0c48c4Sopenharmony_ci#define	__GNUC_ATOMICS
56da0c48c4Sopenharmony_ci#elif !defined(__GNUC__)
57da0c48c4Sopenharmony_ci#error "stdatomic.h does not support your compiler"
58da0c48c4Sopenharmony_ci#endif
59da0c48c4Sopenharmony_ci#endif
60da0c48c4Sopenharmony_ci
61da0c48c4Sopenharmony_ci/*
62da0c48c4Sopenharmony_ci * language independent type to represent a Boolean value
63da0c48c4Sopenharmony_ci */
64da0c48c4Sopenharmony_ci
65da0c48c4Sopenharmony_citypedef int __Bool;
66da0c48c4Sopenharmony_ci
67da0c48c4Sopenharmony_ci/*
68da0c48c4Sopenharmony_ci * 7.17.1 Atomic lock-free macros.
69da0c48c4Sopenharmony_ci */
70da0c48c4Sopenharmony_ci
71da0c48c4Sopenharmony_ci#ifdef __GCC_ATOMIC_BOOL_LOCK_FREE
72da0c48c4Sopenharmony_ci#define	ATOMIC_BOOL_LOCK_FREE		__GCC_ATOMIC_BOOL_LOCK_FREE
73da0c48c4Sopenharmony_ci#endif
74da0c48c4Sopenharmony_ci#ifdef __GCC_ATOMIC_CHAR_LOCK_FREE
75da0c48c4Sopenharmony_ci#define	ATOMIC_CHAR_LOCK_FREE		__GCC_ATOMIC_CHAR_LOCK_FREE
76da0c48c4Sopenharmony_ci#endif
77da0c48c4Sopenharmony_ci#ifdef __GCC_ATOMIC_CHAR16_T_LOCK_FREE
78da0c48c4Sopenharmony_ci#define	ATOMIC_CHAR16_T_LOCK_FREE	__GCC_ATOMIC_CHAR16_T_LOCK_FREE
79da0c48c4Sopenharmony_ci#endif
80da0c48c4Sopenharmony_ci#ifdef __GCC_ATOMIC_CHAR32_T_LOCK_FREE
81da0c48c4Sopenharmony_ci#define	ATOMIC_CHAR32_T_LOCK_FREE	__GCC_ATOMIC_CHAR32_T_LOCK_FREE
82da0c48c4Sopenharmony_ci#endif
83da0c48c4Sopenharmony_ci#ifdef __GCC_ATOMIC_WCHAR_T_LOCK_FREE
84da0c48c4Sopenharmony_ci#define	ATOMIC_WCHAR_T_LOCK_FREE	__GCC_ATOMIC_WCHAR_T_LOCK_FREE
85da0c48c4Sopenharmony_ci#endif
86da0c48c4Sopenharmony_ci#ifdef __GCC_ATOMIC_SHORT_LOCK_FREE
87da0c48c4Sopenharmony_ci#define	ATOMIC_SHORT_LOCK_FREE		__GCC_ATOMIC_SHORT_LOCK_FREE
88da0c48c4Sopenharmony_ci#endif
89da0c48c4Sopenharmony_ci#ifdef __GCC_ATOMIC_INT_LOCK_FREE
90da0c48c4Sopenharmony_ci#define	ATOMIC_INT_LOCK_FREE		__GCC_ATOMIC_INT_LOCK_FREE
91da0c48c4Sopenharmony_ci#endif
92da0c48c4Sopenharmony_ci#ifdef __GCC_ATOMIC_LONG_LOCK_FREE
93da0c48c4Sopenharmony_ci#define	ATOMIC_LONG_LOCK_FREE		__GCC_ATOMIC_LONG_LOCK_FREE
94da0c48c4Sopenharmony_ci#endif
95da0c48c4Sopenharmony_ci#ifdef __GCC_ATOMIC_LLONG_LOCK_FREE
96da0c48c4Sopenharmony_ci#define	ATOMIC_LLONG_LOCK_FREE		__GCC_ATOMIC_LLONG_LOCK_FREE
97da0c48c4Sopenharmony_ci#endif
98da0c48c4Sopenharmony_ci#ifdef __GCC_ATOMIC_POINTER_LOCK_FREE
99da0c48c4Sopenharmony_ci#define	ATOMIC_POINTER_LOCK_FREE	__GCC_ATOMIC_POINTER_LOCK_FREE
100da0c48c4Sopenharmony_ci#endif
101da0c48c4Sopenharmony_ci
102da0c48c4Sopenharmony_ci#if !defined(__CLANG_ATOMICS)
103da0c48c4Sopenharmony_ci#define	_Atomic(T)			struct { volatile __typeof__(T) __val; }
104da0c48c4Sopenharmony_ci#endif
105da0c48c4Sopenharmony_ci
106da0c48c4Sopenharmony_ci/*
107da0c48c4Sopenharmony_ci * 7.17.2 Initialization.
108da0c48c4Sopenharmony_ci */
109da0c48c4Sopenharmony_ci
110da0c48c4Sopenharmony_ci#if defined(__CLANG_ATOMICS)
111da0c48c4Sopenharmony_ci#define	ATOMIC_VAR_INIT(value)		(value)
112da0c48c4Sopenharmony_ci#define	atomic_init(obj, value)		__c11_atomic_init(obj, value)
113da0c48c4Sopenharmony_ci#else
114da0c48c4Sopenharmony_ci#define	ATOMIC_VAR_INIT(value)		{ .__val = (value) }
115da0c48c4Sopenharmony_ci#define	atomic_init(obj, value)		((void)((obj)->__val = (value)))
116da0c48c4Sopenharmony_ci#endif
117da0c48c4Sopenharmony_ci
118da0c48c4Sopenharmony_ci/*
119da0c48c4Sopenharmony_ci * Clang and recent GCC both provide predefined macros for the memory
120da0c48c4Sopenharmony_ci * orderings.  If we are using a compiler that doesn't define them, use the
121da0c48c4Sopenharmony_ci * clang values - these will be ignored in the fallback path.
122da0c48c4Sopenharmony_ci */
123da0c48c4Sopenharmony_ci
124da0c48c4Sopenharmony_ci#ifndef __ATOMIC_RELAXED
125da0c48c4Sopenharmony_ci#define __ATOMIC_RELAXED		0
126da0c48c4Sopenharmony_ci#endif
127da0c48c4Sopenharmony_ci#ifndef __ATOMIC_CONSUME
128da0c48c4Sopenharmony_ci#define __ATOMIC_CONSUME		1
129da0c48c4Sopenharmony_ci#endif
130da0c48c4Sopenharmony_ci#ifndef __ATOMIC_ACQUIRE
131da0c48c4Sopenharmony_ci#define __ATOMIC_ACQUIRE		2
132da0c48c4Sopenharmony_ci#endif
133da0c48c4Sopenharmony_ci#ifndef __ATOMIC_RELEASE
134da0c48c4Sopenharmony_ci#define __ATOMIC_RELEASE		3
135da0c48c4Sopenharmony_ci#endif
136da0c48c4Sopenharmony_ci#ifndef __ATOMIC_ACQ_REL
137da0c48c4Sopenharmony_ci#define __ATOMIC_ACQ_REL		4
138da0c48c4Sopenharmony_ci#endif
139da0c48c4Sopenharmony_ci#ifndef __ATOMIC_SEQ_CST
140da0c48c4Sopenharmony_ci#define __ATOMIC_SEQ_CST		5
141da0c48c4Sopenharmony_ci#endif
142da0c48c4Sopenharmony_ci
143da0c48c4Sopenharmony_ci/*
144da0c48c4Sopenharmony_ci * 7.17.3 Order and consistency.
145da0c48c4Sopenharmony_ci *
146da0c48c4Sopenharmony_ci * The memory_order_* constants that denote the barrier behaviour of the
147da0c48c4Sopenharmony_ci * atomic operations.
148da0c48c4Sopenharmony_ci */
149da0c48c4Sopenharmony_ci
150da0c48c4Sopenharmony_citypedef enum {
151da0c48c4Sopenharmony_ci    memory_order_relaxed = __ATOMIC_RELAXED,
152da0c48c4Sopenharmony_ci    memory_order_consume = __ATOMIC_CONSUME,
153da0c48c4Sopenharmony_ci    memory_order_acquire = __ATOMIC_ACQUIRE,
154da0c48c4Sopenharmony_ci    memory_order_release = __ATOMIC_RELEASE,
155da0c48c4Sopenharmony_ci    memory_order_acq_rel = __ATOMIC_ACQ_REL,
156da0c48c4Sopenharmony_ci    memory_order_seq_cst = __ATOMIC_SEQ_CST
157da0c48c4Sopenharmony_ci} memory_order;
158da0c48c4Sopenharmony_ci
159da0c48c4Sopenharmony_ci/*
160da0c48c4Sopenharmony_ci * 7.17.4 Fences.
161da0c48c4Sopenharmony_ci */
162da0c48c4Sopenharmony_ci
163da0c48c4Sopenharmony_ci//#define __unused
164da0c48c4Sopenharmony_ci
165da0c48c4Sopenharmony_ci//static __inline void
166da0c48c4Sopenharmony_ci//atomic_thread_fence(memory_order __order __unused)
167da0c48c4Sopenharmony_ci//{
168da0c48c4Sopenharmony_ci//
169da0c48c4Sopenharmony_ci//#ifdef __CLANG_ATOMICS
170da0c48c4Sopenharmony_ci//    __c11_atomic_thread_fence(__order);
171da0c48c4Sopenharmony_ci//#elif defined(__GNUC_ATOMICS)
172da0c48c4Sopenharmony_ci//    __atomic_thread_fence(__order);
173da0c48c4Sopenharmony_ci//#else
174da0c48c4Sopenharmony_ci//    __sync_synchronize();
175da0c48c4Sopenharmony_ci//#endif
176da0c48c4Sopenharmony_ci//}
177da0c48c4Sopenharmony_ci//
178da0c48c4Sopenharmony_ci//static __inline void
179da0c48c4Sopenharmony_ci//atomic_signal_fence(memory_order __order __unused)
180da0c48c4Sopenharmony_ci//{
181da0c48c4Sopenharmony_ci//
182da0c48c4Sopenharmony_ci//#ifdef __CLANG_ATOMICS
183da0c48c4Sopenharmony_ci//    __c11_atomic_signal_fence(__order);
184da0c48c4Sopenharmony_ci//#elif defined(__GNUC_ATOMICS)
185da0c48c4Sopenharmony_ci//    __atomic_signal_fence(__order);
186da0c48c4Sopenharmony_ci//#else
187da0c48c4Sopenharmony_ci//    __asm volatile ("" ::: "memory");
188da0c48c4Sopenharmony_ci//#endif
189da0c48c4Sopenharmony_ci//}
190da0c48c4Sopenharmony_ci
191da0c48c4Sopenharmony_ci//#undef __unused
192da0c48c4Sopenharmony_ci
193da0c48c4Sopenharmony_ci/*
194da0c48c4Sopenharmony_ci * 7.17.5 Lock-free property.
195da0c48c4Sopenharmony_ci */
196da0c48c4Sopenharmony_ci
197da0c48c4Sopenharmony_ci#if defined(_KERNEL)
198da0c48c4Sopenharmony_ci/* Atomics in kernelspace are always lock-free. */
199da0c48c4Sopenharmony_ci#define	atomic_is_lock_free(obj) \
200da0c48c4Sopenharmony_ci	((void)(obj), (__Bool)1)
201da0c48c4Sopenharmony_ci#elif defined(__CLANG_ATOMICS)
202da0c48c4Sopenharmony_ci#define	atomic_is_lock_free(obj) \
203da0c48c4Sopenharmony_ci	__atomic_is_lock_free(sizeof(*(obj)), obj)
204da0c48c4Sopenharmony_ci#elif defined(__GNUC_ATOMICS)
205da0c48c4Sopenharmony_ci#define	atomic_is_lock_free(obj) \
206da0c48c4Sopenharmony_ci	__atomic_is_lock_free(sizeof((obj)->__val), &(obj)->__val)
207da0c48c4Sopenharmony_ci#else
208da0c48c4Sopenharmony_ci#define	atomic_is_lock_free(obj) \
209da0c48c4Sopenharmony_ci	((void)(obj), sizeof((obj)->__val) <= sizeof(void *))
210da0c48c4Sopenharmony_ci#endif
211da0c48c4Sopenharmony_ci
212da0c48c4Sopenharmony_ci/*
213da0c48c4Sopenharmony_ci * 7.17.6 Atomic integer types.
214da0c48c4Sopenharmony_ci */
215da0c48c4Sopenharmony_ci
216da0c48c4Sopenharmony_citypedef _Atomic(__Bool)			atomic_bool;
217da0c48c4Sopenharmony_citypedef _Atomic(char)			atomic_char;
218da0c48c4Sopenharmony_citypedef _Atomic(signed char)		atomic_schar;
219da0c48c4Sopenharmony_citypedef _Atomic(unsigned char)		atomic_uchar;
220da0c48c4Sopenharmony_citypedef _Atomic(short)			atomic_short;
221da0c48c4Sopenharmony_citypedef _Atomic(unsigned short)		atomic_ushort;
222da0c48c4Sopenharmony_citypedef _Atomic(int)			atomic_int;
223da0c48c4Sopenharmony_citypedef _Atomic(unsigned int)		atomic_uint;
224da0c48c4Sopenharmony_citypedef _Atomic(long)			atomic_long;
225da0c48c4Sopenharmony_citypedef _Atomic(unsigned long)		atomic_ulong;
226da0c48c4Sopenharmony_citypedef _Atomic(long long)		atomic_llong;
227da0c48c4Sopenharmony_citypedef _Atomic(unsigned long long)	atomic_ullong;
228da0c48c4Sopenharmony_ci#if 0
229da0c48c4Sopenharmony_citypedef _Atomic(char16_t)		atomic_char16_t;
230da0c48c4Sopenharmony_citypedef _Atomic(char32_t)		atomic_char32_t;
231da0c48c4Sopenharmony_ci#endif
232da0c48c4Sopenharmony_citypedef _Atomic(wchar_t)		atomic_wchar_t;
233da0c48c4Sopenharmony_citypedef _Atomic(int_least8_t)		atomic_int_least8_t;
234da0c48c4Sopenharmony_citypedef _Atomic(uint_least8_t)		atomic_uint_least8_t;
235da0c48c4Sopenharmony_citypedef _Atomic(int_least16_t)		atomic_int_least16_t;
236da0c48c4Sopenharmony_citypedef _Atomic(uint_least16_t)		atomic_uint_least16_t;
237da0c48c4Sopenharmony_citypedef _Atomic(int_least32_t)		atomic_int_least32_t;
238da0c48c4Sopenharmony_citypedef _Atomic(uint_least32_t)		atomic_uint_least32_t;
239da0c48c4Sopenharmony_citypedef _Atomic(int_least64_t)		atomic_int_least64_t;
240da0c48c4Sopenharmony_citypedef _Atomic(uint_least64_t)		atomic_uint_least64_t;
241da0c48c4Sopenharmony_citypedef _Atomic(int_fast8_t)		atomic_int_fast8_t;
242da0c48c4Sopenharmony_citypedef _Atomic(uint_fast8_t)		atomic_uint_fast8_t;
243da0c48c4Sopenharmony_citypedef _Atomic(int_fast16_t)		atomic_int_fast16_t;
244da0c48c4Sopenharmony_citypedef _Atomic(uint_fast16_t)		atomic_uint_fast16_t;
245da0c48c4Sopenharmony_citypedef _Atomic(int_fast32_t)		atomic_int_fast32_t;
246da0c48c4Sopenharmony_citypedef _Atomic(uint_fast32_t)		atomic_uint_fast32_t;
247da0c48c4Sopenharmony_citypedef _Atomic(int_fast64_t)		atomic_int_fast64_t;
248da0c48c4Sopenharmony_citypedef _Atomic(uint_fast64_t)		atomic_uint_fast64_t;
249da0c48c4Sopenharmony_citypedef _Atomic(intptr_t)		atomic_intptr_t;
250da0c48c4Sopenharmony_citypedef _Atomic(uintptr_t)		atomic_uintptr_t;
251da0c48c4Sopenharmony_citypedef _Atomic(size_t)			atomic_size_t;
252da0c48c4Sopenharmony_citypedef _Atomic(ptrdiff_t)		atomic_ptrdiff_t;
253da0c48c4Sopenharmony_citypedef _Atomic(intmax_t)		atomic_intmax_t;
254da0c48c4Sopenharmony_citypedef _Atomic(uintmax_t)		atomic_uintmax_t;
255da0c48c4Sopenharmony_ci
256da0c48c4Sopenharmony_ci/*
257da0c48c4Sopenharmony_ci * 7.17.7 Operations on atomic types.
258da0c48c4Sopenharmony_ci */
259da0c48c4Sopenharmony_ci
260da0c48c4Sopenharmony_ci/*
261da0c48c4Sopenharmony_ci * Compiler-specific operations.
262da0c48c4Sopenharmony_ci */
263da0c48c4Sopenharmony_ci
264da0c48c4Sopenharmony_ci#if defined(__CLANG_ATOMICS)
265da0c48c4Sopenharmony_ci#define	atomic_compare_exchange_strong_explicit(object, expected,	\
266da0c48c4Sopenharmony_ci    desired, success, failure)						\
267da0c48c4Sopenharmony_ci	__c11_atomic_compare_exchange_strong(object, expected, desired,	\
268da0c48c4Sopenharmony_ci	    success, failure)
269da0c48c4Sopenharmony_ci#define	atomic_compare_exchange_weak_explicit(object, expected,		\
270da0c48c4Sopenharmony_ci    desired, success, failure)						\
271da0c48c4Sopenharmony_ci	__c11_atomic_compare_exchange_weak(object, expected, desired,	\
272da0c48c4Sopenharmony_ci	    success, failure)
273da0c48c4Sopenharmony_ci#define	atomic_exchange_explicit(object, desired, order)		\
274da0c48c4Sopenharmony_ci	__c11_atomic_exchange(object, desired, order)
275da0c48c4Sopenharmony_ci#define	atomic_fetch_add_explicit(object, operand, order)		\
276da0c48c4Sopenharmony_ci	__c11_atomic_fetch_add(object, operand, order)
277da0c48c4Sopenharmony_ci#define	atomic_fetch_and_explicit(object, operand, order)		\
278da0c48c4Sopenharmony_ci	__c11_atomic_fetch_and(object, operand, order)
279da0c48c4Sopenharmony_ci#define	atomic_fetch_or_explicit(object, operand, order)		\
280da0c48c4Sopenharmony_ci	__c11_atomic_fetch_or(object, operand, order)
281da0c48c4Sopenharmony_ci#define	atomic_fetch_sub_explicit(object, operand, order)		\
282da0c48c4Sopenharmony_ci	__c11_atomic_fetch_sub(object, operand, order)
283da0c48c4Sopenharmony_ci#define	atomic_fetch_xor_explicit(object, operand, order)		\
284da0c48c4Sopenharmony_ci	__c11_atomic_fetch_xor(object, operand, order)
285da0c48c4Sopenharmony_ci#define	atomic_load_explicit(object, order)				\
286da0c48c4Sopenharmony_ci	__c11_atomic_load(object, order)
287da0c48c4Sopenharmony_ci#define	atomic_store_explicit(object, desired, order)			\
288da0c48c4Sopenharmony_ci	__c11_atomic_store(object, desired, order)
289da0c48c4Sopenharmony_ci#elif defined(__GNUC_ATOMICS)
290da0c48c4Sopenharmony_ci#define	atomic_compare_exchange_strong_explicit(object, expected,	\
291da0c48c4Sopenharmony_ci    desired, success, failure)						\
292da0c48c4Sopenharmony_ci	__atomic_compare_exchange_n(&(object)->__val, expected,		\
293da0c48c4Sopenharmony_ci	    desired, 0, success, failure)
294da0c48c4Sopenharmony_ci#define	atomic_compare_exchange_weak_explicit(object, expected,		\
295da0c48c4Sopenharmony_ci    desired, success, failure)						\
296da0c48c4Sopenharmony_ci	__atomic_compare_exchange_n(&(object)->__val, expected,		\
297da0c48c4Sopenharmony_ci	    desired, 1, success, failure)
298da0c48c4Sopenharmony_ci#define	atomic_exchange_explicit(object, desired, order)		\
299da0c48c4Sopenharmony_ci	__atomic_exchange_n(&(object)->__val, desired, order)
300da0c48c4Sopenharmony_ci#define	atomic_fetch_add_explicit(object, operand, order)		\
301da0c48c4Sopenharmony_ci	__atomic_fetch_add(&(object)->__val, operand, order)
302da0c48c4Sopenharmony_ci#define	atomic_fetch_and_explicit(object, operand, order)		\
303da0c48c4Sopenharmony_ci	__atomic_fetch_and(&(object)->__val, operand, order)
304da0c48c4Sopenharmony_ci#define	atomic_fetch_or_explicit(object, operand, order)		\
305da0c48c4Sopenharmony_ci	__atomic_fetch_or(&(object)->__val, operand, order)
306da0c48c4Sopenharmony_ci#define	atomic_fetch_sub_explicit(object, operand, order)		\
307da0c48c4Sopenharmony_ci	__atomic_fetch_sub(&(object)->__val, operand, order)
308da0c48c4Sopenharmony_ci#define	atomic_fetch_xor_explicit(object, operand, order)		\
309da0c48c4Sopenharmony_ci	__atomic_fetch_xor(&(object)->__val, operand, order)
310da0c48c4Sopenharmony_ci#define	atomic_load_explicit(object, order)				\
311da0c48c4Sopenharmony_ci	__atomic_load_n(&(object)->__val, order)
312da0c48c4Sopenharmony_ci#define	atomic_store_explicit(object, desired, order)			\
313da0c48c4Sopenharmony_ci	__atomic_store_n(&(object)->__val, desired, order)
314da0c48c4Sopenharmony_ci#else
315da0c48c4Sopenharmony_ci#define	__atomic_apply_stride(object, operand) \
316da0c48c4Sopenharmony_ci	(((__typeof__((object)->__val))0) + (operand))
317da0c48c4Sopenharmony_ci#define	atomic_compare_exchange_strong_explicit(object, expected,	\
318da0c48c4Sopenharmony_ci    desired, success, failure)	__extension__ ({			\
319da0c48c4Sopenharmony_ci	__typeof__(expected) __ep = (expected);				\
320da0c48c4Sopenharmony_ci	__typeof__(*__ep) __e = *__ep;					\
321da0c48c4Sopenharmony_ci	(void)(success); (void)(failure);				\
322da0c48c4Sopenharmony_ci	(__Bool)((*__ep = __sync_val_compare_and_swap(&(object)->__val,	\
323da0c48c4Sopenharmony_ci	    __e, desired)) == __e);					\
324da0c48c4Sopenharmony_ci})
325da0c48c4Sopenharmony_ci#define	atomic_compare_exchange_weak_explicit(object, expected,		\
326da0c48c4Sopenharmony_ci    desired, success, failure)						\
327da0c48c4Sopenharmony_ci	atomic_compare_exchange_strong_explicit(object, expected,	\
328da0c48c4Sopenharmony_ci		desired, success, failure)
329da0c48c4Sopenharmony_ci#if __has_builtin(__sync_swap)
330da0c48c4Sopenharmony_ci/* Clang provides a full-barrier atomic exchange - use it if available. */
331da0c48c4Sopenharmony_ci#define	atomic_exchange_explicit(object, desired, order)		\
332da0c48c4Sopenharmony_ci	((void)(order), __sync_swap(&(object)->__val, desired))
333da0c48c4Sopenharmony_ci#else
334da0c48c4Sopenharmony_ci/*
335da0c48c4Sopenharmony_ci * __sync_lock_test_and_set() is only an acquire barrier in theory (although in
336da0c48c4Sopenharmony_ci * practice it is usually a full barrier) so we need an explicit barrier before
337da0c48c4Sopenharmony_ci * it.
338da0c48c4Sopenharmony_ci */
339da0c48c4Sopenharmony_ci#define	atomic_exchange_explicit(object, desired, order)		\
340da0c48c4Sopenharmony_ci__extension__ ({							\
341da0c48c4Sopenharmony_ci	__typeof__(object) __o = (object);				\
342da0c48c4Sopenharmony_ci	__typeof__(desired) __d = (desired);				\
343da0c48c4Sopenharmony_ci	(void)(order);							\
344da0c48c4Sopenharmony_ci	__sync_synchronize();						\
345da0c48c4Sopenharmony_ci	__sync_lock_test_and_set(&(__o)->__val, __d);			\
346da0c48c4Sopenharmony_ci})
347da0c48c4Sopenharmony_ci#endif
348da0c48c4Sopenharmony_ci#define	atomic_fetch_add_explicit(object, operand, order)		\
349da0c48c4Sopenharmony_ci	((void)(order), __sync_fetch_and_add(&(object)->__val,		\
350da0c48c4Sopenharmony_ci	    __atomic_apply_stride(object, operand)))
351da0c48c4Sopenharmony_ci#define	atomic_fetch_and_explicit(object, operand, order)		\
352da0c48c4Sopenharmony_ci	((void)(order), __sync_fetch_and_and(&(object)->__val, operand))
353da0c48c4Sopenharmony_ci#define	atomic_fetch_or_explicit(object, operand, order)		\
354da0c48c4Sopenharmony_ci	((void)(order), __sync_fetch_and_or(&(object)->__val, operand))
355da0c48c4Sopenharmony_ci#define	atomic_fetch_sub_explicit(object, operand, order)		\
356da0c48c4Sopenharmony_ci	((void)(order), __sync_fetch_and_sub(&(object)->__val,		\
357da0c48c4Sopenharmony_ci	    __atomic_apply_stride(object, operand)))
358da0c48c4Sopenharmony_ci#define	atomic_fetch_xor_explicit(object, operand, order)		\
359da0c48c4Sopenharmony_ci	((void)(order), __sync_fetch_and_xor(&(object)->__val, operand))
360da0c48c4Sopenharmony_ci#define	atomic_load_explicit(object, order)				\
361da0c48c4Sopenharmony_ci	((void)(order), __sync_fetch_and_add(&(object)->__val, 0))
362da0c48c4Sopenharmony_ci#define	atomic_store_explicit(object, desired, order)			\
363da0c48c4Sopenharmony_ci	((void)atomic_exchange_explicit(object, desired, order))
364da0c48c4Sopenharmony_ci#endif
365da0c48c4Sopenharmony_ci
366da0c48c4Sopenharmony_ci/*
367da0c48c4Sopenharmony_ci * Convenience functions.
368da0c48c4Sopenharmony_ci *
369da0c48c4Sopenharmony_ci * Don't provide these in kernel space. In kernel space, we should be
370da0c48c4Sopenharmony_ci * disciplined enough to always provide explicit barriers.
371da0c48c4Sopenharmony_ci */
372da0c48c4Sopenharmony_ci
373da0c48c4Sopenharmony_ci#ifndef _KERNEL
374da0c48c4Sopenharmony_ci#define	atomic_compare_exchange_strong(object, expected, desired)	\
375da0c48c4Sopenharmony_ci	atomic_compare_exchange_strong_explicit(object, expected,	\
376da0c48c4Sopenharmony_ci	    desired, memory_order_seq_cst, memory_order_seq_cst)
377da0c48c4Sopenharmony_ci#define	atomic_compare_exchange_weak(object, expected, desired)		\
378da0c48c4Sopenharmony_ci	atomic_compare_exchange_weak_explicit(object, expected,		\
379da0c48c4Sopenharmony_ci	    desired, memory_order_seq_cst, memory_order_seq_cst)
380da0c48c4Sopenharmony_ci#define	atomic_exchange(object, desired)				\
381da0c48c4Sopenharmony_ci	atomic_exchange_explicit(object, desired, memory_order_seq_cst)
382da0c48c4Sopenharmony_ci#define	atomic_fetch_add(object, operand)				\
383da0c48c4Sopenharmony_ci	atomic_fetch_add_explicit(object, operand, memory_order_seq_cst)
384da0c48c4Sopenharmony_ci#define	atomic_fetch_and(object, operand)				\
385da0c48c4Sopenharmony_ci	atomic_fetch_and_explicit(object, operand, memory_order_seq_cst)
386da0c48c4Sopenharmony_ci#define	atomic_fetch_or(object, operand)				\
387da0c48c4Sopenharmony_ci	atomic_fetch_or_explicit(object, operand, memory_order_seq_cst)
388da0c48c4Sopenharmony_ci#define	atomic_fetch_sub(object, operand)				\
389da0c48c4Sopenharmony_ci	atomic_fetch_sub_explicit(object, operand, memory_order_seq_cst)
390da0c48c4Sopenharmony_ci#define	atomic_fetch_xor(object, operand)				\
391da0c48c4Sopenharmony_ci	atomic_fetch_xor_explicit(object, operand, memory_order_seq_cst)
392da0c48c4Sopenharmony_ci#define	atomic_load(object)						\
393da0c48c4Sopenharmony_ci	atomic_load_explicit(object, memory_order_seq_cst)
394da0c48c4Sopenharmony_ci#define	atomic_store(object, desired)					\
395da0c48c4Sopenharmony_ci	atomic_store_explicit(object, desired, memory_order_seq_cst)
396da0c48c4Sopenharmony_ci#endif /* !_KERNEL */
397da0c48c4Sopenharmony_ci
398da0c48c4Sopenharmony_ci/*
399da0c48c4Sopenharmony_ci * 7.17.8 Atomic flag type and operations.
400da0c48c4Sopenharmony_ci *
401da0c48c4Sopenharmony_ci * XXX: Assume atomic_bool can be used as an atomic_flag. Is there some
402da0c48c4Sopenharmony_ci * kind of compiler built-in type we could use?
403da0c48c4Sopenharmony_ci */
404da0c48c4Sopenharmony_ci
405da0c48c4Sopenharmony_citypedef struct {
406da0c48c4Sopenharmony_ci    atomic_bool	__flag;
407da0c48c4Sopenharmony_ci} atomic_flag;
408da0c48c4Sopenharmony_ci
409da0c48c4Sopenharmony_ci#define	ATOMIC_FLAG_INIT		{ ATOMIC_VAR_INIT(0) }
410da0c48c4Sopenharmony_ci
411da0c48c4Sopenharmony_cistatic __inline __Bool
412da0c48c4Sopenharmony_ciatomic_flag_test_and_set_explicit(volatile atomic_flag *__object,
413da0c48c4Sopenharmony_ci                                  memory_order __order)
414da0c48c4Sopenharmony_ci{
415da0c48c4Sopenharmony_ci    return (atomic_exchange_explicit(&__object->__flag, 1, __order));
416da0c48c4Sopenharmony_ci}
417da0c48c4Sopenharmony_ci
418da0c48c4Sopenharmony_cistatic __inline void
419da0c48c4Sopenharmony_ciatomic_flag_clear_explicit(volatile atomic_flag *__object, memory_order __order)
420da0c48c4Sopenharmony_ci{
421da0c48c4Sopenharmony_ci
422da0c48c4Sopenharmony_ci    atomic_store_explicit(&__object->__flag, 0, __order);
423da0c48c4Sopenharmony_ci}
424da0c48c4Sopenharmony_ci
425da0c48c4Sopenharmony_ci#ifndef _KERNEL
426da0c48c4Sopenharmony_cistatic __inline __Bool
427da0c48c4Sopenharmony_ciatomic_flag_test_and_set(volatile atomic_flag *__object)
428da0c48c4Sopenharmony_ci{
429da0c48c4Sopenharmony_ci
430da0c48c4Sopenharmony_ci    return (atomic_flag_test_and_set_explicit(__object,
431da0c48c4Sopenharmony_ci                                              memory_order_seq_cst));
432da0c48c4Sopenharmony_ci}
433da0c48c4Sopenharmony_ci
434da0c48c4Sopenharmony_cistatic __inline void
435da0c48c4Sopenharmony_ciatomic_flag_clear(volatile atomic_flag *__object)
436da0c48c4Sopenharmony_ci{
437da0c48c4Sopenharmony_ci
438da0c48c4Sopenharmony_ci    atomic_flag_clear_explicit(__object, memory_order_seq_cst);
439da0c48c4Sopenharmony_ci}
440da0c48c4Sopenharmony_ci#endif /* !_KERNEL */
441da0c48c4Sopenharmony_ci
442da0c48c4Sopenharmony_ci#endif /* !_STDATOMIC_H_ */