Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:13

0001 //===----------------------------------------------------------------------===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef _LIBCPP___ATOMIC_SUPPORT_GCC_H
0010 #define _LIBCPP___ATOMIC_SUPPORT_GCC_H
0011 
0012 #include <__atomic/memory_order.h>
0013 #include <__atomic/to_gcc_order.h>
0014 #include <__config>
0015 #include <__memory/addressof.h>
0016 #include <__type_traits/enable_if.h>
0017 #include <__type_traits/is_assignable.h>
0018 #include <__type_traits/remove_const.h>
0019 
0020 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0021 #  pragma GCC system_header
0022 #endif
0023 
0024 //
0025 // This file implements support for GCC-style atomics
0026 //
0027 
0028 _LIBCPP_BEGIN_NAMESPACE_STD
0029 
0030 // [atomics.types.generic]p1 guarantees _Tp is trivially copyable. Because
0031 // the default operator= in an object is not volatile, a byte-by-byte copy
0032 // is required.
0033 template <typename _Tp, typename _Tv, __enable_if_t<is_assignable<_Tp&, _Tv>::value, int> = 0>
0034 _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_assign_volatile(_Tp& __a_value, _Tv const& __val) {
0035   __a_value = __val;
0036 }
0037 template <typename _Tp, typename _Tv, __enable_if_t<is_assignable<_Tp&, _Tv>::value, int> = 0>
0038 _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_assign_volatile(_Tp volatile& __a_value, _Tv volatile const& __val) {
0039   volatile char* __to         = reinterpret_cast<volatile char*>(std::addressof(__a_value));
0040   volatile char* __end        = __to + sizeof(_Tp);
0041   volatile const char* __from = reinterpret_cast<volatile const char*>(std::addressof(__val));
0042   while (__to != __end)
0043     *__to++ = *__from++;
0044 }
0045 
0046 template <typename _Tp>
0047 struct __cxx_atomic_base_impl {
0048   _LIBCPP_HIDE_FROM_ABI
0049 #ifndef _LIBCPP_CXX03_LANG
0050   __cxx_atomic_base_impl() _NOEXCEPT = default;
0051 #else
0052   __cxx_atomic_base_impl() _NOEXCEPT : __a_value() {
0053   }
0054 #endif // _LIBCPP_CXX03_LANG
0055   _LIBCPP_CONSTEXPR explicit __cxx_atomic_base_impl(_Tp value) _NOEXCEPT : __a_value(value) {}
0056   _Tp __a_value;
0057 };
0058 
0059 template <typename _Tp>
0060 _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val) {
0061   __cxx_atomic_assign_volatile(__a->__a_value, __val);
0062 }
0063 
0064 template <typename _Tp>
0065 _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val) {
0066   __a->__a_value = __val;
0067 }
0068 
0069 _LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_thread_fence(memory_order __order) {
0070   __atomic_thread_fence(__to_gcc_order(__order));
0071 }
0072 
0073 _LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_signal_fence(memory_order __order) {
0074   __atomic_signal_fence(__to_gcc_order(__order));
0075 }
0076 
0077 template <typename _Tp>
0078 _LIBCPP_HIDE_FROM_ABI void
0079 __cxx_atomic_store(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) {
0080   __atomic_store(std::addressof(__a->__a_value), std::addressof(__val), __to_gcc_order(__order));
0081 }
0082 
0083 template <typename _Tp>
0084 _LIBCPP_HIDE_FROM_ABI void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) {
0085   __atomic_store(std::addressof(__a->__a_value), std::addressof(__val), __to_gcc_order(__order));
0086 }
0087 
0088 template <typename _Tp>
0089 _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_load(const volatile __cxx_atomic_base_impl<_Tp>* __a, memory_order __order) {
0090   _Tp __ret;
0091   __atomic_load(std::addressof(__a->__a_value), std::addressof(__ret), __to_gcc_order(__order));
0092   return __ret;
0093 }
0094 
0095 template <typename _Tp>
0096 _LIBCPP_HIDE_FROM_ABI void
0097 __cxx_atomic_load_inplace(const volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp* __dst, memory_order __order) {
0098   __atomic_load(std::addressof(__a->__a_value), __dst, __to_gcc_order(__order));
0099 }
0100 
0101 template <typename _Tp>
0102 _LIBCPP_HIDE_FROM_ABI void
0103 __cxx_atomic_load_inplace(const __cxx_atomic_base_impl<_Tp>* __a, _Tp* __dst, memory_order __order) {
0104   __atomic_load(std::addressof(__a->__a_value), __dst, __to_gcc_order(__order));
0105 }
0106 
0107 template <typename _Tp>
0108 _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_load(const __cxx_atomic_base_impl<_Tp>* __a, memory_order __order) {
0109   _Tp __ret;
0110   __atomic_load(std::addressof(__a->__a_value), std::addressof(__ret), __to_gcc_order(__order));
0111   return __ret;
0112 }
0113 
0114 template <typename _Tp>
0115 _LIBCPP_HIDE_FROM_ABI _Tp
0116 __cxx_atomic_exchange(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) {
0117   _Tp __ret;
0118   __atomic_exchange(
0119       std::addressof(__a->__a_value), std::addressof(__value), std::addressof(__ret), __to_gcc_order(__order));
0120   return __ret;
0121 }
0122 
0123 template <typename _Tp>
0124 _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) {
0125   _Tp __ret;
0126   __atomic_exchange(
0127       std::addressof(__a->__a_value), std::addressof(__value), std::addressof(__ret), __to_gcc_order(__order));
0128   return __ret;
0129 }
0130 
0131 template <typename _Tp>
0132 _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong(
0133     volatile __cxx_atomic_base_impl<_Tp>* __a,
0134     _Tp* __expected,
0135     _Tp __value,
0136     memory_order __success,
0137     memory_order __failure) {
0138   return __atomic_compare_exchange(
0139       std::addressof(__a->__a_value),
0140       __expected,
0141       std::addressof(__value),
0142       false,
0143       __to_gcc_order(__success),
0144       __to_gcc_failure_order(__failure));
0145 }
0146 
0147 template <typename _Tp>
0148 _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong(
0149     __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) {
0150   return __atomic_compare_exchange(
0151       std::addressof(__a->__a_value),
0152       __expected,
0153       std::addressof(__value),
0154       false,
0155       __to_gcc_order(__success),
0156       __to_gcc_failure_order(__failure));
0157 }
0158 
0159 template <typename _Tp>
0160 _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak(
0161     volatile __cxx_atomic_base_impl<_Tp>* __a,
0162     _Tp* __expected,
0163     _Tp __value,
0164     memory_order __success,
0165     memory_order __failure) {
0166   return __atomic_compare_exchange(
0167       std::addressof(__a->__a_value),
0168       __expected,
0169       std::addressof(__value),
0170       true,
0171       __to_gcc_order(__success),
0172       __to_gcc_failure_order(__failure));
0173 }
0174 
0175 template <typename _Tp>
0176 _LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak(
0177     __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) {
0178   return __atomic_compare_exchange(
0179       std::addressof(__a->__a_value),
0180       __expected,
0181       std::addressof(__value),
0182       true,
0183       __to_gcc_order(__success),
0184       __to_gcc_failure_order(__failure));
0185 }
0186 
0187 template <typename _Tp>
0188 struct __skip_amt {
0189   enum { value = 1 };
0190 };
0191 
0192 template <typename _Tp>
0193 struct __skip_amt<_Tp*> {
0194   enum { value = sizeof(_Tp) };
0195 };
0196 
0197 // FIXME: Haven't figured out what the spec says about using arrays with
0198 // atomic_fetch_add. Force a failure rather than creating bad behavior.
0199 template <typename _Tp>
0200 struct __skip_amt<_Tp[]> {};
0201 template <typename _Tp, int n>
0202 struct __skip_amt<_Tp[n]> {};
0203 
0204 template <typename _Tp, typename _Td>
0205 _LIBCPP_HIDE_FROM_ABI _Tp
0206 __cxx_atomic_fetch_add(volatile __cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) {
0207   return __atomic_fetch_add(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order));
0208 }
0209 
0210 template <typename _Tp, typename _Td>
0211 _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) {
0212   return __atomic_fetch_add(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order));
0213 }
0214 
0215 template <typename _Tp, typename _Td>
0216 _LIBCPP_HIDE_FROM_ABI _Tp
0217 __cxx_atomic_fetch_sub(volatile __cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) {
0218   return __atomic_fetch_sub(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order));
0219 }
0220 
0221 template <typename _Tp, typename _Td>
0222 _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) {
0223   return __atomic_fetch_sub(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order));
0224 }
0225 
0226 template <typename _Tp>
0227 _LIBCPP_HIDE_FROM_ABI _Tp
0228 __cxx_atomic_fetch_and(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) {
0229   return __atomic_fetch_and(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order));
0230 }
0231 
0232 template <typename _Tp>
0233 _LIBCPP_HIDE_FROM_ABI _Tp
0234 __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) {
0235   return __atomic_fetch_and(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order));
0236 }
0237 
0238 template <typename _Tp>
0239 _LIBCPP_HIDE_FROM_ABI _Tp
0240 __cxx_atomic_fetch_or(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) {
0241   return __atomic_fetch_or(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order));
0242 }
0243 
0244 template <typename _Tp>
0245 _LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) {
0246   return __atomic_fetch_or(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order));
0247 }
0248 
0249 template <typename _Tp>
0250 _LIBCPP_HIDE_FROM_ABI _Tp
0251 __cxx_atomic_fetch_xor(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) {
0252   return __atomic_fetch_xor(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order));
0253 }
0254 
0255 template <typename _Tp>
0256 _LIBCPP_HIDE_FROM_ABI _Tp
0257 __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) {
0258   return __atomic_fetch_xor(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order));
0259 }
0260 
0261 #define __cxx_atomic_is_lock_free(__s) __atomic_is_lock_free(__s, 0)
0262 
0263 _LIBCPP_END_NAMESPACE_STD
0264 
0265 #endif // _LIBCPP___ATOMIC_SUPPORT_GCC_H