Home | History | Annotate | Download | only in include
      1 /*-
      2  * Copyright (c) 2011 Ed Schouten <ed (at) FreeBSD.org>
      3  *                    David Chisnall <theraven (at) 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 
     35 #if defined(__GNUC__) && !defined(__GNUC_PREREQ)
     36 /* Duplicate definition here, since the mingw sys/cdefs.h omits the  */
     37 /* definition, and this needs to be usable there.                    */
     38 #define	__GNUC_PREREQ(x, y)    \
     39 	((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || (__GNUC__ > (x)))
     40 #endif /* __GNUC__ && ... */
     41 
     42 #if defined(__cplusplus) && __cplusplus >= 201103L && defined(_USING_LIBCXX)
     43 # ifdef __clang__
     44 #  if __has_feature(cxx_atomic)
     45 #   define _STDATOMIC_HAVE_ATOMIC
     46 #  endif
     47 # else /* gcc */
     48 #  if __GNUC_PREREQ(4, 7)
     49 #   define _STDATOMIC_HAVE_ATOMIC
     50 #  endif
     51 # endif
     52 #endif
     53 
     54 #ifdef _STDATOMIC_HAVE_ATOMIC
     55 
     56 /* We have a usable C++ <atomic>; use it instead.  */
     57 
     58 #include <atomic>
     59 
     60 #undef _Atomic
     61         /* Also defined by <atomic> for gcc.  But not used in macros. */
     62         /* Also a clang intrinsic.                                    */
     63         /* Should not be used by client code before this file is      */
     64         /* included.  The definitions in <atomic> themselves see      */
     65         /* the old definition, as they should.                        */
     66         /* Client code sees the following definition.                 */
     67 
     68 #define _Atomic(t) std::atomic<t>
     69 
     70 using std::atomic_is_lock_free;
     71 using std::atomic_init;
     72 using std::atomic_store;
     73 using std::atomic_store_explicit;
     74 using std::atomic_load;
     75 using std::atomic_load_explicit;
     76 using std::atomic_exchange;
     77 using std::atomic_exchange_explicit;
     78 using std::atomic_compare_exchange_strong;
     79 using std::atomic_compare_exchange_strong_explicit;
     80 using std::atomic_compare_exchange_weak;
     81 using std::atomic_compare_exchange_weak_explicit;
     82 using std::atomic_fetch_add;
     83 using std::atomic_fetch_add_explicit;
     84 using std::atomic_fetch_sub;
     85 using std::atomic_fetch_sub_explicit;
     86 using std::atomic_fetch_or;
     87 using std::atomic_fetch_or_explicit;
     88 using std::atomic_fetch_xor;
     89 using std::atomic_fetch_xor_explicit;
     90 using std::atomic_fetch_and;
     91 using std::atomic_fetch_and_explicit;
     92 using std::atomic_thread_fence;
     93 using std::atomic_signal_fence;
     94 
     95 using std::memory_order;
     96 using std::memory_order_relaxed;
     97 using std::memory_order_consume;
     98 using std::memory_order_acquire;
     99 using std::memory_order_release;
    100 using std::memory_order_acq_rel;
    101 using std::memory_order_seq_cst;
    102 
    103 using std::atomic_bool;
    104 using std::atomic_char;
    105 using std::atomic_schar;
    106 using std::atomic_uchar;
    107 using std::atomic_short;
    108 using std::atomic_ushort;
    109 using std::atomic_int;
    110 using std::atomic_uint;
    111 using std::atomic_long;
    112 using std::atomic_ulong;
    113 using std::atomic_llong;
    114 using std::atomic_ullong;
    115 using std::atomic_char16_t;
    116 using std::atomic_char32_t;
    117 using std::atomic_wchar_t;
    118 using std::atomic_int_least8_t;
    119 using std::atomic_uint_least8_t;
    120 using std::atomic_int_least16_t;
    121 using std::atomic_uint_least16_t;
    122 using std::atomic_int_least32_t;
    123 using std::atomic_uint_least32_t;
    124 using std::atomic_int_least64_t;
    125 using std::atomic_uint_least64_t;
    126 using std::atomic_int_fast8_t;
    127 using std::atomic_uint_fast8_t;
    128 using std::atomic_int_fast16_t;
    129 using std::atomic_uint_fast16_t;
    130 using std::atomic_int_fast32_t;
    131 using std::atomic_uint_fast32_t;
    132 using std::atomic_int_fast64_t;
    133 using std::atomic_uint_fast64_t;
    134 using std::atomic_intptr_t;
    135 using std::atomic_uintptr_t;
    136 using std::atomic_size_t;
    137 using std::atomic_ptrdiff_t;
    138 using std::atomic_intmax_t;
    139 using std::atomic_uintmax_t;
    140 
    141 #else /* <atomic> unavailable, possibly because this is C, not C++ */
    142 
    143 #include <sys/types.h>
    144 #include <stdbool.h>
    145 
    146 /*
    147  * C: Do it ourselves.
    148  * Note that the runtime representation defined here should be compatible
    149  * with the C++ one, i.e. an _Atomic(T) needs to contain the same
    150  * bits as a T.
    151  */
    152 
    153 #include <stddef.h>  /* For ptrdiff_t.                          */
    154 #include <stdint.h>  /* TODO: Should pollute namespace less.    */
    155 #if __STDC_VERSION__ >= 201112L
    156 # include <uchar.h>  /* For char16_t and char32_t.              */
    157 #endif
    158 
    159 #ifdef __clang__
    160 # if __has_extension(c_atomic) || __has_extension(cxx_atomic)
    161 #  define       __CLANG_ATOMICS
    162 # else
    163 #  error "stdatomic.h does not support your compiler"
    164 # endif
    165 # if __has_builtin(__sync_swap)
    166 #  define __HAS_BUILTIN_SYNC_SWAP
    167 # endif
    168 #else
    169 # if __GNUC_PREREQ(4, 7)
    170 #  define	__GNUC_ATOMICS
    171 # else
    172 #  define	__SYNC_ATOMICS
    173 #  ifdef __cplusplus
    174 #   define       __ATOMICS_AVOID_DOT_INIT
    175 #  endif
    176 # endif
    177 #endif
    178 
    179 /*
    180  * 7.17.1 Atomic lock-free macros.
    181  */
    182 
    183 #ifdef __GCC_ATOMIC_BOOL_LOCK_FREE
    184 #define	ATOMIC_BOOL_LOCK_FREE		__GCC_ATOMIC_BOOL_LOCK_FREE
    185 #elif defined(__SYNC_ATOMICS)
    186 #define	ATOMIC_BOOL_LOCK_FREE           2 /* For all modern platforms */
    187 #endif
    188 #ifdef __GCC_ATOMIC_CHAR_LOCK_FREE
    189 #define	ATOMIC_CHAR_LOCK_FREE		__GCC_ATOMIC_CHAR_LOCK_FREE
    190 #elif defined(__SYNC_ATOMICS)
    191 #define	ATOMIC_CHAR_LOCK_FREE           2
    192 #endif
    193 #ifdef __GCC_ATOMIC_CHAR16_T_LOCK_FREE
    194 #define	ATOMIC_CHAR16_T_LOCK_FREE	__GCC_ATOMIC_CHAR16_T_LOCK_FREE
    195 #elif defined(__SYNC_ATOMICS)
    196 #define	ATOMIC_CHAR16_T_LOCK_FREE       2
    197 #endif
    198 #ifdef __GCC_ATOMIC_CHAR32_T_LOCK_FREE
    199 #define	ATOMIC_CHAR32_T_LOCK_FREE	__GCC_ATOMIC_CHAR32_T_LOCK_FREE
    200 #elif defined(__SYNC_ATOMICS)
    201 #define	ATOMIC_CHAR32_T_LOCK_FREE       2
    202 #endif
    203 #ifdef __GCC_ATOMIC_WCHAR_T_LOCK_FREE
    204 #define	ATOMIC_WCHAR_T_LOCK_FREE	__GCC_ATOMIC_WCHAR_T_LOCK_FREE
    205 #elif defined(__SYNC_ATOMICS)
    206 #define	ATOMIC_WCHAR_T_LOCK_FREE        2
    207 #endif
    208 #ifdef __GCC_ATOMIC_SHORT_LOCK_FREE
    209 #define	ATOMIC_SHORT_LOCK_FREE		__GCC_ATOMIC_SHORT_LOCK_FREE
    210 #elif defined(__SYNC_ATOMICS)
    211 #define	ATOMIC_SHORT_LOCK_FREE          2
    212 #endif
    213 #ifdef __GCC_ATOMIC_INT_LOCK_FREE
    214 #define	ATOMIC_INT_LOCK_FREE		__GCC_ATOMIC_INT_LOCK_FREE
    215 #elif defined(__SYNC_ATOMICS)
    216 #define	ATOMIC_INT_LOCK_FREE            2
    217 #endif
    218 #ifdef __GCC_ATOMIC_LONG_LOCK_FREE
    219 #define	ATOMIC_LONG_LOCK_FREE		__GCC_ATOMIC_LONG_LOCK_FREE
    220 #elif defined(__SYNC_ATOMICS)
    221 #define	ATOMIC_LONG_LOCK_FREE           2
    222 #endif
    223 #ifdef __GCC_ATOMIC_LLONG_LOCK_FREE
    224 #define	ATOMIC_LLONG_LOCK_FREE		__GCC_ATOMIC_LLONG_LOCK_FREE
    225 #elif defined(__SYNC_ATOMICS)
    226 #define	ATOMIC_LLONG_LOCK_FREE          1 /* maybe */
    227 #endif
    228 #ifdef __GCC_ATOMIC_POINTER_LOCK_FREE
    229 #define	ATOMIC_POINTER_LOCK_FREE	__GCC_ATOMIC_POINTER_LOCK_FREE
    230 #elif defined(__SYNC_ATOMICS)
    231 #define	ATOMIC_POINTER_LOCK_FREE        2
    232 #endif
    233 
    234 /*
    235  * 7.17.2 Initialization.
    236  */
    237 
    238 #if defined(__CLANG_ATOMICS)
    239 #define	ATOMIC_VAR_INIT(value)		(value)
    240 #define	atomic_init(obj, value)		__c11_atomic_init(obj, value)
    241 #else
    242 #ifdef __ATOMICS_AVOID_DOT_INIT
    243 #define	ATOMIC_VAR_INIT(value)		{ value }
    244 #else
    245 #define	ATOMIC_VAR_INIT(value)		{ .__val = (value) }
    246 #endif
    247 #define	atomic_init(obj, value)		((void)((obj)->__val = (value)))
    248 #endif
    249 
    250 /*
    251  * Clang and recent GCC both provide predefined macros for the memory
    252  * orderings.  If we are using a compiler that doesn't define them, use the
    253  * clang values - these will be ignored in the fallback path.
    254  */
    255 
    256 #ifndef __ATOMIC_RELAXED
    257 #define __ATOMIC_RELAXED		0
    258 #endif
    259 #ifndef __ATOMIC_CONSUME
    260 #define __ATOMIC_CONSUME		1
    261 #endif
    262 #ifndef __ATOMIC_ACQUIRE
    263 #define __ATOMIC_ACQUIRE		2
    264 #endif
    265 #ifndef __ATOMIC_RELEASE
    266 #define __ATOMIC_RELEASE		3
    267 #endif
    268 #ifndef __ATOMIC_ACQ_REL
    269 #define __ATOMIC_ACQ_REL		4
    270 #endif
    271 #ifndef __ATOMIC_SEQ_CST
    272 #define __ATOMIC_SEQ_CST		5
    273 #endif
    274 
    275 /*
    276  * 7.17.3 Order and consistency.
    277  *
    278  * The memory_order_* constants that denote the barrier behaviour of the
    279  * atomic operations.
    280  * The enum values must be identical to those used by the
    281  * C++ <atomic> header.
    282  */
    283 
    284 typedef enum {
    285 	memory_order_relaxed = __ATOMIC_RELAXED,
    286 	memory_order_consume = __ATOMIC_CONSUME,
    287 	memory_order_acquire = __ATOMIC_ACQUIRE,
    288 	memory_order_release = __ATOMIC_RELEASE,
    289 	memory_order_acq_rel = __ATOMIC_ACQ_REL,
    290 	memory_order_seq_cst = __ATOMIC_SEQ_CST
    291 } memory_order;
    292 
    293 /*
    294  * 7.17.4 Fences.
    295  */
    296 
    297 static __inline void
    298 atomic_thread_fence(memory_order __order __attribute__((unused)))
    299 {
    300 
    301 #ifdef __CLANG_ATOMICS
    302 	__c11_atomic_thread_fence(__order);
    303 #elif defined(__GNUC_ATOMICS)
    304 	__atomic_thread_fence(__order);
    305 #else
    306 	__sync_synchronize();
    307 #endif
    308 }
    309 
    310 static __inline void
    311 atomic_signal_fence(memory_order __order __attribute__((unused)))
    312 {
    313 
    314 #ifdef __CLANG_ATOMICS
    315 	__c11_atomic_signal_fence(__order);
    316 #elif defined(__GNUC_ATOMICS)
    317 	__atomic_signal_fence(__order);
    318 #else
    319 	__asm volatile ("" ::: "memory");
    320 #endif
    321 }
    322 
    323 /*
    324  * 7.17.5 Lock-free property.
    325  */
    326 
    327 #if defined(_KERNEL)
    328 /* Atomics in kernelspace are always lock-free. */
    329 #define	atomic_is_lock_free(obj) \
    330 	((void)(obj), (_Bool)1)
    331 #elif defined(__CLANG_ATOMICS)
    332 #define	atomic_is_lock_free(obj) \
    333 	__c11_atomic_is_lock_free(sizeof(*(obj)))
    334 #elif defined(__GNUC_ATOMICS)
    335 #define	atomic_is_lock_free(obj) \
    336 	__atomic_is_lock_free(sizeof((obj)->__val), &(obj)->__val)
    337 #else
    338 #define	atomic_is_lock_free(obj) \
    339 	((void)(obj), sizeof((obj)->__val) <= sizeof(void *))
    340 #endif
    341 
    342 /*
    343  * 7.17.6 Atomic integer types.
    344  */
    345 
    346 #ifndef __CLANG_ATOMICS
    347 /*
    348  * No native support for _Atomic(). Place object in structure to prevent
    349  * most forms of direct non-atomic access.
    350  */
    351 #define _Atomic(T)              struct { T volatile __val; }
    352 #endif
    353 
    354 typedef _Atomic(bool)			atomic_bool;
    355 typedef _Atomic(char)			atomic_char;
    356 typedef _Atomic(signed char)		atomic_schar;
    357 typedef _Atomic(unsigned char)		atomic_uchar;
    358 typedef _Atomic(short)			atomic_short;
    359 typedef _Atomic(unsigned short)		atomic_ushort;
    360 typedef _Atomic(int)			atomic_int;
    361 typedef _Atomic(unsigned int)		atomic_uint;
    362 typedef _Atomic(long)			atomic_long;
    363 typedef _Atomic(unsigned long)		atomic_ulong;
    364 typedef _Atomic(long long)		atomic_llong;
    365 typedef _Atomic(unsigned long long)	atomic_ullong;
    366 #if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L
    367   typedef _Atomic(char16_t)		atomic_char16_t;
    368   typedef _Atomic(char32_t)		atomic_char32_t;
    369 #endif
    370 typedef _Atomic(wchar_t)		atomic_wchar_t;
    371 typedef _Atomic(int_least8_t)		atomic_int_least8_t;
    372 typedef _Atomic(uint_least8_t)	atomic_uint_least8_t;
    373 typedef _Atomic(int_least16_t)	atomic_int_least16_t;
    374 typedef _Atomic(uint_least16_t)	atomic_uint_least16_t;
    375 typedef _Atomic(int_least32_t)	atomic_int_least32_t;
    376 typedef _Atomic(uint_least32_t)	atomic_uint_least32_t;
    377 typedef _Atomic(int_least64_t)	atomic_int_least64_t;
    378 typedef _Atomic(uint_least64_t)	atomic_uint_least64_t;
    379 typedef _Atomic(int_fast8_t)		atomic_int_fast8_t;
    380 typedef _Atomic(uint_fast8_t)		atomic_uint_fast8_t;
    381 typedef _Atomic(int_fast16_t)		atomic_int_fast16_t;
    382 typedef _Atomic(uint_fast16_t)	atomic_uint_fast16_t;
    383 typedef _Atomic(int_fast32_t)		atomic_int_fast32_t;
    384 typedef _Atomic(uint_fast32_t)	atomic_uint_fast32_t;
    385 typedef _Atomic(int_fast64_t)		atomic_int_fast64_t;
    386 typedef _Atomic(uint_fast64_t)	atomic_uint_fast64_t;
    387 typedef _Atomic(intptr_t)		atomic_intptr_t;
    388 typedef _Atomic(uintptr_t)		atomic_uintptr_t;
    389 typedef _Atomic(size_t)		atomic_size_t;
    390 typedef _Atomic(ptrdiff_t)		atomic_ptrdiff_t;
    391 typedef _Atomic(intmax_t)		atomic_intmax_t;
    392 typedef _Atomic(uintmax_t)		atomic_uintmax_t;
    393 
    394 /*
    395  * 7.17.7 Operations on atomic types.
    396  */
    397 
    398 /*
    399  * Compiler-specific operations.
    400  */
    401 
    402 #if defined(__CLANG_ATOMICS)
    403 #define	atomic_compare_exchange_strong_explicit(object, expected,	\
    404     desired, success, failure)						\
    405 	__c11_atomic_compare_exchange_strong(object, expected, desired,	\
    406 	    success, failure)
    407 #define	atomic_compare_exchange_weak_explicit(object, expected,		\
    408     desired, success, failure)						\
    409 	__c11_atomic_compare_exchange_weak(object, expected, desired,	\
    410 	    success, failure)
    411 #define	atomic_exchange_explicit(object, desired, order)		\
    412 	__c11_atomic_exchange(object, desired, order)
    413 #define	atomic_fetch_add_explicit(object, operand, order)		\
    414 	__c11_atomic_fetch_add(object, operand, order)
    415 #define	atomic_fetch_and_explicit(object, operand, order)		\
    416 	__c11_atomic_fetch_and(object, operand, order)
    417 #define	atomic_fetch_or_explicit(object, operand, order)		\
    418 	__c11_atomic_fetch_or(object, operand, order)
    419 #define	atomic_fetch_sub_explicit(object, operand, order)		\
    420 	__c11_atomic_fetch_sub(object, operand, order)
    421 #define	atomic_fetch_xor_explicit(object, operand, order)		\
    422 	__c11_atomic_fetch_xor(object, operand, order)
    423 #define	atomic_load_explicit(object, order)				\
    424 	__c11_atomic_load(object, order)
    425 #define	atomic_store_explicit(object, desired, order)			\
    426 	__c11_atomic_store(object, desired, order)
    427 #elif defined(__GNUC_ATOMICS)
    428 #define	atomic_compare_exchange_strong_explicit(object, expected,	\
    429     desired, success, failure)						\
    430 	__atomic_compare_exchange_n(&(object)->__val, expected,		\
    431 	    desired, 0, success, failure)
    432 #define	atomic_compare_exchange_weak_explicit(object, expected,		\
    433     desired, success, failure)						\
    434 	__atomic_compare_exchange_n(&(object)->__val, expected,		\
    435 	    desired, 1, success, failure)
    436 #define	atomic_exchange_explicit(object, desired, order)		\
    437 	__atomic_exchange_n(&(object)->__val, desired, order)
    438 #define	atomic_fetch_add_explicit(object, operand, order)		\
    439 	__atomic_fetch_add(&(object)->__val, operand, order)
    440 #define	atomic_fetch_and_explicit(object, operand, order)		\
    441 	__atomic_fetch_and(&(object)->__val, operand, order)
    442 #define	atomic_fetch_or_explicit(object, operand, order)		\
    443 	__atomic_fetch_or(&(object)->__val, operand, order)
    444 #define	atomic_fetch_sub_explicit(object, operand, order)		\
    445 	__atomic_fetch_sub(&(object)->__val, operand, order)
    446 #define	atomic_fetch_xor_explicit(object, operand, order)		\
    447 	__atomic_fetch_xor(&(object)->__val, operand, order)
    448 #define	atomic_load_explicit(object, order)				\
    449 	__atomic_load_n(&(object)->__val, order)
    450 #define	atomic_store_explicit(object, desired, order)			\
    451 	__atomic_store_n(&(object)->__val, desired, order)
    452 #else
    453 #define	__atomic_apply_stride(object, operand) \
    454 	(((__typeof__((object)->__val))0) + (operand))
    455 #define	atomic_compare_exchange_strong_explicit(object, expected,	\
    456     desired, success, failure)	__extension__ ({			\
    457 	__typeof__(expected) __ep = (expected);				\
    458 	__typeof__(*__ep) __e = *__ep;					\
    459 	(void)(success); (void)(failure);				\
    460 	(bool)((*__ep = __sync_val_compare_and_swap(&(object)->__val,	\
    461 	    __e, desired)) == __e);					\
    462 })
    463 #define	atomic_compare_exchange_weak_explicit(object, expected,		\
    464     desired, success, failure)						\
    465 	atomic_compare_exchange_strong_explicit(object, expected,	\
    466 		desired, success, failure)
    467 #ifdef __HAS_BUILTIN_SYNC_SWAP
    468 /* Clang provides a full-barrier atomic exchange - use it if available. */
    469 #define	atomic_exchange_explicit(object, desired, order)		\
    470 	((void)(order), __sync_swap(&(object)->__val, desired))
    471 #else
    472 /*
    473  * __sync_lock_test_and_set() is only an acquire barrier in theory (although in
    474  * practice it is usually a full barrier) so we need an explicit barrier before
    475  * it.
    476  */
    477 #define	atomic_exchange_explicit(object, desired, order)		\
    478 __extension__ ({							\
    479 	__typeof__(object) __o = (object);				\
    480 	__typeof__(desired) __d = (desired);				\
    481 	(void)(order);							\
    482 	__sync_synchronize();						\
    483 	__sync_lock_test_and_set(&(__o)->__val, __d);			\
    484 })
    485 #endif
    486 #define	atomic_fetch_add_explicit(object, operand, order)		\
    487 	((void)(order), __sync_fetch_and_add(&(object)->__val,		\
    488 	    __atomic_apply_stride(object, operand)))
    489 #define	atomic_fetch_and_explicit(object, operand, order)		\
    490 	((void)(order), __sync_fetch_and_and(&(object)->__val, operand))
    491 #define	atomic_fetch_or_explicit(object, operand, order)		\
    492 	((void)(order), __sync_fetch_and_or(&(object)->__val, operand))
    493 #define	atomic_fetch_sub_explicit(object, operand, order)		\
    494 	((void)(order), __sync_fetch_and_sub(&(object)->__val,		\
    495 	    __atomic_apply_stride(object, operand)))
    496 #define	atomic_fetch_xor_explicit(object, operand, order)		\
    497 	((void)(order), __sync_fetch_and_xor(&(object)->__val, operand))
    498 #define	atomic_load_explicit(object, order)				\
    499 	((void)(order), __sync_fetch_and_add(&(object)->__val, 0))
    500 #define	atomic_store_explicit(object, desired, order)			\
    501 	((void)atomic_exchange_explicit(object, desired, order))
    502 #endif
    503 
    504 /*
    505  * Convenience functions.
    506  *
    507  * Don't provide these in kernel space. In kernel space, we should be
    508  * disciplined enough to always provide explicit barriers.
    509  */
    510 
    511 #ifndef _KERNEL
    512 #define	atomic_compare_exchange_strong(object, expected, desired)	\
    513 	atomic_compare_exchange_strong_explicit(object, expected,	\
    514 	    desired, memory_order_seq_cst, memory_order_seq_cst)
    515 #define	atomic_compare_exchange_weak(object, expected, desired)		\
    516 	atomic_compare_exchange_weak_explicit(object, expected,		\
    517 	    desired, memory_order_seq_cst, memory_order_seq_cst)
    518 #define	atomic_exchange(object, desired)				\
    519 	atomic_exchange_explicit(object, desired, memory_order_seq_cst)
    520 #define	atomic_fetch_add(object, operand)				\
    521 	atomic_fetch_add_explicit(object, operand, memory_order_seq_cst)
    522 #define	atomic_fetch_and(object, operand)				\
    523 	atomic_fetch_and_explicit(object, operand, memory_order_seq_cst)
    524 #define	atomic_fetch_or(object, operand)				\
    525 	atomic_fetch_or_explicit(object, operand, memory_order_seq_cst)
    526 #define	atomic_fetch_sub(object, operand)				\
    527 	atomic_fetch_sub_explicit(object, operand, memory_order_seq_cst)
    528 #define	atomic_fetch_xor(object, operand)				\
    529 	atomic_fetch_xor_explicit(object, operand, memory_order_seq_cst)
    530 #define	atomic_load(object)						\
    531 	atomic_load_explicit(object, memory_order_seq_cst)
    532 #define	atomic_store(object, desired)					\
    533 	atomic_store_explicit(object, desired, memory_order_seq_cst)
    534 #endif /* !_KERNEL */
    535 
    536 /*
    537  * 7.17.8 Atomic flag type and operations.
    538  *
    539  * XXX: Assume atomic_bool can be used as an atomic_flag. Is there some
    540  * kind of compiler built-in type we could use?
    541  */
    542 
    543 typedef struct {
    544 	atomic_bool	__flag;
    545 } atomic_flag;
    546 
    547 #define	ATOMIC_FLAG_INIT		{ ATOMIC_VAR_INIT(false) }
    548 
    549 static __inline bool
    550 atomic_flag_test_and_set_explicit(volatile atomic_flag *__object,
    551     memory_order __order)
    552 {
    553 	return (atomic_exchange_explicit(&__object->__flag, 1, __order));
    554 }
    555 
    556 static __inline void
    557 atomic_flag_clear_explicit(volatile atomic_flag *__object, memory_order __order)
    558 {
    559 
    560 	atomic_store_explicit(&__object->__flag, 0, __order);
    561 }
    562 
    563 #ifndef _KERNEL
    564 static __inline bool
    565 atomic_flag_test_and_set(volatile atomic_flag *__object)
    566 {
    567 
    568 	return (atomic_flag_test_and_set_explicit(__object,
    569 	    memory_order_seq_cst));
    570 }
    571 
    572 static __inline void
    573 atomic_flag_clear(volatile atomic_flag *__object)
    574 {
    575 
    576 	atomic_flag_clear_explicit(__object, memory_order_seq_cst);
    577 }
    578 #endif /* !_KERNEL */
    579 
    580 #endif /* <atomic> unavailable */
    581 
    582 #endif /* !_STDATOMIC_H_ */
    583