265 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef _LIBCPP___ATOMIC_SUPPORT_C11_H10#define _LIBCPP___ATOMIC_SUPPORT_C11_H11 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_header20#endif21 22//23// This file implements support for C11-style atomics24//25 26_LIBCPP_BEGIN_NAMESPACE_STD27 28template <typename _Tp>29struct __cxx_atomic_base_impl {30 _LIBCPP_HIDE_FROM_ABI31#ifndef _LIBCPP_CXX03_LANG32 __cxx_atomic_base_impl() _NOEXCEPT = default;33#else34 __cxx_atomic_base_impl() _NOEXCEPT : __a_value() {35 }36#endif // _LIBCPP_CXX03_LANG37 _LIBCPP_CONSTEXPR explicit __cxx_atomic_base_impl(_Tp __value) _NOEXCEPT : __a_value(__value) {}38 _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 51template <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}55template <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 60template <class _Tp>61_LIBCPP_HIDE_FROM_ABI void62__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}65template <class _Tp>66_LIBCPP_HIDE_FROM_ABI void67__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 71template <class _Tp>72_LIBCPP_HIDE_FROM_ABI _Tp73__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}78template <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 85template <class _Tp>86_LIBCPP_HIDE_FROM_ABI void87__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}92template <class _Tp>93_LIBCPP_HIDE_FROM_ABI void94__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 100template <class _Tp>101_LIBCPP_HIDE_FROM_ABI _Tp102__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}106template <class _Tp>107_LIBCPP_HIDE_FROM_ABI _Tp108__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_release116 ? memory_order_relaxed117 : (__order == memory_order_acq_rel ? memory_order_acquire : __order);118}119 120template <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}134template <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 146template <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}160template <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 172template <class _Tp>173_LIBCPP_HIDE_FROM_ABI _Tp174__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}178template <class _Tp>179_LIBCPP_HIDE_FROM_ABI _Tp180__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 185template <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}191template <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 198template <class _Tp>199_LIBCPP_HIDE_FROM_ABI _Tp200__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}204template <class _Tp>205_LIBCPP_HIDE_FROM_ABI _Tp206__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}210template <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}216template <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 223template <class _Tp>224_LIBCPP_HIDE_FROM_ABI _Tp225__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}229template <class _Tp>230_LIBCPP_HIDE_FROM_ABI _Tp231__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 236template <class _Tp>237_LIBCPP_HIDE_FROM_ABI _Tp238__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}242template <class _Tp>243_LIBCPP_HIDE_FROM_ABI _Tp244__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 249template <class _Tp>250_LIBCPP_HIDE_FROM_ABI _Tp251__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}255template <class _Tp>256_LIBCPP_HIDE_FROM_ABI _Tp257__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_STD263 264#endif // _LIBCPP___ATOMIC_SUPPORT_C11_H265