1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef _LIBCPP___ATOMIC_SUPPORT_C11_H 10 #define _LIBCPP___ATOMIC_SUPPORT_C11_H 11 12 #include <__atomic/memory_order.h> 13 #include <__config> 14 #include <__cstddef/ptrdiff_t.h> 15 #include <__memory/addressof.h> 16 #include <__type_traits/remove_const.h> 17 18 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 19 # pragma GCC system_header 20 #endif 21 22 // 23 // This file implements support for C11-style atomics 24 // 25 26 _LIBCPP_BEGIN_NAMESPACE_STD 27 28 template <typename _Tp> 29 struct __cxx_atomic_base_impl { 30 _LIBCPP_HIDE_FROM_ABI 31 #ifndef _LIBCPP_CXX03_LANG 32 __cxx_atomic_base_impl() _NOEXCEPT = default; 33 #else 34 __cxx_atomic_base_impl() _NOEXCEPT : __a_value() { 35 } 36 #endif // _LIBCPP_CXX03_LANG 37 _LIBCPP_CONSTEXPR explicit __cxx_atomic_base_impl(_Tp __value) _NOEXCEPT : __a_value(__value) {} 38 _LIBCPP_DISABLE_EXTENSION_WARNING _Atomic(_Tp) __a_value; 39 }; 40 41 #define __cxx_atomic_is_lock_free(__s) __c11_atomic_is_lock_free(__s) 42 43 _LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_thread_fence(memory_order __order) _NOEXCEPT { 44 __c11_atomic_thread_fence(static_cast<__memory_order_underlying_t>(__order)); 45 } 46 47 _LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_signal_fence(memory_order __order) _NOEXCEPT { 48 __c11_atomic_signal_fence(static_cast<__memory_order_underlying_t>(__order)); 49 } 50 51 template <class _Tp> 52 _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __val) _NOEXCEPT { 53 __c11_atomic_init(std::addressof(__a->__a_value), __val); 54 } 55 template <class _Tp> 56 _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val) _NOEXCEPT { 57 __c11_atomic_init(std::addressof(__a->__a_value), __val); 58 } 59 60 template <class _Tp> 61 _LIBCPP_HIDE_FROM_ABI void 62 __cxx_atomic_store(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __val, memory_order __order) _NOEXCEPT { 63 __c11_atomic_store(std::addressof(__a->__a_value), __val, static_cast<__memory_order_underlying_t>(__order)); 64 } 65 template <class _Tp> 66 _LIBCPP_HIDE_FROM_ABI void 67 __cxx_atomic_store(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) _NOEXCEPT { 68 __c11_atomic_store(std::addressof(__a->__a_value), __val, static_cast<__memory_order_underlying_t>(__order)); 69 } 70 71 template <class _Tp> 72 _LIBCPP_HIDE_FROM_ABI _Tp 73 __cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const volatile* __a, memory_order __order) _NOEXCEPT { 74 using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*; 75 return __c11_atomic_load( 76 const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); 77 } 78 template <class _Tp> 79 _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const* __a, memory_order __order) _NOEXCEPT { 80 using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*; 81 return __c11_atomic_load( 82 const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); 83 } 84 85 template <class _Tp> 86 _LIBCPP_HIDE_FROM_ABI void 87 __cxx_atomic_load_inplace(__cxx_atomic_base_impl<_Tp> const volatile* __a, _Tp* __dst, memory_order __order) _NOEXCEPT { 88 using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*; 89 *__dst = __c11_atomic_load( 90 const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); 91 } 92 template <class _Tp> 93 _LIBCPP_HIDE_FROM_ABI void 94 __cxx_atomic_load_inplace(__cxx_atomic_base_impl<_Tp> const* __a, _Tp* __dst, memory_order __order) _NOEXCEPT { 95 using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*; 96 *__dst = __c11_atomic_load( 97 const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); 98 } 99 100 template <class _Tp> 101 _LIBCPP_HIDE_FROM_ABI _Tp 102 __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __value, memory_order __order) _NOEXCEPT { 103 return __c11_atomic_exchange( 104 std::addressof(__a->__a_value), __value, static_cast<__memory_order_underlying_t>(__order)); 105 } 106 template <class _Tp> 107 _LIBCPP_HIDE_FROM_ABI _Tp 108 __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) _NOEXCEPT { 109 return __c11_atomic_exchange( 110 std::addressof(__a->__a_value), __value, static_cast<__memory_order_underlying_t>(__order)); 111 } 112 113 _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR memory_order __to_failure_order(memory_order __order) { 114 // Avoid switch statement to make this a constexpr. 115 return __order == memory_order_release 116 ? memory_order_relaxed 117 : (__order == memory_order_acq_rel ? memory_order_acquire : __order); 118 } 119 120 template <class _Tp> 121 _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong( 122 __cxx_atomic_base_impl<_Tp> volatile* __a, 123 _Tp* __expected, 124 _Tp __value, 125 memory_order __success, 126 memory_order __failure) _NOEXCEPT { 127 return __c11_atomic_compare_exchange_strong( 128 std::addressof(__a->__a_value), 129 __expected, 130 __value, 131 static_cast<__memory_order_underlying_t>(__success), 132 static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); 133 } 134 template <class _Tp> 135 _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong( 136 __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) 137 _NOEXCEPT { 138 return __c11_atomic_compare_exchange_strong( 139 std::addressof(__a->__a_value), 140 __expected, 141 __value, 142 static_cast<__memory_order_underlying_t>(__success), 143 static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); 144 } 145 146 template <class _Tp> 147 _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak( 148 __cxx_atomic_base_impl<_Tp> volatile* __a, 149 _Tp* __expected, 150 _Tp __value, 151 memory_order __success, 152 memory_order __failure) _NOEXCEPT { 153 return __c11_atomic_compare_exchange_weak( 154 std::addressof(__a->__a_value), 155 __expected, 156 __value, 157 static_cast<__memory_order_underlying_t>(__success), 158 static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); 159 } 160 template <class _Tp> 161 _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak( 162 __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) 163 _NOEXCEPT { 164 return __c11_atomic_compare_exchange_weak( 165 std::addressof(__a->__a_value), 166 __expected, 167 __value, 168 static_cast<__memory_order_underlying_t>(__success), 169 static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); 170 } 171 172 template <class _Tp> 173 _LIBCPP_HIDE_FROM_ABI _Tp 174 __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, memory_order __order) _NOEXCEPT { 175 return __c11_atomic_fetch_add( 176 std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 177 } 178 template <class _Tp> 179 _LIBCPP_HIDE_FROM_ABI _Tp 180 __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp>* __a, _Tp __delta, memory_order __order) _NOEXCEPT { 181 return __c11_atomic_fetch_add( 182 std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 183 } 184 185 template <class _Tp> 186 _LIBCPP_HIDE_FROM_ABI _Tp* 187 __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { 188 return __c11_atomic_fetch_add( 189 std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 190 } 191 template <class _Tp> 192 _LIBCPP_HIDE_FROM_ABI _Tp* 193 __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*>* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { 194 return __c11_atomic_fetch_add( 195 std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 196 } 197 198 template <class _Tp> 199 _LIBCPP_HIDE_FROM_ABI _Tp 200 __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, memory_order __order) _NOEXCEPT { 201 return __c11_atomic_fetch_sub( 202 std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 203 } 204 template <class _Tp> 205 _LIBCPP_HIDE_FROM_ABI _Tp 206 __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp>* __a, _Tp __delta, memory_order __order) _NOEXCEPT { 207 return __c11_atomic_fetch_sub( 208 std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 209 } 210 template <class _Tp> 211 _LIBCPP_HIDE_FROM_ABI _Tp* 212 __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { 213 return __c11_atomic_fetch_sub( 214 std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 215 } 216 template <class _Tp> 217 _LIBCPP_HIDE_FROM_ABI _Tp* 218 __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*>* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { 219 return __c11_atomic_fetch_sub( 220 std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); 221 } 222 223 template <class _Tp> 224 _LIBCPP_HIDE_FROM_ABI _Tp 225 __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { 226 return __c11_atomic_fetch_and( 227 std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); 228 } 229 template <class _Tp> 230 _LIBCPP_HIDE_FROM_ABI _Tp 231 __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { 232 return __c11_atomic_fetch_and( 233 std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); 234 } 235 236 template <class _Tp> 237 _LIBCPP_HIDE_FROM_ABI _Tp 238 __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { 239 return __c11_atomic_fetch_or( 240 std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); 241 } 242 template <class _Tp> 243 _LIBCPP_HIDE_FROM_ABI _Tp 244 __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { 245 return __c11_atomic_fetch_or( 246 std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); 247 } 248 249 template <class _Tp> 250 _LIBCPP_HIDE_FROM_ABI _Tp 251 __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { 252 return __c11_atomic_fetch_xor( 253 std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); 254 } 255 template <class _Tp> 256 _LIBCPP_HIDE_FROM_ABI _Tp 257 __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { 258 return __c11_atomic_fetch_xor( 259 std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); 260 } 261 262 _LIBCPP_END_NAMESPACE_STD 263 264 #endif // _LIBCPP___ATOMIC_SUPPORT_C11_H 265