xref: /freebsd-src/contrib/llvm-project/libcxx/include/__atomic/cxx_atomic_impl.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
206c3fb27SDimitry Andric //
306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606c3fb27SDimitry Andric //
706c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
806c3fb27SDimitry Andric 
906c3fb27SDimitry Andric #ifndef _LIBCPP___ATOMIC_CXX_ATOMIC_IMPL_H
1006c3fb27SDimitry Andric #define _LIBCPP___ATOMIC_CXX_ATOMIC_IMPL_H
1106c3fb27SDimitry Andric 
1206c3fb27SDimitry Andric #include <__atomic/memory_order.h>
13*0fca6ea1SDimitry Andric #include <__atomic/to_gcc_order.h>
1406c3fb27SDimitry Andric #include <__config>
1506c3fb27SDimitry Andric #include <__memory/addressof.h>
1606c3fb27SDimitry Andric #include <__type_traits/is_assignable.h>
1706c3fb27SDimitry Andric #include <__type_traits/is_trivially_copyable.h>
1806c3fb27SDimitry Andric #include <__type_traits/remove_const.h>
1906c3fb27SDimitry Andric #include <cstddef>
2006c3fb27SDimitry Andric 
2106c3fb27SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2206c3fb27SDimitry Andric #  pragma GCC system_header
2306c3fb27SDimitry Andric #endif
2406c3fb27SDimitry Andric 
2506c3fb27SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
2606c3fb27SDimitry Andric 
27*0fca6ea1SDimitry Andric #if defined(_LIBCPP_HAS_GCC_ATOMIC_IMP)
2806c3fb27SDimitry Andric 
2906c3fb27SDimitry Andric // [atomics.types.generic]p1 guarantees _Tp is trivially copyable. Because
3006c3fb27SDimitry Andric // the default operator= in an object is not volatile, a byte-by-byte copy
3106c3fb27SDimitry Andric // is required.
32cb14a3feSDimitry Andric template <typename _Tp, typename _Tv, __enable_if_t<is_assignable<_Tp&, _Tv>::value, int> = 0>
33cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_assign_volatile(_Tp& __a_value, _Tv const& __val) {
3406c3fb27SDimitry Andric   __a_value = __val;
3506c3fb27SDimitry Andric }
36cb14a3feSDimitry Andric template <typename _Tp, typename _Tv, __enable_if_t<is_assignable<_Tp&, _Tv>::value, int> = 0>
37cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_assign_volatile(_Tp volatile& __a_value, _Tv volatile const& __val) {
3806c3fb27SDimitry Andric   volatile char* __to         = reinterpret_cast<volatile char*>(std::addressof(__a_value));
3906c3fb27SDimitry Andric   volatile char* __end        = __to + sizeof(_Tp);
4006c3fb27SDimitry Andric   volatile const char* __from = reinterpret_cast<volatile const char*>(std::addressof(__val));
4106c3fb27SDimitry Andric   while (__to != __end)
4206c3fb27SDimitry Andric     *__to++ = *__from++;
4306c3fb27SDimitry Andric }
4406c3fb27SDimitry Andric 
4506c3fb27SDimitry Andric template <typename _Tp>
4606c3fb27SDimitry Andric struct __cxx_atomic_base_impl {
4706c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
4806c3fb27SDimitry Andric #  ifndef _LIBCPP_CXX03_LANG
4906c3fb27SDimitry Andric   __cxx_atomic_base_impl() _NOEXCEPT = default;
5006c3fb27SDimitry Andric #  else
51cb14a3feSDimitry Andric   __cxx_atomic_base_impl() _NOEXCEPT : __a_value() {
52cb14a3feSDimitry Andric   }
5306c3fb27SDimitry Andric #  endif // _LIBCPP_CXX03_LANG
54cb14a3feSDimitry Andric   _LIBCPP_CONSTEXPR explicit __cxx_atomic_base_impl(_Tp value) _NOEXCEPT : __a_value(value) {}
5506c3fb27SDimitry Andric   _Tp __a_value;
5606c3fb27SDimitry Andric };
5706c3fb27SDimitry Andric 
5806c3fb27SDimitry Andric template <typename _Tp>
59cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val) {
6006c3fb27SDimitry Andric   __cxx_atomic_assign_volatile(__a->__a_value, __val);
6106c3fb27SDimitry Andric }
6206c3fb27SDimitry Andric 
6306c3fb27SDimitry Andric template <typename _Tp>
64cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val) {
6506c3fb27SDimitry Andric   __a->__a_value = __val;
6606c3fb27SDimitry Andric }
6706c3fb27SDimitry Andric 
68cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_thread_fence(memory_order __order) {
6906c3fb27SDimitry Andric   __atomic_thread_fence(__to_gcc_order(__order));
7006c3fb27SDimitry Andric }
7106c3fb27SDimitry Andric 
72cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_signal_fence(memory_order __order) {
7306c3fb27SDimitry Andric   __atomic_signal_fence(__to_gcc_order(__order));
7406c3fb27SDimitry Andric }
7506c3fb27SDimitry Andric 
7606c3fb27SDimitry Andric template <typename _Tp>
77cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void
78cb14a3feSDimitry Andric __cxx_atomic_store(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) {
7906c3fb27SDimitry Andric   __atomic_store(std::addressof(__a->__a_value), std::addressof(__val), __to_gcc_order(__order));
8006c3fb27SDimitry Andric }
8106c3fb27SDimitry Andric 
8206c3fb27SDimitry Andric template <typename _Tp>
83cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) {
8406c3fb27SDimitry Andric   __atomic_store(std::addressof(__a->__a_value), std::addressof(__val), __to_gcc_order(__order));
8506c3fb27SDimitry Andric }
8606c3fb27SDimitry Andric 
8706c3fb27SDimitry Andric template <typename _Tp>
88cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_load(const volatile __cxx_atomic_base_impl<_Tp>* __a, memory_order __order) {
8906c3fb27SDimitry Andric   _Tp __ret;
9006c3fb27SDimitry Andric   __atomic_load(std::addressof(__a->__a_value), std::addressof(__ret), __to_gcc_order(__order));
9106c3fb27SDimitry Andric   return __ret;
9206c3fb27SDimitry Andric }
9306c3fb27SDimitry Andric 
9406c3fb27SDimitry Andric template <typename _Tp>
955f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI void
965f757f3fSDimitry Andric __cxx_atomic_load_inplace(const volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp* __dst, memory_order __order) {
975f757f3fSDimitry Andric   __atomic_load(std::addressof(__a->__a_value), __dst, __to_gcc_order(__order));
985f757f3fSDimitry Andric }
995f757f3fSDimitry Andric 
1005f757f3fSDimitry Andric template <typename _Tp>
1015f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI void
1025f757f3fSDimitry Andric __cxx_atomic_load_inplace(const __cxx_atomic_base_impl<_Tp>* __a, _Tp* __dst, memory_order __order) {
1035f757f3fSDimitry Andric   __atomic_load(std::addressof(__a->__a_value), __dst, __to_gcc_order(__order));
1045f757f3fSDimitry Andric }
1055f757f3fSDimitry Andric 
1065f757f3fSDimitry Andric template <typename _Tp>
107cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_load(const __cxx_atomic_base_impl<_Tp>* __a, memory_order __order) {
10806c3fb27SDimitry Andric   _Tp __ret;
10906c3fb27SDimitry Andric   __atomic_load(std::addressof(__a->__a_value), std::addressof(__ret), __to_gcc_order(__order));
11006c3fb27SDimitry Andric   return __ret;
11106c3fb27SDimitry Andric }
11206c3fb27SDimitry Andric 
11306c3fb27SDimitry Andric template <typename _Tp>
114cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
115cb14a3feSDimitry Andric __cxx_atomic_exchange(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) {
11606c3fb27SDimitry Andric   _Tp __ret;
11706c3fb27SDimitry Andric   __atomic_exchange(
11806c3fb27SDimitry Andric       std::addressof(__a->__a_value), std::addressof(__value), std::addressof(__ret), __to_gcc_order(__order));
11906c3fb27SDimitry Andric   return __ret;
12006c3fb27SDimitry Andric }
12106c3fb27SDimitry Andric 
12206c3fb27SDimitry Andric template <typename _Tp>
123cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) {
12406c3fb27SDimitry Andric   _Tp __ret;
12506c3fb27SDimitry Andric   __atomic_exchange(
12606c3fb27SDimitry Andric       std::addressof(__a->__a_value), std::addressof(__value), std::addressof(__ret), __to_gcc_order(__order));
12706c3fb27SDimitry Andric   return __ret;
12806c3fb27SDimitry Andric }
12906c3fb27SDimitry Andric 
13006c3fb27SDimitry Andric template <typename _Tp>
131cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong(
132cb14a3feSDimitry Andric     volatile __cxx_atomic_base_impl<_Tp>* __a,
133cb14a3feSDimitry Andric     _Tp* __expected,
134cb14a3feSDimitry Andric     _Tp __value,
135cb14a3feSDimitry Andric     memory_order __success,
13606c3fb27SDimitry Andric     memory_order __failure) {
13706c3fb27SDimitry Andric   return __atomic_compare_exchange(
13806c3fb27SDimitry Andric       std::addressof(__a->__a_value),
13906c3fb27SDimitry Andric       __expected,
14006c3fb27SDimitry Andric       std::addressof(__value),
14106c3fb27SDimitry Andric       false,
14206c3fb27SDimitry Andric       __to_gcc_order(__success),
14306c3fb27SDimitry Andric       __to_gcc_failure_order(__failure));
14406c3fb27SDimitry Andric }
14506c3fb27SDimitry Andric 
14606c3fb27SDimitry Andric template <typename _Tp>
147cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong(
148cb14a3feSDimitry Andric     __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) {
14906c3fb27SDimitry Andric   return __atomic_compare_exchange(
15006c3fb27SDimitry Andric       std::addressof(__a->__a_value),
15106c3fb27SDimitry Andric       __expected,
15206c3fb27SDimitry Andric       std::addressof(__value),
153cb14a3feSDimitry Andric       false,
15406c3fb27SDimitry Andric       __to_gcc_order(__success),
15506c3fb27SDimitry Andric       __to_gcc_failure_order(__failure));
15606c3fb27SDimitry Andric }
15706c3fb27SDimitry Andric 
15806c3fb27SDimitry Andric template <typename _Tp>
159cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak(
160cb14a3feSDimitry Andric     volatile __cxx_atomic_base_impl<_Tp>* __a,
161cb14a3feSDimitry Andric     _Tp* __expected,
162cb14a3feSDimitry Andric     _Tp __value,
163cb14a3feSDimitry Andric     memory_order __success,
16406c3fb27SDimitry Andric     memory_order __failure) {
16506c3fb27SDimitry Andric   return __atomic_compare_exchange(
16606c3fb27SDimitry Andric       std::addressof(__a->__a_value),
16706c3fb27SDimitry Andric       __expected,
16806c3fb27SDimitry Andric       std::addressof(__value),
16906c3fb27SDimitry Andric       true,
17006c3fb27SDimitry Andric       __to_gcc_order(__success),
17106c3fb27SDimitry Andric       __to_gcc_failure_order(__failure));
17206c3fb27SDimitry Andric }
17306c3fb27SDimitry Andric 
17406c3fb27SDimitry Andric template <typename _Tp>
175cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak(
176cb14a3feSDimitry Andric     __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) {
177cb14a3feSDimitry Andric   return __atomic_compare_exchange(
178cb14a3feSDimitry Andric       std::addressof(__a->__a_value),
179cb14a3feSDimitry Andric       __expected,
180cb14a3feSDimitry Andric       std::addressof(__value),
181cb14a3feSDimitry Andric       true,
182cb14a3feSDimitry Andric       __to_gcc_order(__success),
183cb14a3feSDimitry Andric       __to_gcc_failure_order(__failure));
184cb14a3feSDimitry Andric }
18506c3fb27SDimitry Andric 
18606c3fb27SDimitry Andric template <typename _Tp>
187cb14a3feSDimitry Andric struct __skip_amt {
188cb14a3feSDimitry Andric   enum { value = 1 };
189cb14a3feSDimitry Andric };
190cb14a3feSDimitry Andric 
191cb14a3feSDimitry Andric template <typename _Tp>
192cb14a3feSDimitry Andric struct __skip_amt<_Tp*> {
193cb14a3feSDimitry Andric   enum { value = sizeof(_Tp) };
194cb14a3feSDimitry Andric };
19506c3fb27SDimitry Andric 
19606c3fb27SDimitry Andric // FIXME: Haven't figured out what the spec says about using arrays with
19706c3fb27SDimitry Andric // atomic_fetch_add. Force a failure rather than creating bad behavior.
19806c3fb27SDimitry Andric template <typename _Tp>
19906c3fb27SDimitry Andric struct __skip_amt<_Tp[]> {};
20006c3fb27SDimitry Andric template <typename _Tp, int n>
20106c3fb27SDimitry Andric struct __skip_amt<_Tp[n]> {};
20206c3fb27SDimitry Andric 
20306c3fb27SDimitry Andric template <typename _Tp, typename _Td>
204cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
205cb14a3feSDimitry Andric __cxx_atomic_fetch_add(volatile __cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) {
20606c3fb27SDimitry Andric   return __atomic_fetch_add(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order));
20706c3fb27SDimitry Andric }
20806c3fb27SDimitry Andric 
20906c3fb27SDimitry Andric template <typename _Tp, typename _Td>
210cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) {
21106c3fb27SDimitry Andric   return __atomic_fetch_add(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order));
21206c3fb27SDimitry Andric }
21306c3fb27SDimitry Andric 
21406c3fb27SDimitry Andric template <typename _Tp, typename _Td>
215cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
216cb14a3feSDimitry Andric __cxx_atomic_fetch_sub(volatile __cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) {
21706c3fb27SDimitry Andric   return __atomic_fetch_sub(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order));
21806c3fb27SDimitry Andric }
21906c3fb27SDimitry Andric 
22006c3fb27SDimitry Andric template <typename _Tp, typename _Td>
221cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) {
22206c3fb27SDimitry Andric   return __atomic_fetch_sub(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order));
22306c3fb27SDimitry Andric }
22406c3fb27SDimitry Andric 
22506c3fb27SDimitry Andric template <typename _Tp>
226cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
227cb14a3feSDimitry Andric __cxx_atomic_fetch_and(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) {
22806c3fb27SDimitry Andric   return __atomic_fetch_and(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order));
22906c3fb27SDimitry Andric }
23006c3fb27SDimitry Andric 
23106c3fb27SDimitry Andric template <typename _Tp>
232cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
233cb14a3feSDimitry Andric __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) {
23406c3fb27SDimitry Andric   return __atomic_fetch_and(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order));
23506c3fb27SDimitry Andric }
23606c3fb27SDimitry Andric 
23706c3fb27SDimitry Andric template <typename _Tp>
238cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
239cb14a3feSDimitry Andric __cxx_atomic_fetch_or(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) {
24006c3fb27SDimitry Andric   return __atomic_fetch_or(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order));
24106c3fb27SDimitry Andric }
24206c3fb27SDimitry Andric 
24306c3fb27SDimitry Andric template <typename _Tp>
244cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) {
24506c3fb27SDimitry Andric   return __atomic_fetch_or(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order));
24606c3fb27SDimitry Andric }
24706c3fb27SDimitry Andric 
24806c3fb27SDimitry Andric template <typename _Tp>
249cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
250cb14a3feSDimitry Andric __cxx_atomic_fetch_xor(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) {
25106c3fb27SDimitry Andric   return __atomic_fetch_xor(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order));
25206c3fb27SDimitry Andric }
25306c3fb27SDimitry Andric 
25406c3fb27SDimitry Andric template <typename _Tp>
255cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
256cb14a3feSDimitry Andric __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) {
25706c3fb27SDimitry Andric   return __atomic_fetch_xor(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order));
25806c3fb27SDimitry Andric }
25906c3fb27SDimitry Andric 
26006c3fb27SDimitry Andric #  define __cxx_atomic_is_lock_free(__s) __atomic_is_lock_free(__s, 0)
26106c3fb27SDimitry Andric 
26206c3fb27SDimitry Andric #elif defined(_LIBCPP_HAS_C_ATOMIC_IMP)
26306c3fb27SDimitry Andric 
26406c3fb27SDimitry Andric template <typename _Tp>
26506c3fb27SDimitry Andric struct __cxx_atomic_base_impl {
26606c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
26706c3fb27SDimitry Andric #  ifndef _LIBCPP_CXX03_LANG
26806c3fb27SDimitry Andric   __cxx_atomic_base_impl() _NOEXCEPT = default;
26906c3fb27SDimitry Andric #  else
270cb14a3feSDimitry Andric   __cxx_atomic_base_impl() _NOEXCEPT : __a_value() {
271cb14a3feSDimitry Andric   }
27206c3fb27SDimitry Andric #  endif // _LIBCPP_CXX03_LANG
273cb14a3feSDimitry Andric   _LIBCPP_CONSTEXPR explicit __cxx_atomic_base_impl(_Tp __value) _NOEXCEPT : __a_value(__value) {}
27406c3fb27SDimitry Andric   _LIBCPP_DISABLE_EXTENSION_WARNING _Atomic(_Tp) __a_value;
27506c3fb27SDimitry Andric };
27606c3fb27SDimitry Andric 
27706c3fb27SDimitry Andric #  define __cxx_atomic_is_lock_free(__s) __c11_atomic_is_lock_free(__s)
27806c3fb27SDimitry Andric 
279cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_thread_fence(memory_order __order) _NOEXCEPT {
28006c3fb27SDimitry Andric   __c11_atomic_thread_fence(static_cast<__memory_order_underlying_t>(__order));
28106c3fb27SDimitry Andric }
28206c3fb27SDimitry Andric 
283cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_signal_fence(memory_order __order) _NOEXCEPT {
28406c3fb27SDimitry Andric   __c11_atomic_signal_fence(static_cast<__memory_order_underlying_t>(__order));
28506c3fb27SDimitry Andric }
28606c3fb27SDimitry Andric 
28706c3fb27SDimitry Andric template <class _Tp>
288cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __val) _NOEXCEPT {
28906c3fb27SDimitry Andric   __c11_atomic_init(std::addressof(__a->__a_value), __val);
29006c3fb27SDimitry Andric }
29106c3fb27SDimitry Andric template <class _Tp>
292cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val) _NOEXCEPT {
29306c3fb27SDimitry Andric   __c11_atomic_init(std::addressof(__a->__a_value), __val);
29406c3fb27SDimitry Andric }
29506c3fb27SDimitry Andric 
29606c3fb27SDimitry Andric template <class _Tp>
297cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void
298cb14a3feSDimitry Andric __cxx_atomic_store(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __val, memory_order __order) _NOEXCEPT {
29906c3fb27SDimitry Andric   __c11_atomic_store(std::addressof(__a->__a_value), __val, static_cast<__memory_order_underlying_t>(__order));
30006c3fb27SDimitry Andric }
30106c3fb27SDimitry Andric template <class _Tp>
302cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void
303cb14a3feSDimitry Andric __cxx_atomic_store(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) _NOEXCEPT {
30406c3fb27SDimitry Andric   __c11_atomic_store(std::addressof(__a->__a_value), __val, static_cast<__memory_order_underlying_t>(__order));
30506c3fb27SDimitry Andric }
30606c3fb27SDimitry Andric 
30706c3fb27SDimitry Andric template <class _Tp>
308cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
309cb14a3feSDimitry Andric __cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const volatile* __a, memory_order __order) _NOEXCEPT {
31006c3fb27SDimitry Andric   using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*;
31106c3fb27SDimitry Andric   return __c11_atomic_load(
31206c3fb27SDimitry Andric       const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order));
31306c3fb27SDimitry Andric }
31406c3fb27SDimitry Andric template <class _Tp>
315cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const* __a, memory_order __order) _NOEXCEPT {
31606c3fb27SDimitry Andric   using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*;
31706c3fb27SDimitry Andric   return __c11_atomic_load(
31806c3fb27SDimitry Andric       const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order));
31906c3fb27SDimitry Andric }
32006c3fb27SDimitry Andric 
32106c3fb27SDimitry Andric template <class _Tp>
3225f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI void
3235f757f3fSDimitry Andric __cxx_atomic_load_inplace(__cxx_atomic_base_impl<_Tp> const volatile* __a, _Tp* __dst, memory_order __order) _NOEXCEPT {
3245f757f3fSDimitry Andric   using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*;
3255f757f3fSDimitry Andric   *__dst           = __c11_atomic_load(
3265f757f3fSDimitry Andric       const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order));
3275f757f3fSDimitry Andric }
3285f757f3fSDimitry Andric template <class _Tp>
3295f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI void
3305f757f3fSDimitry Andric __cxx_atomic_load_inplace(__cxx_atomic_base_impl<_Tp> const* __a, _Tp* __dst, memory_order __order) _NOEXCEPT {
3315f757f3fSDimitry Andric   using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*;
3325f757f3fSDimitry Andric   *__dst           = __c11_atomic_load(
3335f757f3fSDimitry Andric       const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order));
3345f757f3fSDimitry Andric }
3355f757f3fSDimitry Andric 
3365f757f3fSDimitry Andric template <class _Tp>
337cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
338cb14a3feSDimitry Andric __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __value, memory_order __order) _NOEXCEPT {
33906c3fb27SDimitry Andric   return __c11_atomic_exchange(
34006c3fb27SDimitry Andric       std::addressof(__a->__a_value), __value, static_cast<__memory_order_underlying_t>(__order));
34106c3fb27SDimitry Andric }
34206c3fb27SDimitry Andric template <class _Tp>
343cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
344cb14a3feSDimitry Andric __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) _NOEXCEPT {
34506c3fb27SDimitry Andric   return __c11_atomic_exchange(
34606c3fb27SDimitry Andric       std::addressof(__a->__a_value), __value, static_cast<__memory_order_underlying_t>(__order));
34706c3fb27SDimitry Andric }
34806c3fb27SDimitry Andric 
34906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR memory_order __to_failure_order(memory_order __order) {
35006c3fb27SDimitry Andric   // Avoid switch statement to make this a constexpr.
351cb14a3feSDimitry Andric   return __order == memory_order_release
352cb14a3feSDimitry Andric            ? memory_order_relaxed
353cb14a3feSDimitry Andric            : (__order == memory_order_acq_rel ? memory_order_acquire : __order);
35406c3fb27SDimitry Andric }
35506c3fb27SDimitry Andric 
35606c3fb27SDimitry Andric template <class _Tp>
357cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong(
358cb14a3feSDimitry Andric     __cxx_atomic_base_impl<_Tp> volatile* __a,
359cb14a3feSDimitry Andric     _Tp* __expected,
360cb14a3feSDimitry Andric     _Tp __value,
361cb14a3feSDimitry Andric     memory_order __success,
362cb14a3feSDimitry Andric     memory_order __failure) _NOEXCEPT {
36306c3fb27SDimitry Andric   return __c11_atomic_compare_exchange_strong(
36406c3fb27SDimitry Andric       std::addressof(__a->__a_value),
36506c3fb27SDimitry Andric       __expected,
36606c3fb27SDimitry Andric       __value,
36706c3fb27SDimitry Andric       static_cast<__memory_order_underlying_t>(__success),
36806c3fb27SDimitry Andric       static_cast<__memory_order_underlying_t>(__to_failure_order(__failure)));
36906c3fb27SDimitry Andric }
37006c3fb27SDimitry Andric template <class _Tp>
371cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong(
372cb14a3feSDimitry Andric     __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure)
373cb14a3feSDimitry Andric     _NOEXCEPT {
37406c3fb27SDimitry Andric   return __c11_atomic_compare_exchange_strong(
37506c3fb27SDimitry Andric       std::addressof(__a->__a_value),
37606c3fb27SDimitry Andric       __expected,
37706c3fb27SDimitry Andric       __value,
37806c3fb27SDimitry Andric       static_cast<__memory_order_underlying_t>(__success),
37906c3fb27SDimitry Andric       static_cast<__memory_order_underlying_t>(__to_failure_order(__failure)));
38006c3fb27SDimitry Andric }
38106c3fb27SDimitry Andric 
38206c3fb27SDimitry Andric template <class _Tp>
383cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak(
384cb14a3feSDimitry Andric     __cxx_atomic_base_impl<_Tp> volatile* __a,
385cb14a3feSDimitry Andric     _Tp* __expected,
386cb14a3feSDimitry Andric     _Tp __value,
387cb14a3feSDimitry Andric     memory_order __success,
388cb14a3feSDimitry Andric     memory_order __failure) _NOEXCEPT {
38906c3fb27SDimitry Andric   return __c11_atomic_compare_exchange_weak(
39006c3fb27SDimitry Andric       std::addressof(__a->__a_value),
39106c3fb27SDimitry Andric       __expected,
39206c3fb27SDimitry Andric       __value,
39306c3fb27SDimitry Andric       static_cast<__memory_order_underlying_t>(__success),
39406c3fb27SDimitry Andric       static_cast<__memory_order_underlying_t>(__to_failure_order(__failure)));
39506c3fb27SDimitry Andric }
39606c3fb27SDimitry Andric template <class _Tp>
397cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak(
398cb14a3feSDimitry Andric     __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure)
399cb14a3feSDimitry Andric     _NOEXCEPT {
40006c3fb27SDimitry Andric   return __c11_atomic_compare_exchange_weak(
40106c3fb27SDimitry Andric       std::addressof(__a->__a_value),
40206c3fb27SDimitry Andric       __expected,
40306c3fb27SDimitry Andric       __value,
40406c3fb27SDimitry Andric       static_cast<__memory_order_underlying_t>(__success),
40506c3fb27SDimitry Andric       static_cast<__memory_order_underlying_t>(__to_failure_order(__failure)));
40606c3fb27SDimitry Andric }
40706c3fb27SDimitry Andric 
40806c3fb27SDimitry Andric template <class _Tp>
409cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
410cb14a3feSDimitry Andric __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, memory_order __order) _NOEXCEPT {
41106c3fb27SDimitry Andric   return __c11_atomic_fetch_add(
41206c3fb27SDimitry Andric       std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order));
41306c3fb27SDimitry Andric }
41406c3fb27SDimitry Andric template <class _Tp>
415cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
416cb14a3feSDimitry Andric __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp>* __a, _Tp __delta, memory_order __order) _NOEXCEPT {
41706c3fb27SDimitry Andric   return __c11_atomic_fetch_add(
41806c3fb27SDimitry Andric       std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order));
41906c3fb27SDimitry Andric }
42006c3fb27SDimitry Andric 
42106c3fb27SDimitry Andric template <class _Tp>
422cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp*
423cb14a3feSDimitry Andric __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT {
42406c3fb27SDimitry Andric   return __c11_atomic_fetch_add(
42506c3fb27SDimitry Andric       std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order));
42606c3fb27SDimitry Andric }
42706c3fb27SDimitry Andric template <class _Tp>
428cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp*
429cb14a3feSDimitry Andric __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*>* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT {
43006c3fb27SDimitry Andric   return __c11_atomic_fetch_add(
43106c3fb27SDimitry Andric       std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order));
43206c3fb27SDimitry Andric }
43306c3fb27SDimitry Andric 
43406c3fb27SDimitry Andric template <class _Tp>
435cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
436cb14a3feSDimitry Andric __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, memory_order __order) _NOEXCEPT {
43706c3fb27SDimitry Andric   return __c11_atomic_fetch_sub(
43806c3fb27SDimitry Andric       std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order));
43906c3fb27SDimitry Andric }
44006c3fb27SDimitry Andric template <class _Tp>
441cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
442cb14a3feSDimitry Andric __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp>* __a, _Tp __delta, memory_order __order) _NOEXCEPT {
44306c3fb27SDimitry Andric   return __c11_atomic_fetch_sub(
44406c3fb27SDimitry Andric       std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order));
44506c3fb27SDimitry Andric }
44606c3fb27SDimitry Andric template <class _Tp>
447cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp*
448cb14a3feSDimitry Andric __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT {
44906c3fb27SDimitry Andric   return __c11_atomic_fetch_sub(
45006c3fb27SDimitry Andric       std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order));
45106c3fb27SDimitry Andric }
45206c3fb27SDimitry Andric template <class _Tp>
453cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp*
454cb14a3feSDimitry Andric __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*>* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT {
45506c3fb27SDimitry Andric   return __c11_atomic_fetch_sub(
45606c3fb27SDimitry Andric       std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order));
45706c3fb27SDimitry Andric }
45806c3fb27SDimitry Andric 
45906c3fb27SDimitry Andric template <class _Tp>
460cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
461cb14a3feSDimitry Andric __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT {
46206c3fb27SDimitry Andric   return __c11_atomic_fetch_and(
46306c3fb27SDimitry Andric       std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order));
46406c3fb27SDimitry Andric }
46506c3fb27SDimitry Andric template <class _Tp>
466cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
467cb14a3feSDimitry Andric __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) _NOEXCEPT {
46806c3fb27SDimitry Andric   return __c11_atomic_fetch_and(
46906c3fb27SDimitry Andric       std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order));
47006c3fb27SDimitry Andric }
47106c3fb27SDimitry Andric 
47206c3fb27SDimitry Andric template <class _Tp>
473cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
474cb14a3feSDimitry Andric __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT {
47506c3fb27SDimitry Andric   return __c11_atomic_fetch_or(
47606c3fb27SDimitry Andric       std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order));
47706c3fb27SDimitry Andric }
47806c3fb27SDimitry Andric template <class _Tp>
479cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
480cb14a3feSDimitry Andric __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) _NOEXCEPT {
48106c3fb27SDimitry Andric   return __c11_atomic_fetch_or(
48206c3fb27SDimitry Andric       std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order));
48306c3fb27SDimitry Andric }
48406c3fb27SDimitry Andric 
48506c3fb27SDimitry Andric template <class _Tp>
486cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
487cb14a3feSDimitry Andric __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT {
48806c3fb27SDimitry Andric   return __c11_atomic_fetch_xor(
48906c3fb27SDimitry Andric       std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order));
49006c3fb27SDimitry Andric }
49106c3fb27SDimitry Andric template <class _Tp>
492cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp
493cb14a3feSDimitry Andric __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) _NOEXCEPT {
49406c3fb27SDimitry Andric   return __c11_atomic_fetch_xor(
49506c3fb27SDimitry Andric       std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order));
49606c3fb27SDimitry Andric }
49706c3fb27SDimitry Andric 
49806c3fb27SDimitry Andric #endif // _LIBCPP_HAS_GCC_ATOMIC_IMP, _LIBCPP_HAS_C_ATOMIC_IMP
49906c3fb27SDimitry Andric 
500cb14a3feSDimitry Andric template <typename _Tp, typename _Base = __cxx_atomic_base_impl<_Tp> >
50106c3fb27SDimitry Andric struct __cxx_atomic_impl : public _Base {
502cb14a3feSDimitry Andric   static_assert(is_trivially_copyable<_Tp>::value, "std::atomic<T> requires that 'T' be a trivially copyable type");
50306c3fb27SDimitry Andric 
50406c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI __cxx_atomic_impl() _NOEXCEPT = default;
505cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __cxx_atomic_impl(_Tp __value) _NOEXCEPT : _Base(__value) {}
50606c3fb27SDimitry Andric };
50706c3fb27SDimitry Andric 
50806c3fb27SDimitry Andric _LIBCPP_END_NAMESPACE_STD
50906c3fb27SDimitry Andric 
51006c3fb27SDimitry Andric #endif // _LIBCPP___ATOMIC_CXX_ATOMIC_IMPL_H
511