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