1 //===----------------------------------------------------------------------===////
2 //
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
6 //
7 //===----------------------------------------------------------------------===////
8
9 // FIXME: This file is copied from libcxx/src/include/atomic_support.h. Instead
10 // of duplicating the file in libc++abi we should require that the libc++
11 // sources are available when building libc++abi.
12
13 #ifndef ATOMIC_SUPPORT_H
14 #define ATOMIC_SUPPORT_H
15
16 #include "__config"
17 #include "memory" // for __libcpp_relaxed_load
18
19 #if defined(__clang__) && __has_builtin(__atomic_load_n) \
20 && __has_builtin(__atomic_store_n) \
21 && __has_builtin(__atomic_add_fetch) \
22 && __has_builtin(__atomic_exchange_n) \
23 && __has_builtin(__atomic_compare_exchange_n) \
24 && defined(__ATOMIC_RELAXED) \
25 && defined(__ATOMIC_CONSUME) \
26 && defined(__ATOMIC_ACQUIRE) \
27 && defined(__ATOMIC_RELEASE) \
28 && defined(__ATOMIC_ACQ_REL) \
29 && defined(__ATOMIC_SEQ_CST)
30 # define _LIBCXXABI_HAS_ATOMIC_BUILTINS
31 #elif !defined(__clang__) && defined(_GNUC_VER) && _GNUC_VER >= 407
32 # define _LIBCXXABI_HAS_ATOMIC_BUILTINS
33 #endif
34
35 #if !defined(_LIBCXXABI_HAS_ATOMIC_BUILTINS) && !defined(_LIBCXXABI_HAS_NO_THREADS)
36 # if defined(_LIBCPP_WARNING)
37 _LIBCPP_WARNING("Building libc++ without __atomic builtins is unsupported")
38 # else
39 # warning Building libc++ without __atomic builtins is unsupported
40 # endif
41 #endif
42
43 _LIBCPP_BEGIN_NAMESPACE_STD
44
45 namespace {
46
47 #if defined(_LIBCXXABI_HAS_ATOMIC_BUILTINS) && !defined(_LIBCXXABI_HAS_NO_THREADS)
48
49 enum __libcpp_atomic_order {
50 _AO_Relaxed = __ATOMIC_RELAXED,
51 _AO_Consume = __ATOMIC_CONSUME,
52 _AO_Acquire = __ATOMIC_ACQUIRE,
53 _AO_Release = __ATOMIC_RELEASE,
54 _AO_Acq_Rel = __ATOMIC_ACQ_REL,
55 _AO_Seq = __ATOMIC_SEQ_CST
56 };
57
58 template <class _ValueType, class _FromType>
59 inline _LIBCPP_INLINE_VISIBILITY
60 void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
61 int __order = _AO_Seq)
62 {
63 __atomic_store_n(__dest, __val, __order);
64 }
65
66 template <class _ValueType, class _FromType>
67 inline _LIBCPP_INLINE_VISIBILITY
__libcpp_relaxed_store(_ValueType * __dest,_FromType __val)68 void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
69 {
70 __atomic_store_n(__dest, __val, _AO_Relaxed);
71 }
72
73 template <class _ValueType>
74 inline _LIBCPP_INLINE_VISIBILITY
75 _ValueType __libcpp_atomic_load(_ValueType const* __val,
76 int __order = _AO_Seq)
77 {
78 return __atomic_load_n(__val, __order);
79 }
80
81 template <class _ValueType, class _AddType>
82 inline _LIBCPP_INLINE_VISIBILITY
83 _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
84 int __order = _AO_Seq)
85 {
86 return __atomic_add_fetch(__val, __a, __order);
87 }
88
89 template <class _ValueType>
90 inline _LIBCPP_INLINE_VISIBILITY
91 _ValueType __libcpp_atomic_exchange(_ValueType* __target,
92 _ValueType __value, int __order = _AO_Seq)
93 {
94 return __atomic_exchange_n(__target, __value, __order);
95 }
96
97 template <class _ValueType>
98 inline _LIBCPP_INLINE_VISIBILITY
99 bool __libcpp_atomic_compare_exchange(_ValueType* __val,
100 _ValueType* __expected, _ValueType __after,
101 int __success_order = _AO_Seq,
102 int __fail_order = _AO_Seq)
103 {
104 return __atomic_compare_exchange_n(__val, __expected, __after, true,
105 __success_order, __fail_order);
106 }
107
108 #else // _LIBCPP_HAS_NO_THREADS
109
110 enum __libcpp_atomic_order {
111 _AO_Relaxed,
112 _AO_Consume,
113 _AO_Acquire,
114 _AO_Release,
115 _AO_Acq_Rel,
116 _AO_Seq
117 };
118
119 template <class _ValueType, class _FromType>
120 inline _LIBCPP_INLINE_VISIBILITY
121 void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
122 int = 0)
123 {
124 *__dest = __val;
125 }
126
127 template <class _ValueType, class _FromType>
128 inline _LIBCPP_INLINE_VISIBILITY
129 void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
130 {
131 *__dest = __val;
132 }
133
134 template <class _ValueType>
135 inline _LIBCPP_INLINE_VISIBILITY
136 _ValueType __libcpp_atomic_load(_ValueType const* __val,
137 int = 0)
138 {
139 return *__val;
140 }
141
142 template <class _ValueType, class _AddType>
143 inline _LIBCPP_INLINE_VISIBILITY
144 _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
145 int = 0)
146 {
147 return *__val += __a;
148 }
149
150 template <class _ValueType>
151 inline _LIBCPP_INLINE_VISIBILITY
152 _ValueType __libcpp_atomic_exchange(_ValueType* __target,
153 _ValueType __value, int = _AO_Seq)
154 {
155 _ValueType old = *__target;
156 *__target = __value;
157 return old;
158 }
159
160 template <class _ValueType>
161 inline _LIBCPP_INLINE_VISIBILITY
162 bool __libcpp_atomic_compare_exchange(_ValueType* __val,
163 _ValueType* __expected, _ValueType __after,
164 int = 0, int = 0)
165 {
166 if (*__val == *__expected) {
167 *__val = __after;
168 return true;
169 }
170 *__expected = *__val;
171 return false;
172 }
173
174 #endif // _LIBCPP_HAS_NO_THREADS
175
176 } // end namespace
177
178 _LIBCPP_END_NAMESPACE_STD
179
180 #endif // ATOMIC_SUPPORT_H
181