xref: /openbsd-src/gnu/llvm/libcxx/src/include/atomic_support.h (revision 4bdff4bed0e3d54e55670334c7d0077db4170f86)
146035553Spatrick //===----------------------------------------------------------------------===////
246035553Spatrick //
346035553Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
446035553Spatrick // See https://llvm.org/LICENSE.txt for license information.
546035553Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
646035553Spatrick //
746035553Spatrick //===----------------------------------------------------------------------===////
846035553Spatrick 
946035553Spatrick #ifndef ATOMIC_SUPPORT_H
1046035553Spatrick #define ATOMIC_SUPPORT_H
1146035553Spatrick 
12*4bdff4beSrobert #include <__config>
13*4bdff4beSrobert #include <memory> // for __libcpp_relaxed_load
1446035553Spatrick 
1546035553Spatrick #if defined(__clang__) && __has_builtin(__atomic_load_n)             \
1646035553Spatrick                        && __has_builtin(__atomic_store_n)            \
1746035553Spatrick                        && __has_builtin(__atomic_add_fetch)          \
1846035553Spatrick                        && __has_builtin(__atomic_exchange_n)         \
1946035553Spatrick                        && __has_builtin(__atomic_compare_exchange_n) \
2046035553Spatrick                        && defined(__ATOMIC_RELAXED)                  \
2146035553Spatrick                        && defined(__ATOMIC_CONSUME)                  \
2246035553Spatrick                        && defined(__ATOMIC_ACQUIRE)                  \
2346035553Spatrick                        && defined(__ATOMIC_RELEASE)                  \
2446035553Spatrick                        && defined(__ATOMIC_ACQ_REL)                  \
2546035553Spatrick                        && defined(__ATOMIC_SEQ_CST)
2646035553Spatrick #   define _LIBCPP_HAS_ATOMIC_BUILTINS
27*4bdff4beSrobert #elif defined(_LIBCPP_COMPILER_GCC)
2846035553Spatrick #   define _LIBCPP_HAS_ATOMIC_BUILTINS
2946035553Spatrick #endif
3046035553Spatrick 
3146035553Spatrick #if !defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS)
3246035553Spatrick # if defined(_LIBCPP_WARNING)
3346035553Spatrick     _LIBCPP_WARNING("Building libc++ without __atomic builtins is unsupported")
3446035553Spatrick # else
3546035553Spatrick #   warning Building libc++ without __atomic builtins is unsupported
3646035553Spatrick # endif
3746035553Spatrick #endif
3846035553Spatrick 
3946035553Spatrick _LIBCPP_BEGIN_NAMESPACE_STD
4046035553Spatrick 
4146035553Spatrick namespace {
4246035553Spatrick 
4346035553Spatrick #if defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS)
4446035553Spatrick 
4546035553Spatrick enum __libcpp_atomic_order {
4646035553Spatrick     _AO_Relaxed = __ATOMIC_RELAXED,
4746035553Spatrick     _AO_Consume = __ATOMIC_CONSUME,
4846035553Spatrick     _AO_Acquire = __ATOMIC_ACQUIRE,
4946035553Spatrick     _AO_Release = __ATOMIC_RELEASE,
5046035553Spatrick     _AO_Acq_Rel = __ATOMIC_ACQ_REL,
5146035553Spatrick     _AO_Seq     = __ATOMIC_SEQ_CST
5246035553Spatrick };
5346035553Spatrick 
5446035553Spatrick template <class _ValueType, class _FromType>
5546035553Spatrick inline _LIBCPP_INLINE_VISIBILITY
5646035553Spatrick void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
5746035553Spatrick                            int __order = _AO_Seq)
5846035553Spatrick {
5946035553Spatrick     __atomic_store_n(__dest, __val, __order);
6046035553Spatrick }
6146035553Spatrick 
6246035553Spatrick template <class _ValueType, class _FromType>
6346035553Spatrick inline _LIBCPP_INLINE_VISIBILITY
__libcpp_relaxed_store(_ValueType * __dest,_FromType __val)6446035553Spatrick void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
6546035553Spatrick {
6646035553Spatrick     __atomic_store_n(__dest, __val, _AO_Relaxed);
6746035553Spatrick }
6846035553Spatrick 
6946035553Spatrick template <class _ValueType>
7046035553Spatrick inline _LIBCPP_INLINE_VISIBILITY
7146035553Spatrick _ValueType __libcpp_atomic_load(_ValueType const* __val,
7246035553Spatrick                                 int __order = _AO_Seq)
7346035553Spatrick {
7446035553Spatrick     return __atomic_load_n(__val, __order);
7546035553Spatrick }
7646035553Spatrick 
7746035553Spatrick template <class _ValueType, class _AddType>
7846035553Spatrick inline _LIBCPP_INLINE_VISIBILITY
7946035553Spatrick _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
8046035553Spatrick                                int __order = _AO_Seq)
8146035553Spatrick {
8246035553Spatrick     return __atomic_add_fetch(__val, __a, __order);
8346035553Spatrick }
8446035553Spatrick 
8546035553Spatrick template <class _ValueType>
8646035553Spatrick inline _LIBCPP_INLINE_VISIBILITY
8746035553Spatrick _ValueType __libcpp_atomic_exchange(_ValueType* __target,
8846035553Spatrick                                     _ValueType __value, int __order = _AO_Seq)
8946035553Spatrick {
9046035553Spatrick     return __atomic_exchange_n(__target, __value, __order);
9146035553Spatrick }
9246035553Spatrick 
9346035553Spatrick template <class _ValueType>
9446035553Spatrick inline _LIBCPP_INLINE_VISIBILITY
9546035553Spatrick bool __libcpp_atomic_compare_exchange(_ValueType* __val,
9646035553Spatrick     _ValueType* __expected, _ValueType __after,
9746035553Spatrick     int __success_order = _AO_Seq,
9846035553Spatrick     int __fail_order = _AO_Seq)
9946035553Spatrick {
10046035553Spatrick     return __atomic_compare_exchange_n(__val, __expected, __after, true,
10146035553Spatrick                                        __success_order, __fail_order);
10246035553Spatrick }
10346035553Spatrick 
10446035553Spatrick #else // _LIBCPP_HAS_NO_THREADS
10546035553Spatrick 
10646035553Spatrick enum __libcpp_atomic_order {
10746035553Spatrick     _AO_Relaxed,
10846035553Spatrick     _AO_Consume,
10946035553Spatrick     _AO_Acquire,
11046035553Spatrick     _AO_Release,
11146035553Spatrick     _AO_Acq_Rel,
11246035553Spatrick     _AO_Seq
11346035553Spatrick };
11446035553Spatrick 
11546035553Spatrick template <class _ValueType, class _FromType>
11646035553Spatrick inline _LIBCPP_INLINE_VISIBILITY
11746035553Spatrick void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
11846035553Spatrick                            int = 0)
11946035553Spatrick {
12046035553Spatrick     *__dest = __val;
12146035553Spatrick }
12246035553Spatrick 
12346035553Spatrick template <class _ValueType, class _FromType>
12446035553Spatrick inline _LIBCPP_INLINE_VISIBILITY
12546035553Spatrick void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
12646035553Spatrick {
12746035553Spatrick     *__dest = __val;
12846035553Spatrick }
12946035553Spatrick 
13046035553Spatrick template <class _ValueType>
13146035553Spatrick inline _LIBCPP_INLINE_VISIBILITY
13246035553Spatrick _ValueType __libcpp_atomic_load(_ValueType const* __val,
13346035553Spatrick                                 int = 0)
13446035553Spatrick {
13546035553Spatrick     return *__val;
13646035553Spatrick }
13746035553Spatrick 
13846035553Spatrick template <class _ValueType, class _AddType>
13946035553Spatrick inline _LIBCPP_INLINE_VISIBILITY
14046035553Spatrick _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
14146035553Spatrick                                int = 0)
14246035553Spatrick {
14346035553Spatrick     return *__val += __a;
14446035553Spatrick }
14546035553Spatrick 
14646035553Spatrick template <class _ValueType>
14746035553Spatrick inline _LIBCPP_INLINE_VISIBILITY
14846035553Spatrick _ValueType __libcpp_atomic_exchange(_ValueType* __target,
149*4bdff4beSrobert                                     _ValueType __value, int = _AO_Seq)
15046035553Spatrick {
15146035553Spatrick     _ValueType old = *__target;
15246035553Spatrick     *__target = __value;
15346035553Spatrick     return old;
15446035553Spatrick }
15546035553Spatrick 
15646035553Spatrick template <class _ValueType>
15746035553Spatrick inline _LIBCPP_INLINE_VISIBILITY
15846035553Spatrick bool __libcpp_atomic_compare_exchange(_ValueType* __val,
15946035553Spatrick     _ValueType* __expected, _ValueType __after,
16046035553Spatrick     int = 0, int = 0)
16146035553Spatrick {
16246035553Spatrick     if (*__val == *__expected) {
16346035553Spatrick         *__val = __after;
16446035553Spatrick         return true;
16546035553Spatrick     }
16646035553Spatrick     *__expected = *__val;
16746035553Spatrick     return false;
16846035553Spatrick }
16946035553Spatrick 
17046035553Spatrick #endif // _LIBCPP_HAS_NO_THREADS
17146035553Spatrick 
17246035553Spatrick } // end namespace
17346035553Spatrick 
17446035553Spatrick _LIBCPP_END_NAMESPACE_STD
17546035553Spatrick 
17646035553Spatrick #endif // ATOMIC_SUPPORT_H
177