| //===----------------------------------------------------------------------===//// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===//// |
| |
| #ifndef ATOMIC_SUPPORT_H |
| #define ATOMIC_SUPPORT_H |
| |
| #include <__config> |
| |
| _LIBCPP_BEGIN_NAMESPACE_STD |
| |
| #if _LIBCPP_HAS_THREADS |
| |
| enum __libcpp_atomic_order { |
| _AO_Relaxed = __ATOMIC_RELAXED, |
| _AO_Consume = __ATOMIC_CONSUME, |
| _AO_Acquire = __ATOMIC_ACQUIRE, |
| _AO_Release = __ATOMIC_RELEASE, |
| _AO_Acq_Rel = __ATOMIC_ACQ_REL, |
| _AO_Seq = __ATOMIC_SEQ_CST |
| }; |
| |
| template <class _ValueType, class _FromType> |
| inline _LIBCPP_HIDE_FROM_ABI void __libcpp_atomic_store(_ValueType* __dest, _FromType __val, int __order = _AO_Seq) { |
| __atomic_store_n(__dest, __val, __order); |
| } |
| |
| template <class _ValueType, class _FromType> |
| inline _LIBCPP_HIDE_FROM_ABI void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val) { |
| __atomic_store_n(__dest, __val, _AO_Relaxed); |
| } |
| |
| template <class _ValueType> |
| inline _LIBCPP_HIDE_FROM_ABI _ValueType __libcpp_atomic_load(_ValueType const* __val, int __order = _AO_Seq) { |
| return __atomic_load_n(__val, __order); |
| } |
| |
| template <class _ValueType, class _AddType> |
| inline _LIBCPP_HIDE_FROM_ABI _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a, int __order = _AO_Seq) { |
| return __atomic_add_fetch(__val, __a, __order); |
| } |
| |
| template <class _ValueType> |
| inline _LIBCPP_HIDE_FROM_ABI _ValueType |
| __libcpp_atomic_exchange(_ValueType* __target, _ValueType __value, int __order = _AO_Seq) { |
| return __atomic_exchange_n(__target, __value, __order); |
| } |
| |
| template <class _ValueType> |
| inline _LIBCPP_HIDE_FROM_ABI bool __libcpp_atomic_compare_exchange( |
| _ValueType* __val, |
| _ValueType* __expected, |
| _ValueType __after, |
| int __success_order = _AO_Seq, |
| int __fail_order = _AO_Seq) { |
| return __atomic_compare_exchange_n(__val, __expected, __after, true, __success_order, __fail_order); |
| } |
| |
| #else // _LIBCPP_HAS_THREADS |
| |
| enum __libcpp_atomic_order { _AO_Relaxed, _AO_Consume, _AO_Acquire, _AO_Release, _AO_Acq_Rel, _AO_Seq }; |
| |
| template <class _ValueType, class _FromType> |
| inline _LIBCPP_HIDE_FROM_ABI void __libcpp_atomic_store(_ValueType* __dest, _FromType __val, int = 0) { |
| *__dest = __val; |
| } |
| |
| template <class _ValueType, class _FromType> |
| inline _LIBCPP_HIDE_FROM_ABI void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val) { |
| *__dest = __val; |
| } |
| |
| template <class _ValueType> |
| inline _LIBCPP_HIDE_FROM_ABI _ValueType __libcpp_atomic_load(_ValueType const* __val, int = 0) { |
| return *__val; |
| } |
| |
| template <class _ValueType, class _AddType> |
| inline _LIBCPP_HIDE_FROM_ABI _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a, int = 0) { |
| return *__val += __a; |
| } |
| |
| template <class _ValueType> |
| inline _LIBCPP_HIDE_FROM_ABI _ValueType |
| __libcpp_atomic_exchange(_ValueType* __target, _ValueType __value, int = _AO_Seq) { |
| _ValueType old = *__target; |
| *__target = __value; |
| return old; |
| } |
| |
| template <class _ValueType> |
| inline _LIBCPP_HIDE_FROM_ABI bool |
| __libcpp_atomic_compare_exchange(_ValueType* __val, _ValueType* __expected, _ValueType __after, int = 0, int = 0) { |
| if (*__val == *__expected) { |
| *__val = __after; |
| return true; |
| } |
| *__expected = *__val; |
| return false; |
| } |
| |
| #endif // _LIBCPP_HAS_THREADS |
| |
| _LIBCPP_END_NAMESPACE_STD |
| |
| #endif // ATOMIC_SUPPORT_H |