1 // <atomic> compatibility -*- C++ -*- 2 3 // Copyright (C) 2008, 2009, 2010, 2011, 2012 4 // Free Software Foundation, Inc. 5 // 6 // This file is part of the GNU ISO C++ Library. This library is free 7 // software; you can redistribute it and/or modify it under the 8 // terms of the GNU General Public License as published by the 9 // Free Software Foundation; either version 3, or (at your option) 10 // any later version. 11 12 // This library is distributed in the hope that it will be useful, 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 // GNU General Public License for more details. 16 17 // Under Section 7 of GPL version 3, you are granted additional 18 // permissions described in the GCC Runtime Library Exception, version 19 // 3.1, as published by the Free Software Foundation. 20 21 // You should have received a copy of the GNU General Public License and 22 // a copy of the GCC Runtime Library Exception along with this program; 23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24 // <http://www.gnu.org/licenses/>. 25 26 #include "gstdint.h" 27 #include <atomic> 28 #include <mutex> 29 30 // XXX GLIBCXX_ABI Deprecated 31 // gcc-4.7.0 32 33 #ifdef _GLIBCXX_SHARED 34 35 #define LOGSIZE 4 36 37 namespace 38 { 39 #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) 40 std::mutex& 41 get_atomic_mutex() 42 { 43 static std::mutex atomic_mutex; 44 return atomic_mutex; 45 } 46 #endif 47 48 std::__atomic_flag_base flag_table[ 1 << LOGSIZE ] = 49 { 50 ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, 51 ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, 52 ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, 53 ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, 54 }; 55 } // anonymous namespace 56 57 namespace std _GLIBCXX_VISIBILITY(default) 58 { 59 _GLIBCXX_BEGIN_NAMESPACE_VERSION 60 61 namespace __atomic0 62 { 63 64 struct atomic_flag : public __atomic_flag_base 65 { 66 bool 67 test_and_set(memory_order) noexcept; 68 69 void 70 clear(memory_order) noexcept; 71 }; 72 73 bool 74 atomic_flag::test_and_set(memory_order) noexcept 75 { 76 #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) 77 lock_guard<mutex> __lock(get_atomic_mutex()); 78 #endif 79 bool result = _M_i; 80 _M_i = true; 81 return result; 82 } 83 84 void 85 atomic_flag::clear(memory_order) noexcept 86 { 87 #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) 88 lock_guard<mutex> __lock(get_atomic_mutex()); 89 #endif 90 _M_i = false; 91 } 92 } // namespace __atomic0 93 94 _GLIBCXX_BEGIN_EXTERN_C 95 96 bool 97 atomic_flag_test_and_set_explicit(__atomic_flag_base* __a, 98 memory_order __m) _GLIBCXX_NOTHROW 99 { 100 atomic_flag* d = static_cast<atomic_flag*>(__a); 101 return d->test_and_set(__m); 102 } 103 104 void 105 atomic_flag_clear_explicit(__atomic_flag_base* __a, 106 memory_order __m) _GLIBCXX_NOTHROW 107 { 108 atomic_flag* d = static_cast<atomic_flag*>(__a); 109 return d->clear(__m); 110 } 111 112 void 113 __atomic_flag_wait_explicit(__atomic_flag_base* __a, 114 memory_order __x) _GLIBCXX_NOTHROW 115 { 116 while (atomic_flag_test_and_set_explicit(__a, __x)) 117 { }; 118 } 119 120 _GLIBCXX_CONST __atomic_flag_base* 121 __atomic_flag_for_address(const volatile void* __z) _GLIBCXX_NOTHROW 122 { 123 uintptr_t __u = reinterpret_cast<uintptr_t>(__z); 124 __u += (__u >> 2) + (__u << 4); 125 __u += (__u >> 7) + (__u << 5); 126 __u += (__u >> 17) + (__u << 13); 127 if (sizeof(uintptr_t) > 4) 128 __u += (__u >> 31); 129 __u &= ~((~uintptr_t(0)) << LOGSIZE); 130 return flag_table + __u; 131 } 132 133 _GLIBCXX_END_EXTERN_C 134 135 _GLIBCXX_END_NAMESPACE_VERSION 136 } // namespace std 137 138 #endif 139 140 // XXX GLIBCXX_ABI Deprecated 141 // gcc-4.5.0 142 // <atomic> signature changes 143 144 // The rename syntax for default exported names is 145 // asm (".symver name1,exportedname@GLIBCXX_3.4") 146 // asm (".symver name2,exportedname@@GLIBCXX_3.4.5") 147 // In the future, GLIBCXX_ABI > 6 should remove all uses of 148 // _GLIBCXX_*_SYMVER macros in this file. 149 150 #if defined(_GLIBCXX_SYMVER_GNU) && defined(_GLIBCXX_SHARED) \ 151 && defined(_GLIBCXX_HAVE_AS_SYMVER_DIRECTIVE) \ 152 && defined(_GLIBCXX_HAVE_SYMVER_SYMBOL_RENAMING_RUNTIME_SUPPORT) 153 154 #define _GLIBCXX_ASM_SYMVER(cur, old, version) \ 155 asm (".symver " #cur "," #old "@@" #version); 156 157 _GLIBCXX_ASM_SYMVER(_ZNSt9__atomic011atomic_flag5clearESt12memory_order, _ZNVSt9__atomic011atomic_flag5clearESt12memory_order, GLIBCXX_3.4.11) 158 159 _GLIBCXX_ASM_SYMVER(_ZNSt9__atomic011atomic_flag12test_and_setESt12memory_order, _ZNVSt9__atomic011atomic_flag12test_and_setESt12memory_order, GLIBCXX_3.4.11) 160 161 #endif 162