1 //===----------------------------------------------------------------------===//// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===//// 9 10 // FIXME: This file is copied from libcxx/src/include/atomic_support.h. Instead 11 // of duplicating the file in libc++abi we should require that the libc++ 12 // sources are available when building libc++abi. 13 14 #ifndef ATOMIC_SUPPORT_H 15 #define ATOMIC_SUPPORT_H 16 17 #include "__config" 18 #include "memory" // for __libcpp_relaxed_load 19 20 #if defined(__clang__) && __has_builtin(__atomic_load_n) \ 21 && __has_builtin(__atomic_store_n) \ 22 && __has_builtin(__atomic_add_fetch) \ 23 && __has_builtin(__atomic_exchange_n) \ 24 && __has_builtin(__atomic_compare_exchange_n) \ 25 && defined(__ATOMIC_RELAXED) \ 26 && defined(__ATOMIC_CONSUME) \ 27 && defined(__ATOMIC_ACQUIRE) \ 28 && defined(__ATOMIC_RELEASE) \ 29 && defined(__ATOMIC_ACQ_REL) \ 30 && defined(__ATOMIC_SEQ_CST) 31 # define _LIBCXXABI_HAS_ATOMIC_BUILTINS 32 #elif !defined(__clang__) && defined(_GNUC_VER) && _GNUC_VER >= 407 33 # define _LIBCXXABI_HAS_ATOMIC_BUILTINS 34 #endif 35 36 #if !defined(_LIBCXXABI_HAS_ATOMIC_BUILTINS) && !defined(_LIBCXXABI_HAS_NO_THREADS) 37 # if defined(_LIBCPP_WARNING) 38 _LIBCPP_WARNING("Building libc++ without __atomic builtins is unsupported") 39 # else 40 # warning Building libc++ without __atomic builtins is unsupported 41 # endif 42 #endif 43 44 _LIBCPP_BEGIN_NAMESPACE_STD 45 46 namespace { 47 48 #if defined(_LIBCXXABI_HAS_ATOMIC_BUILTINS) && !defined(_LIBCXXABI_HAS_NO_THREADS) 49 50 enum __libcpp_atomic_order { 51 _AO_Relaxed = __ATOMIC_RELAXED, 52 _AO_Consume = __ATOMIC_CONSUME, 53 _AO_Acquire = __ATOMIC_ACQUIRE, 54 _AO_Release = __ATOMIC_RELEASE, 55 _AO_Acq_Rel = __ATOMIC_ACQ_REL, 56 _AO_Seq = __ATOMIC_SEQ_CST 57 }; 58 59 template <class _ValueType, class _FromType> 60 inline _LIBCPP_INLINE_VISIBILITY 61 void __libcpp_atomic_store(_ValueType* __dest, _FromType __val, 62 int __order = _AO_Seq) 63 { 64 __atomic_store_n(__dest, __val, __order); 65 } 66 67 template <class _ValueType, class _FromType> 68 inline _LIBCPP_INLINE_VISIBILITY 69 void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val) 70 { 71 __atomic_store_n(__dest, __val, _AO_Relaxed); 72 } 73 74 template <class _ValueType> 75 inline _LIBCPP_INLINE_VISIBILITY 76 _ValueType __libcpp_atomic_load(_ValueType const* __val, 77 int __order = _AO_Seq) 78 { 79 return __atomic_load_n(__val, __order); 80 } 81 82 template <class _ValueType, class _AddType> 83 inline _LIBCPP_INLINE_VISIBILITY 84 _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a, 85 int __order = _AO_Seq) 86 { 87 return __atomic_add_fetch(__val, __a, __order); 88 } 89 90 template <class _ValueType> 91 inline _LIBCPP_INLINE_VISIBILITY 92 _ValueType __libcpp_atomic_exchange(_ValueType* __target, 93 _ValueType __value, int __order = _AO_Seq) 94 { 95 return __atomic_exchange_n(__target, __value, __order); 96 } 97 98 template <class _ValueType> 99 inline _LIBCPP_INLINE_VISIBILITY 100 bool __libcpp_atomic_compare_exchange(_ValueType* __val, 101 _ValueType* __expected, _ValueType __after, 102 int __success_order = _AO_Seq, 103 int __fail_order = _AO_Seq) 104 { 105 return __atomic_compare_exchange_n(__val, __expected, __after, true, 106 __success_order, __fail_order); 107 } 108 109 #else // _LIBCPP_HAS_NO_THREADS 110 111 enum __libcpp_atomic_order { 112 _AO_Relaxed, 113 _AO_Consume, 114 _AO_Acquire, 115 _AO_Release, 116 _AO_Acq_Rel, 117 _AO_Seq 118 }; 119 120 template <class _ValueType, class _FromType> 121 inline _LIBCPP_INLINE_VISIBILITY 122 void __libcpp_atomic_store(_ValueType* __dest, _FromType __val, 123 int = 0) 124 { 125 *__dest = __val; 126 } 127 128 template <class _ValueType, class _FromType> 129 inline _LIBCPP_INLINE_VISIBILITY 130 void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val) 131 { 132 *__dest = __val; 133 } 134 135 template <class _ValueType> 136 inline _LIBCPP_INLINE_VISIBILITY 137 _ValueType __libcpp_atomic_load(_ValueType const* __val, 138 int = 0) 139 { 140 return *__val; 141 } 142 143 template <class _ValueType, class _AddType> 144 inline _LIBCPP_INLINE_VISIBILITY 145 _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a, 146 int = 0) 147 { 148 return *__val += __a; 149 } 150 151 template <class _ValueType> 152 inline _LIBCPP_INLINE_VISIBILITY 153 _ValueType __libcpp_atomic_exchange(_ValueType* __target, 154 _ValueType __value, int __order = _AO_Seq) 155 { 156 _ValueType old = *__target; 157 *__target = __value; 158 return old; 159 } 160 161 template <class _ValueType> 162 inline _LIBCPP_INLINE_VISIBILITY 163 bool __libcpp_atomic_compare_exchange(_ValueType* __val, 164 _ValueType* __expected, _ValueType __after, 165 int = 0, int = 0) 166 { 167 if (*__val == *__expected) { 168 *__val = __after; 169 return true; 170 } 171 *__expected = *__val; 172 return false; 173 } 174 175 #endif // _LIBCPP_HAS_NO_THREADS 176 177 } // end namespace 178 179 _LIBCPP_END_NAMESPACE_STD 180 181 #endif // ATOMIC_SUPPORT_H 182