xref: /llvm-project/libcxx/include/__atomic/support/c11.h (revision 0e34f3f4968d8d32a64e26777541f939deb2274c)
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