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