1 //===----------------------------------------------------------------------===////
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
7 //===----------------------------------------------------------------------===////
9 #ifndef ATOMIC_SUPPORT_H
10 #define ATOMIC_SUPPORT_H
13 #include "memory" // for __libcpp_relaxed_load
15 #if defined(__clang__) && __has_builtin(__atomic_load_n) \
16 && __has_builtin(__atomic_store_n) \
17 && __has_builtin(__atomic_add_fetch) \
18 && __has_builtin(__atomic_exchange_n) \
19 && __has_builtin(__atomic_compare_exchange_n) \
20 && defined(__ATOMIC_RELAXED) \
21 && defined(__ATOMIC_CONSUME) \
22 && defined(__ATOMIC_ACQUIRE) \
23 && defined(__ATOMIC_RELEASE) \
24 && defined(__ATOMIC_ACQ_REL) \
25 && defined(__ATOMIC_SEQ_CST)
26 # define _LIBCPP_HAS_ATOMIC_BUILTINS
27 #elif !defined(__clang__) && defined(_GNUC_VER) && _GNUC_VER >= 407
28 # define _LIBCPP_HAS_ATOMIC_BUILTINS
31 #if !defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS)
32 # if defined(_LIBCPP_WARNING)
33 _LIBCPP_WARNING("Building libc++ without __atomic builtins is unsupported")
35 # warning Building libc++ without __atomic builtins is unsupported
39 _LIBCPP_BEGIN_NAMESPACE_STD
43 #if defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS)
45 enum __libcpp_atomic_order {
46 _AO_Relaxed = __ATOMIC_RELAXED,
47 _AO_Consume = __ATOMIC_CONSUME,
48 _AO_Acquire = __ATOMIC_ACQUIRE,
49 _AO_Release = __ATOMIC_RELEASE,
50 _AO_Acq_Rel = __ATOMIC_ACQ_REL,
51 _AO_Seq = __ATOMIC_SEQ_CST
54 template <class _ValueType, class _FromType>
55 inline _LIBCPP_INLINE_VISIBILITY
56 void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
57 int __order = _AO_Seq)
59 __atomic_store_n(__dest, __val, __order);
62 template <class _ValueType, class _FromType>
63 inline _LIBCPP_INLINE_VISIBILITY
64 void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
66 __atomic_store_n(__dest, __val, _AO_Relaxed);
69 template <class _ValueType>
70 inline _LIBCPP_INLINE_VISIBILITY
71 _ValueType __libcpp_atomic_load(_ValueType const* __val,
72 int __order = _AO_Seq)
74 return __atomic_load_n(__val, __order);
77 template <class _ValueType, class _AddType>
78 inline _LIBCPP_INLINE_VISIBILITY
79 _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
80 int __order = _AO_Seq)
82 return __atomic_add_fetch(__val, __a, __order);
85 template <class _ValueType>
86 inline _LIBCPP_INLINE_VISIBILITY
87 _ValueType __libcpp_atomic_exchange(_ValueType* __target,
88 _ValueType __value, int __order = _AO_Seq)
90 return __atomic_exchange_n(__target, __value, __order);
93 template <class _ValueType>
94 inline _LIBCPP_INLINE_VISIBILITY
95 bool __libcpp_atomic_compare_exchange(_ValueType* __val,
96 _ValueType* __expected, _ValueType __after,
97 int __success_order = _AO_Seq,
98 int __fail_order = _AO_Seq)
100 return __atomic_compare_exchange_n(__val, __expected, __after, true,
101 __success_order, __fail_order);
104 #else // _LIBCPP_HAS_NO_THREADS
106 enum __libcpp_atomic_order {
115 template <class _ValueType, class _FromType>
116 inline _LIBCPP_INLINE_VISIBILITY
117 void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
123 template <class _ValueType, class _FromType>
124 inline _LIBCPP_INLINE_VISIBILITY
125 void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
130 template <class _ValueType>
131 inline _LIBCPP_INLINE_VISIBILITY
132 _ValueType __libcpp_atomic_load(_ValueType const* __val,
138 template <class _ValueType, class _AddType>
139 inline _LIBCPP_INLINE_VISIBILITY
140 _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
143 return *__val += __a;
146 template <class _ValueType>
147 inline _LIBCPP_INLINE_VISIBILITY
148 _ValueType __libcpp_atomic_exchange(_ValueType* __target,
149 _ValueType __value, int __order = _AO_Seq)
151 _ValueType old = *__target;
156 template <class _ValueType>
157 inline _LIBCPP_INLINE_VISIBILITY
158 bool __libcpp_atomic_compare_exchange(_ValueType* __val,
159 _ValueType* __expected, _ValueType __after,
162 if (*__val == *__expected) {
166 *__expected = *__val;
170 #endif // _LIBCPP_HAS_NO_THREADS
174 _LIBCPP_END_NAMESPACE_STD
176 #endif // ATOMIC_SUPPORT_H