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