// -*- C++ -*- compatibility header. // Copyright (C) 2008, 2009 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file stdatomic.h * This is a Standard C++ Library header. */ #include #include #include // XXX need to define bool w/o stdbool.h in tr1/cstdbool #ifndef _GLIBCXX_STDATOMIC_H #define _GLIBCXX_STDATOMIC_H 1 _GLIBCXX_BEGIN_NAMESPACE(std) _GLIBCXX_BEGIN_EXTERN_C /** * @defgroup atomics Atomics * * Components for performing atomic operations. * @{ */ /// Enumeration for memory_order typedef enum memory_order { memory_order_relaxed, memory_order_consume, memory_order_acquire, memory_order_release, memory_order_acq_rel, memory_order_seq_cst } memory_order; // Base for atomic_flag. typedef struct __atomic_flag_base { bool _M_i; } __atomic_flag_base; #define ATOMIC_FLAG_INIT { false } /// 29.2 Lock-free Property #if defined(_GLIBCXX_ATOMIC_BUILTINS_1) && defined(_GLIBCXX_ATOMIC_BUILTINS_2) \ && defined(_GLIBCXX_ATOMIC_BUILTINS_4) && defined(_GLIBCXX_ATOMIC_BUILTINS_8) # define _GLIBCXX_ATOMIC_PROPERTY 2 # define _GLIBCXX_ATOMIC_NAMESPACE __atomic2 #elif defined(_GLIBCXX_ATOMIC_BUILTINS_1) # define _GLIBCXX_ATOMIC_PROPERTY 1 # define _GLIBCXX_ATOMIC_NAMESPACE __atomic1 #else # define _GLIBCXX_ATOMIC_PROPERTY 0 # define _GLIBCXX_ATOMIC_NAMESPACE __atomic0 #endif #define ATOMIC_INTEGRAL_LOCK_FREE _GLIBCXX_ATOMIC_PROPERTY #define ATOMIC_ADDRESS_LOCK_FREE _GLIBCXX_ATOMIC_PROPERTY // Switch atomic integral base types based on C or C++. In // addition, for "C" only provide type-generic macros for atomic // operations. (As C++ accomplishes the same thing with sets of // overloaded functions. #ifdef __cplusplus inline namespace _GLIBCXX_ATOMIC_NAMESPACE { } # include #else # include #endif // Typedefs for other atomic integral types. typedef atomic_schar atomic_int_least8_t; typedef atomic_uchar atomic_uint_least8_t; typedef atomic_short atomic_int_least16_t; typedef atomic_ushort atomic_uint_least16_t; typedef atomic_int atomic_int_least32_t; typedef atomic_uint atomic_uint_least32_t; typedef atomic_llong atomic_int_least64_t; typedef atomic_ullong atomic_uint_least64_t; typedef atomic_schar atomic_int_fast8_t; typedef atomic_uchar atomic_uint_fast8_t; typedef atomic_short atomic_int_fast16_t; typedef atomic_ushort atomic_uint_fast16_t; typedef atomic_int atomic_int_fast32_t; typedef atomic_uint atomic_uint_fast32_t; typedef atomic_llong atomic_int_fast64_t; typedef atomic_ullong atomic_uint_fast64_t; typedef atomic_long atomic_intptr_t; typedef atomic_ulong atomic_uintptr_t; typedef atomic_long atomic_ssize_t; typedef atomic_ulong atomic_size_t; typedef atomic_llong atomic_intmax_t; typedef atomic_ullong atomic_uintmax_t; typedef atomic_long atomic_ptrdiff_t; // Accessor functions for base atomic_flag type. bool atomic_flag_test_and_set_explicit(volatile __atomic_flag_base*, memory_order); inline bool atomic_flag_test_and_set(volatile __atomic_flag_base* __a) { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); } void atomic_flag_clear_explicit(volatile __atomic_flag_base*, memory_order); inline void atomic_flag_clear(volatile __atomic_flag_base* __a) { atomic_flag_clear_explicit(__a, memory_order_seq_cst); } void __atomic_flag_wait_explicit(volatile __atomic_flag_base*, memory_order); volatile __atomic_flag_base* __atomic_flag_for_address(const volatile void* __z) __attribute__((const)); // Implementation specific defines. #define _ATOMIC_LOAD_(__a, __x) \ ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \ volatile atomic_flag* __g = __atomic_flag_for_address(__p); \ __atomic_flag_wait_explicit(__g, __x); \ __typeof__ _ATOMIC_MEMBER_ __r = *__p; \ atomic_flag_clear_explicit(__g, __x); \ __r; }) #define _ATOMIC_STORE_(__a, __m, __x) \ ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \ __typeof__(__m) __v = (__m); \ volatile atomic_flag* __g = __atomic_flag_for_address(__p); \ __atomic_flag_wait_explicit(__g, __x); \ *__p = __v; \ atomic_flag_clear_explicit(__g, __x); \ __v; }) #define _ATOMIC_MODIFY_(__a, __o, __m, __x) \ ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \ __typeof__(__m) __v = (__m); \ volatile atomic_flag* __g = __atomic_flag_for_address(__p); \ __atomic_flag_wait_explicit(__g, __x); \ __typeof__ _ATOMIC_MEMBER_ __r = *__p; \ *__p __o __v; \ atomic_flag_clear_explicit(__g, __x); \ __r; }) #define _ATOMIC_CMPEXCHNG_(__a, __e, __m, __x) \ ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \ __typeof__(__e) __q = (__e); \ __typeof__(__m) __v = (__m); \ bool __r; \ volatile atomic_flag* __g = __atomic_flag_for_address(__p); \ __atomic_flag_wait_explicit(__g, __x); \ __typeof__ _ATOMIC_MEMBER_ __t__ = *__p; \ if (__t__ == *__q) { *__p = __v; __r = true; } \ else { *__q = __t__; __r = false; } \ atomic_flag_clear_explicit(__g, __x); \ __r; }) // @} group atomics _GLIBCXX_END_EXTERN_C _GLIBCXX_END_NAMESPACE // Inject into global namespace. #ifdef __cplusplus #include using std::memory_order; using std::memory_order_relaxed; using std::memory_order_consume; using std::memory_order_acquire; using std::memory_order_release; using std::memory_order_acq_rel; using std::memory_order_seq_cst; using std::atomic_flag; using std::atomic_bool; using std::atomic_char; using std::atomic_schar; using std::atomic_uchar; using std::atomic_short; using std::atomic_ushort; using std::atomic_int; using std::atomic_uint; using std::atomic_long; using std::atomic_ulong; using std::atomic_llong; using std::atomic_ullong; using std::atomic_wchar_t; using std::atomic_char16_t; using std::atomic_char32_t; using std::atomic_address; using std::atomic; #endif #endif