150
|
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
|
|
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
|