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 bits/atomic_base.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_ATOMIC_BASE_H 34#define _GLIBCXX_ATOMIC_BASE_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(__atomic_flag_base*, memory_order) 125 _GLIBCXX_NOTHROW; 126 127 inline bool 128 atomic_flag_test_and_set(__atomic_flag_base* __a) 129 { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); } 130 131 void 132 atomic_flag_clear_explicit(__atomic_flag_base*, memory_order) 133 _GLIBCXX_NOTHROW; 134 135 inline void 136 atomic_flag_clear(__atomic_flag_base* __a) 137 { atomic_flag_clear_explicit(__a, memory_order_seq_cst); } 138 139 void 140 __atomic_flag_wait_explicit(__atomic_flag_base*, memory_order) 141 _GLIBCXX_NOTHROW; 142 143 _GLIBCXX_CONST __atomic_flag_base* 144 __atomic_flag_for_address(const void* __z) _GLIBCXX_NOTHROW; 145 146 // Implementation specific defines. 147#define _ATOMIC_LOAD_(__a, __x) \ 148 ({__typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \ 149 atomic_flag* __g = __atomic_flag_for_address(__p); \ 150 __atomic_flag_wait_explicit(__g, __x); \ 151 __typeof__ _ATOMIC_MEMBER_ __r = *__p; \ 152 atomic_flag_clear_explicit(__g, __x); \ 153 __r; }) 154 155#define _ATOMIC_STORE_(__a, __m, __x) \ 156 ({__typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \ 157 __typeof__(__m) __v = (__m); \ 158 atomic_flag* __g = __atomic_flag_for_address(__p); \ 159 __atomic_flag_wait_explicit(__g, __x); \ 160 *__p = __v; \ 161 atomic_flag_clear_explicit(__g, __x); \ 162 __v; }) 163 164#define _ATOMIC_MODIFY_(__a, __o, __m, __x) \ 165 ({__typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \ 166 __typeof__(__m) __v = (__m); \ 167 atomic_flag* __g = __atomic_flag_for_address(__p); \ 168 __atomic_flag_wait_explicit(__g, __x); \ 169 __typeof__ _ATOMIC_MEMBER_ __r = *__p; \ 170 *__p __o __v; \ 171 atomic_flag_clear_explicit(__g, __x); \ 172 __r; }) 173 174#define _ATOMIC_CMPEXCHNG_(__a, __e, __m, __x) \ 175 ({__typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \ 176 __typeof__(__e) __q = (__e); \ 177 __typeof__(__m) __v = (__m); \ 178 bool __r; \ 179 atomic_flag* __g = __atomic_flag_for_address(__p); \ 180 __atomic_flag_wait_explicit(__g, __x); \ 181 __typeof__ _ATOMIC_MEMBER_ __t__ = *__p; \ 182 if (__t__ == *__q) { *__p = __v; __r = true; } \ 183 else { *__q = __t__; __r = false; } \ 184 atomic_flag_clear_explicit(__g, __x); \ 185 __r; }) 186 187 // @} group atomics 188 189_GLIBCXX_END_EXTERN_C 190_GLIBCXX_END_NAMESPACE 191 192// Inject into global namespace. 193#ifdef __cplusplus 194 195#include <atomic> 196 197using std::memory_order; 198using std::memory_order_relaxed; 199using std::memory_order_consume; 200using std::memory_order_acquire; 201using std::memory_order_release; 202using std::memory_order_acq_rel; 203using std::memory_order_seq_cst; 204using std::atomic_flag; 205using std::atomic_bool; 206using std::atomic_char; 207using std::atomic_schar; 208using std::atomic_uchar; 209using std::atomic_short; 210using std::atomic_ushort; 211using std::atomic_int; 212using std::atomic_uint; 213using std::atomic_long; 214using std::atomic_ulong; 215using std::atomic_llong; 216using std::atomic_ullong; 217using std::atomic_wchar_t; 218using std::atomic_char16_t; 219using std::atomic_char32_t; 220using std::atomic_address; 221using std::atomic; 222#endif 223 224#endif 225