libstdc++
|
00001 // -*- C++ -*- compatibility header. 00002 00003 // Copyright (C) 2008, 2009 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 /** @file stdatomic.h 00026 * This is a Standard C++ Library header. 00027 */ 00028 00029 #include <bits/c++config.h> 00030 #include <stddef.h> 00031 #include <stdbool.h> // XXX need to define bool w/o stdbool.h in tr1/cstdbool 00032 00033 #ifndef _GLIBCXX_STDATOMIC_H 00034 #define _GLIBCXX_STDATOMIC_H 1 00035 00036 _GLIBCXX_BEGIN_NAMESPACE(std) 00037 _GLIBCXX_BEGIN_EXTERN_C 00038 00039 /** 00040 * @defgroup atomics Atomics 00041 * 00042 * Components for performing atomic operations. 00043 * @{ 00044 */ 00045 00046 /// Enumeration for memory_order 00047 typedef enum memory_order 00048 { 00049 memory_order_relaxed, 00050 memory_order_consume, 00051 memory_order_acquire, 00052 memory_order_release, 00053 memory_order_acq_rel, 00054 memory_order_seq_cst 00055 } memory_order; 00056 00057 // Base for atomic_flag. 00058 typedef struct __atomic_flag_base 00059 { 00060 bool _M_i; 00061 } __atomic_flag_base; 00062 00063 #define ATOMIC_FLAG_INIT { false } 00064 00065 /// 29.2 Lock-free Property 00066 #if defined(_GLIBCXX_ATOMIC_BUILTINS_1) && defined(_GLIBCXX_ATOMIC_BUILTINS_2) \ 00067 && defined(_GLIBCXX_ATOMIC_BUILTINS_4) && defined(_GLIBCXX_ATOMIC_BUILTINS_8) 00068 # define _GLIBCXX_ATOMIC_PROPERTY 2 00069 # define _GLIBCXX_ATOMIC_NAMESPACE __atomic2 00070 #elif defined(_GLIBCXX_ATOMIC_BUILTINS_1) 00071 # define _GLIBCXX_ATOMIC_PROPERTY 1 00072 # define _GLIBCXX_ATOMIC_NAMESPACE __atomic1 00073 #else 00074 # define _GLIBCXX_ATOMIC_PROPERTY 0 00075 # define _GLIBCXX_ATOMIC_NAMESPACE __atomic0 00076 #endif 00077 00078 #define ATOMIC_INTEGRAL_LOCK_FREE _GLIBCXX_ATOMIC_PROPERTY 00079 #define ATOMIC_ADDRESS_LOCK_FREE _GLIBCXX_ATOMIC_PROPERTY 00080 00081 // Switch atomic integral base types based on C or C++. In 00082 // addition, for "C" only provide type-generic macros for atomic 00083 // operations. (As C++ accomplishes the same thing with sets of 00084 // overloaded functions. 00085 #ifdef __cplusplus 00086 inline namespace _GLIBCXX_ATOMIC_NAMESPACE { } 00087 # include <bits/atomicfwd_cxx.h> 00088 #else 00089 # include <bits/atomicfwd_c.h> 00090 #endif 00091 00092 // Typedefs for other atomic integral types. 00093 typedef atomic_schar atomic_int_least8_t; 00094 typedef atomic_uchar atomic_uint_least8_t; 00095 typedef atomic_short atomic_int_least16_t; 00096 typedef atomic_ushort atomic_uint_least16_t; 00097 typedef atomic_int atomic_int_least32_t; 00098 typedef atomic_uint atomic_uint_least32_t; 00099 typedef atomic_llong atomic_int_least64_t; 00100 typedef atomic_ullong atomic_uint_least64_t; 00101 00102 typedef atomic_schar atomic_int_fast8_t; 00103 typedef atomic_uchar atomic_uint_fast8_t; 00104 typedef atomic_short atomic_int_fast16_t; 00105 typedef atomic_ushort atomic_uint_fast16_t; 00106 typedef atomic_int atomic_int_fast32_t; 00107 typedef atomic_uint atomic_uint_fast32_t; 00108 typedef atomic_llong atomic_int_fast64_t; 00109 typedef atomic_ullong atomic_uint_fast64_t; 00110 00111 typedef atomic_long atomic_intptr_t; 00112 typedef atomic_ulong atomic_uintptr_t; 00113 00114 typedef atomic_long atomic_ssize_t; 00115 typedef atomic_ulong atomic_size_t; 00116 00117 typedef atomic_llong atomic_intmax_t; 00118 typedef atomic_ullong atomic_uintmax_t; 00119 00120 typedef atomic_long atomic_ptrdiff_t; 00121 00122 // Accessor functions for base atomic_flag type. 00123 bool 00124 atomic_flag_test_and_set_explicit(volatile __atomic_flag_base*, memory_order); 00125 00126 inline bool 00127 atomic_flag_test_and_set(volatile __atomic_flag_base* __a) 00128 { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); } 00129 00130 void 00131 atomic_flag_clear_explicit(volatile __atomic_flag_base*, memory_order); 00132 00133 inline void 00134 atomic_flag_clear(volatile __atomic_flag_base* __a) 00135 { atomic_flag_clear_explicit(__a, memory_order_seq_cst); } 00136 00137 void 00138 __atomic_flag_wait_explicit(volatile __atomic_flag_base*, memory_order); 00139 00140 volatile __atomic_flag_base* 00141 __atomic_flag_for_address(const volatile void* __z) __attribute__((const)); 00142 00143 // Implementation specific defines. 00144 #define _ATOMIC_LOAD_(__a, __x) \ 00145 ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \ 00146 volatile atomic_flag* __g = __atomic_flag_for_address(__p); \ 00147 __atomic_flag_wait_explicit(__g, __x); \ 00148 __typeof__ _ATOMIC_MEMBER_ __r = *__p; \ 00149 atomic_flag_clear_explicit(__g, __x); \ 00150 __r; }) 00151 00152 #define _ATOMIC_STORE_(__a, __m, __x) \ 00153 ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \ 00154 __typeof__(__m) __v = (__m); \ 00155 volatile atomic_flag* __g = __atomic_flag_for_address(__p); \ 00156 __atomic_flag_wait_explicit(__g, __x); \ 00157 *__p = __v; \ 00158 atomic_flag_clear_explicit(__g, __x); \ 00159 __v; }) 00160 00161 #define _ATOMIC_MODIFY_(__a, __o, __m, __x) \ 00162 ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \ 00163 __typeof__(__m) __v = (__m); \ 00164 volatile atomic_flag* __g = __atomic_flag_for_address(__p); \ 00165 __atomic_flag_wait_explicit(__g, __x); \ 00166 __typeof__ _ATOMIC_MEMBER_ __r = *__p; \ 00167 *__p __o __v; \ 00168 atomic_flag_clear_explicit(__g, __x); \ 00169 __r; }) 00170 00171 #define _ATOMIC_CMPEXCHNG_(__a, __e, __m, __x) \ 00172 ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \ 00173 __typeof__(__e) __q = (__e); \ 00174 __typeof__(__m) __v = (__m); \ 00175 bool __r; \ 00176 volatile atomic_flag* __g = __atomic_flag_for_address(__p); \ 00177 __atomic_flag_wait_explicit(__g, __x); \ 00178 __typeof__ _ATOMIC_MEMBER_ __t__ = *__p; \ 00179 if (__t__ == *__q) { *__p = __v; __r = true; } \ 00180 else { *__q = __t__; __r = false; } \ 00181 atomic_flag_clear_explicit(__g, __x); \ 00182 __r; }) 00183 00184 // @} group atomics 00185 00186 _GLIBCXX_END_EXTERN_C 00187 _GLIBCXX_END_NAMESPACE 00188 00189 // Inject into global namespace. 00190 #ifdef __cplusplus 00191 00192 #include <cstdatomic> 00193 00194 using std::memory_order; 00195 using std::memory_order_relaxed; 00196 using std::memory_order_consume; 00197 using std::memory_order_acquire; 00198 using std::memory_order_release; 00199 using std::memory_order_acq_rel; 00200 using std::memory_order_seq_cst; 00201 using std::atomic_flag; 00202 using std::atomic_bool; 00203 using std::atomic_char; 00204 using std::atomic_schar; 00205 using std::atomic_uchar; 00206 using std::atomic_short; 00207 using std::atomic_ushort; 00208 using std::atomic_int; 00209 using std::atomic_uint; 00210 using std::atomic_long; 00211 using std::atomic_ulong; 00212 using std::atomic_llong; 00213 using std::atomic_ullong; 00214 using std::atomic_wchar_t; 00215 using std::atomic_char16_t; 00216 using std::atomic_char32_t; 00217 using std::atomic_address; 00218 using std::atomic; 00219 #endif 00220 00221 #endif