1 // -*- C++ -*- compatibility header. 2 3 // Copyright (C) 2008, 2009 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 /** @file stdatomic.h 26 * This is a Standard C++ Library header. 27 */ 28 29 #include <bits/c++config.h> 30 #include <stddef.h> 31 #include <stdbool.h> // XXX need to define bool w/o stdbool.h in tr1/cstdbool 32 33 #ifndef _GLIBCXX_STDATOMIC_H 34 #define _GLIBCXX_STDATOMIC_H 1 35 36 _GLIBCXX_BEGIN_NAMESPACE(std) 37 _GLIBCXX_BEGIN_EXTERN_C 38 39 /** 40 * @defgroup atomics Atomics 41 * 42 * Components for performing atomic operations. 43 * @{ 44 */ 45 46 /// Enumeration for memory_order 47 typedef enum memory_order 48 { 49 memory_order_relaxed, 50 memory_order_consume, 51 memory_order_acquire, 52 memory_order_release, 53 memory_order_acq_rel, 54 memory_order_seq_cst 55 } memory_order; 56 57 // Base for atomic_flag. 58 typedef struct __atomic_flag_base 59 { 60 bool _M_i; 61 } __atomic_flag_base; 62 63 #define ATOMIC_FLAG_INIT { false } 64 65 /// 29.2 Lock-free Property 66 #if defined(_GLIBCXX_ATOMIC_BUILTINS_1) && defined(_GLIBCXX_ATOMIC_BUILTINS_2) \ 67 && defined(_GLIBCXX_ATOMIC_BUILTINS_4) && defined(_GLIBCXX_ATOMIC_BUILTINS_8) 68 # define _GLIBCXX_ATOMIC_PROPERTY 2 69 # define _GLIBCXX_ATOMIC_NAMESPACE __atomic2 70 #elif defined(_GLIBCXX_ATOMIC_BUILTINS_1) 71 # define _GLIBCXX_ATOMIC_PROPERTY 1 72 # define _GLIBCXX_ATOMIC_NAMESPACE __atomic1 73 #else 74 # define _GLIBCXX_ATOMIC_PROPERTY 0 75 # define _GLIBCXX_ATOMIC_NAMESPACE __atomic0 76 #endif 77 78 #define ATOMIC_INTEGRAL_LOCK_FREE _GLIBCXX_ATOMIC_PROPERTY 79 #define ATOMIC_ADDRESS_LOCK_FREE _GLIBCXX_ATOMIC_PROPERTY 80 81 // Switch atomic integral base types based on C or C++. In 82 // addition, for "C" only provide type-generic macros for atomic 83 // operations. (As C++ accomplishes the same thing with sets of 84 // overloaded functions. 85 #ifdef __cplusplus 86 inline namespace _GLIBCXX_ATOMIC_NAMESPACE { } 87 # include <bits/atomicfwd_cxx.h> 88 #else 89 # include <bits/atomicfwd_c.h> 90 #endif 91 92 // Typedefs for other atomic integral types. 93 typedef atomic_schar atomic_int_least8_t; 94 typedef atomic_uchar atomic_uint_least8_t; 95 typedef atomic_short atomic_int_least16_t; 96 typedef atomic_ushort atomic_uint_least16_t; 97 typedef atomic_int atomic_int_least32_t; 98 typedef atomic_uint atomic_uint_least32_t; 99 typedef atomic_llong atomic_int_least64_t; 100 typedef atomic_ullong atomic_uint_least64_t; 101 102 typedef atomic_schar atomic_int_fast8_t; 103 typedef atomic_uchar atomic_uint_fast8_t; 104 typedef atomic_short atomic_int_fast16_t; 105 typedef atomic_ushort atomic_uint_fast16_t; 106 typedef atomic_int atomic_int_fast32_t; 107 typedef atomic_uint atomic_uint_fast32_t; 108 typedef atomic_llong atomic_int_fast64_t; 109 typedef atomic_ullong atomic_uint_fast64_t; 110 111 typedef atomic_long atomic_intptr_t; 112 typedef atomic_ulong atomic_uintptr_t; 113 114 typedef atomic_long atomic_ssize_t; 115 typedef atomic_ulong atomic_size_t; 116 117 typedef atomic_llong atomic_intmax_t; 118 typedef atomic_ullong atomic_uintmax_t; 119 120 typedef atomic_long atomic_ptrdiff_t; 121 122 // Accessor functions for base atomic_flag type. 123 bool 124 atomic_flag_test_and_set_explicit(volatile __atomic_flag_base*, memory_order); 125 126 inline bool 127 atomic_flag_test_and_set(volatile __atomic_flag_base* __a) 128 { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); } 129 130 void 131 atomic_flag_clear_explicit(volatile __atomic_flag_base*, memory_order); 132 133 inline void 134 atomic_flag_clear(volatile __atomic_flag_base* __a) 135 { atomic_flag_clear_explicit(__a, memory_order_seq_cst); } 136 137 void 138 __atomic_flag_wait_explicit(volatile __atomic_flag_base*, memory_order); 139 140 volatile __atomic_flag_base* 141 __atomic_flag_for_address(const volatile void* __z) __attribute__((const)); 142 143 // Implementation specific defines. 144 #define _ATOMIC_LOAD_(__a, __x) \ 145 ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \ 146 volatile atomic_flag* __g = __atomic_flag_for_address(__p); \ 147 __atomic_flag_wait_explicit(__g, __x); \ 148 __typeof__ _ATOMIC_MEMBER_ __r = *__p; \ 149 atomic_flag_clear_explicit(__g, __x); \ 150 __r; }) 151 152 #define _ATOMIC_STORE_(__a, __m, __x) \ 153 ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \ 154 __typeof__(__m) __v = (__m); \ 155 volatile atomic_flag* __g = __atomic_flag_for_address(__p); \ 156 __atomic_flag_wait_explicit(__g, __x); \ 157 *__p = __v; \ 158 atomic_flag_clear_explicit(__g, __x); \ 159 __v; }) 160 161 #define _ATOMIC_MODIFY_(__a, __o, __m, __x) \ 162 ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \ 163 __typeof__(__m) __v = (__m); \ 164 volatile atomic_flag* __g = __atomic_flag_for_address(__p); \ 165 __atomic_flag_wait_explicit(__g, __x); \ 166 __typeof__ _ATOMIC_MEMBER_ __r = *__p; \ 167 *__p __o __v; \ 168 atomic_flag_clear_explicit(__g, __x); \ 169 __r; }) 170 171 #define _ATOMIC_CMPEXCHNG_(__a, __e, __m, __x) \ 172 ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \ 173 __typeof__(__e) __q = (__e); \ 174 __typeof__(__m) __v = (__m); \ 175 bool __r; \ 176 volatile atomic_flag* __g = __atomic_flag_for_address(__p); \ 177 __atomic_flag_wait_explicit(__g, __x); \ 178 __typeof__ _ATOMIC_MEMBER_ __t__ = *__p; \ 179 if (__t__ == *__q) { *__p = __v; __r = true; } \ 180 else { *__q = __t__; __r = false; } \ 181 atomic_flag_clear_explicit(__g, __x); \ 182 __r; }) 183 184 // @} group atomics 185 186 _GLIBCXX_END_EXTERN_C 187 _GLIBCXX_END_NAMESPACE 188 189 // Inject into global namespace. 190 #ifdef __cplusplus 191 192 #include <cstdatomic> 193 194 using std::memory_order; 195 using std::memory_order_relaxed; 196 using std::memory_order_consume; 197 using std::memory_order_acquire; 198 using std::memory_order_release; 199 using std::memory_order_acq_rel; 200 using std::memory_order_seq_cst; 201 using std::atomic_flag; 202 using std::atomic_bool; 203 using std::atomic_char; 204 using std::atomic_schar; 205 using std::atomic_uchar; 206 using std::atomic_short; 207 using std::atomic_ushort; 208 using std::atomic_int; 209 using std::atomic_uint; 210 using std::atomic_long; 211 using std::atomic_ulong; 212 using std::atomic_llong; 213 using std::atomic_ullong; 214 using std::atomic_wchar_t; 215 using std::atomic_char16_t; 216 using std::atomic_char32_t; 217 using std::atomic_address; 218 using std::atomic; 219 #endif 220 221 #endif 222