1*c05d8e5dSAndroid Build Coastguard Worker //===----------------------------------------------------------------------===////
2*c05d8e5dSAndroid Build Coastguard Worker //
3*c05d8e5dSAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*c05d8e5dSAndroid Build Coastguard Worker //
5*c05d8e5dSAndroid Build Coastguard Worker // This file is dual licensed under the MIT and the University of Illinois Open
6*c05d8e5dSAndroid Build Coastguard Worker // Source Licenses. See LICENSE.TXT for details.
7*c05d8e5dSAndroid Build Coastguard Worker //
8*c05d8e5dSAndroid Build Coastguard Worker //===----------------------------------------------------------------------===////
9*c05d8e5dSAndroid Build Coastguard Worker
10*c05d8e5dSAndroid Build Coastguard Worker // FIXME: This file is copied from libcxx/src/include/atomic_support.h. Instead
11*c05d8e5dSAndroid Build Coastguard Worker // of duplicating the file in libc++abi we should require that the libc++
12*c05d8e5dSAndroid Build Coastguard Worker // sources are available when building libc++abi.
13*c05d8e5dSAndroid Build Coastguard Worker
14*c05d8e5dSAndroid Build Coastguard Worker #ifndef ATOMIC_SUPPORT_H
15*c05d8e5dSAndroid Build Coastguard Worker #define ATOMIC_SUPPORT_H
16*c05d8e5dSAndroid Build Coastguard Worker
17*c05d8e5dSAndroid Build Coastguard Worker #include "__config"
18*c05d8e5dSAndroid Build Coastguard Worker #include "memory" // for __libcpp_relaxed_load
19*c05d8e5dSAndroid Build Coastguard Worker
20*c05d8e5dSAndroid Build Coastguard Worker #if defined(__clang__) && __has_builtin(__atomic_load_n) \
21*c05d8e5dSAndroid Build Coastguard Worker && __has_builtin(__atomic_store_n) \
22*c05d8e5dSAndroid Build Coastguard Worker && __has_builtin(__atomic_add_fetch) \
23*c05d8e5dSAndroid Build Coastguard Worker && __has_builtin(__atomic_exchange_n) \
24*c05d8e5dSAndroid Build Coastguard Worker && __has_builtin(__atomic_compare_exchange_n) \
25*c05d8e5dSAndroid Build Coastguard Worker && defined(__ATOMIC_RELAXED) \
26*c05d8e5dSAndroid Build Coastguard Worker && defined(__ATOMIC_CONSUME) \
27*c05d8e5dSAndroid Build Coastguard Worker && defined(__ATOMIC_ACQUIRE) \
28*c05d8e5dSAndroid Build Coastguard Worker && defined(__ATOMIC_RELEASE) \
29*c05d8e5dSAndroid Build Coastguard Worker && defined(__ATOMIC_ACQ_REL) \
30*c05d8e5dSAndroid Build Coastguard Worker && defined(__ATOMIC_SEQ_CST)
31*c05d8e5dSAndroid Build Coastguard Worker # define _LIBCXXABI_HAS_ATOMIC_BUILTINS
32*c05d8e5dSAndroid Build Coastguard Worker #elif !defined(__clang__) && defined(_GNUC_VER) && _GNUC_VER >= 407
33*c05d8e5dSAndroid Build Coastguard Worker # define _LIBCXXABI_HAS_ATOMIC_BUILTINS
34*c05d8e5dSAndroid Build Coastguard Worker #endif
35*c05d8e5dSAndroid Build Coastguard Worker
36*c05d8e5dSAndroid Build Coastguard Worker #if !defined(_LIBCXXABI_HAS_ATOMIC_BUILTINS) && !defined(_LIBCXXABI_HAS_NO_THREADS)
37*c05d8e5dSAndroid Build Coastguard Worker # if defined(_LIBCPP_WARNING)
38*c05d8e5dSAndroid Build Coastguard Worker _LIBCPP_WARNING("Building libc++ without __atomic builtins is unsupported")
39*c05d8e5dSAndroid Build Coastguard Worker # else
40*c05d8e5dSAndroid Build Coastguard Worker # warning Building libc++ without __atomic builtins is unsupported
41*c05d8e5dSAndroid Build Coastguard Worker # endif
42*c05d8e5dSAndroid Build Coastguard Worker #endif
43*c05d8e5dSAndroid Build Coastguard Worker
44*c05d8e5dSAndroid Build Coastguard Worker _LIBCPP_BEGIN_NAMESPACE_STD
45*c05d8e5dSAndroid Build Coastguard Worker
46*c05d8e5dSAndroid Build Coastguard Worker namespace {
47*c05d8e5dSAndroid Build Coastguard Worker
48*c05d8e5dSAndroid Build Coastguard Worker #if defined(_LIBCXXABI_HAS_ATOMIC_BUILTINS) && !defined(_LIBCXXABI_HAS_NO_THREADS)
49*c05d8e5dSAndroid Build Coastguard Worker
50*c05d8e5dSAndroid Build Coastguard Worker enum __libcpp_atomic_order {
51*c05d8e5dSAndroid Build Coastguard Worker _AO_Relaxed = __ATOMIC_RELAXED,
52*c05d8e5dSAndroid Build Coastguard Worker _AO_Consume = __ATOMIC_CONSUME,
53*c05d8e5dSAndroid Build Coastguard Worker _AO_Acquire = __ATOMIC_ACQUIRE,
54*c05d8e5dSAndroid Build Coastguard Worker _AO_Release = __ATOMIC_RELEASE,
55*c05d8e5dSAndroid Build Coastguard Worker _AO_Acq_Rel = __ATOMIC_ACQ_REL,
56*c05d8e5dSAndroid Build Coastguard Worker _AO_Seq = __ATOMIC_SEQ_CST
57*c05d8e5dSAndroid Build Coastguard Worker };
58*c05d8e5dSAndroid Build Coastguard Worker
59*c05d8e5dSAndroid Build Coastguard Worker template <class _ValueType, class _FromType>
60*c05d8e5dSAndroid Build Coastguard Worker inline _LIBCPP_INLINE_VISIBILITY
61*c05d8e5dSAndroid Build Coastguard Worker void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
62*c05d8e5dSAndroid Build Coastguard Worker int __order = _AO_Seq)
63*c05d8e5dSAndroid Build Coastguard Worker {
64*c05d8e5dSAndroid Build Coastguard Worker __atomic_store_n(__dest, __val, __order);
65*c05d8e5dSAndroid Build Coastguard Worker }
66*c05d8e5dSAndroid Build Coastguard Worker
67*c05d8e5dSAndroid Build Coastguard Worker template <class _ValueType, class _FromType>
68*c05d8e5dSAndroid Build Coastguard Worker inline _LIBCPP_INLINE_VISIBILITY
__libcpp_relaxed_store(_ValueType * __dest,_FromType __val)69*c05d8e5dSAndroid Build Coastguard Worker void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
70*c05d8e5dSAndroid Build Coastguard Worker {
71*c05d8e5dSAndroid Build Coastguard Worker __atomic_store_n(__dest, __val, _AO_Relaxed);
72*c05d8e5dSAndroid Build Coastguard Worker }
73*c05d8e5dSAndroid Build Coastguard Worker
74*c05d8e5dSAndroid Build Coastguard Worker template <class _ValueType>
75*c05d8e5dSAndroid Build Coastguard Worker inline _LIBCPP_INLINE_VISIBILITY
76*c05d8e5dSAndroid Build Coastguard Worker _ValueType __libcpp_atomic_load(_ValueType const* __val,
77*c05d8e5dSAndroid Build Coastguard Worker int __order = _AO_Seq)
78*c05d8e5dSAndroid Build Coastguard Worker {
79*c05d8e5dSAndroid Build Coastguard Worker return __atomic_load_n(__val, __order);
80*c05d8e5dSAndroid Build Coastguard Worker }
81*c05d8e5dSAndroid Build Coastguard Worker
82*c05d8e5dSAndroid Build Coastguard Worker template <class _ValueType, class _AddType>
83*c05d8e5dSAndroid Build Coastguard Worker inline _LIBCPP_INLINE_VISIBILITY
84*c05d8e5dSAndroid Build Coastguard Worker _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
85*c05d8e5dSAndroid Build Coastguard Worker int __order = _AO_Seq)
86*c05d8e5dSAndroid Build Coastguard Worker {
87*c05d8e5dSAndroid Build Coastguard Worker return __atomic_add_fetch(__val, __a, __order);
88*c05d8e5dSAndroid Build Coastguard Worker }
89*c05d8e5dSAndroid Build Coastguard Worker
90*c05d8e5dSAndroid Build Coastguard Worker template <class _ValueType>
91*c05d8e5dSAndroid Build Coastguard Worker inline _LIBCPP_INLINE_VISIBILITY
92*c05d8e5dSAndroid Build Coastguard Worker _ValueType __libcpp_atomic_exchange(_ValueType* __target,
93*c05d8e5dSAndroid Build Coastguard Worker _ValueType __value, int __order = _AO_Seq)
94*c05d8e5dSAndroid Build Coastguard Worker {
95*c05d8e5dSAndroid Build Coastguard Worker return __atomic_exchange_n(__target, __value, __order);
96*c05d8e5dSAndroid Build Coastguard Worker }
97*c05d8e5dSAndroid Build Coastguard Worker
98*c05d8e5dSAndroid Build Coastguard Worker template <class _ValueType>
99*c05d8e5dSAndroid Build Coastguard Worker inline _LIBCPP_INLINE_VISIBILITY
100*c05d8e5dSAndroid Build Coastguard Worker bool __libcpp_atomic_compare_exchange(_ValueType* __val,
101*c05d8e5dSAndroid Build Coastguard Worker _ValueType* __expected, _ValueType __after,
102*c05d8e5dSAndroid Build Coastguard Worker int __success_order = _AO_Seq,
103*c05d8e5dSAndroid Build Coastguard Worker int __fail_order = _AO_Seq)
104*c05d8e5dSAndroid Build Coastguard Worker {
105*c05d8e5dSAndroid Build Coastguard Worker return __atomic_compare_exchange_n(__val, __expected, __after, true,
106*c05d8e5dSAndroid Build Coastguard Worker __success_order, __fail_order);
107*c05d8e5dSAndroid Build Coastguard Worker }
108*c05d8e5dSAndroid Build Coastguard Worker
109*c05d8e5dSAndroid Build Coastguard Worker #else // _LIBCPP_HAS_NO_THREADS
110*c05d8e5dSAndroid Build Coastguard Worker
111*c05d8e5dSAndroid Build Coastguard Worker enum __libcpp_atomic_order {
112*c05d8e5dSAndroid Build Coastguard Worker _AO_Relaxed,
113*c05d8e5dSAndroid Build Coastguard Worker _AO_Consume,
114*c05d8e5dSAndroid Build Coastguard Worker _AO_Acquire,
115*c05d8e5dSAndroid Build Coastguard Worker _AO_Release,
116*c05d8e5dSAndroid Build Coastguard Worker _AO_Acq_Rel,
117*c05d8e5dSAndroid Build Coastguard Worker _AO_Seq
118*c05d8e5dSAndroid Build Coastguard Worker };
119*c05d8e5dSAndroid Build Coastguard Worker
120*c05d8e5dSAndroid Build Coastguard Worker template <class _ValueType, class _FromType>
121*c05d8e5dSAndroid Build Coastguard Worker inline _LIBCPP_INLINE_VISIBILITY
122*c05d8e5dSAndroid Build Coastguard Worker void __libcpp_atomic_store(_ValueType* __dest, _FromType __val,
123*c05d8e5dSAndroid Build Coastguard Worker int = 0)
124*c05d8e5dSAndroid Build Coastguard Worker {
125*c05d8e5dSAndroid Build Coastguard Worker *__dest = __val;
126*c05d8e5dSAndroid Build Coastguard Worker }
127*c05d8e5dSAndroid Build Coastguard Worker
128*c05d8e5dSAndroid Build Coastguard Worker template <class _ValueType, class _FromType>
129*c05d8e5dSAndroid Build Coastguard Worker inline _LIBCPP_INLINE_VISIBILITY
130*c05d8e5dSAndroid Build Coastguard Worker void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
131*c05d8e5dSAndroid Build Coastguard Worker {
132*c05d8e5dSAndroid Build Coastguard Worker *__dest = __val;
133*c05d8e5dSAndroid Build Coastguard Worker }
134*c05d8e5dSAndroid Build Coastguard Worker
135*c05d8e5dSAndroid Build Coastguard Worker template <class _ValueType>
136*c05d8e5dSAndroid Build Coastguard Worker inline _LIBCPP_INLINE_VISIBILITY
137*c05d8e5dSAndroid Build Coastguard Worker _ValueType __libcpp_atomic_load(_ValueType const* __val,
138*c05d8e5dSAndroid Build Coastguard Worker int = 0)
139*c05d8e5dSAndroid Build Coastguard Worker {
140*c05d8e5dSAndroid Build Coastguard Worker return *__val;
141*c05d8e5dSAndroid Build Coastguard Worker }
142*c05d8e5dSAndroid Build Coastguard Worker
143*c05d8e5dSAndroid Build Coastguard Worker template <class _ValueType, class _AddType>
144*c05d8e5dSAndroid Build Coastguard Worker inline _LIBCPP_INLINE_VISIBILITY
145*c05d8e5dSAndroid Build Coastguard Worker _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
146*c05d8e5dSAndroid Build Coastguard Worker int = 0)
147*c05d8e5dSAndroid Build Coastguard Worker {
148*c05d8e5dSAndroid Build Coastguard Worker return *__val += __a;
149*c05d8e5dSAndroid Build Coastguard Worker }
150*c05d8e5dSAndroid Build Coastguard Worker
151*c05d8e5dSAndroid Build Coastguard Worker template <class _ValueType>
152*c05d8e5dSAndroid Build Coastguard Worker inline _LIBCPP_INLINE_VISIBILITY
153*c05d8e5dSAndroid Build Coastguard Worker _ValueType __libcpp_atomic_exchange(_ValueType* __target,
154*c05d8e5dSAndroid Build Coastguard Worker _ValueType __value, int = _AO_Seq)
155*c05d8e5dSAndroid Build Coastguard Worker {
156*c05d8e5dSAndroid Build Coastguard Worker _ValueType old = *__target;
157*c05d8e5dSAndroid Build Coastguard Worker *__target = __value;
158*c05d8e5dSAndroid Build Coastguard Worker return old;
159*c05d8e5dSAndroid Build Coastguard Worker }
160*c05d8e5dSAndroid Build Coastguard Worker
161*c05d8e5dSAndroid Build Coastguard Worker template <class _ValueType>
162*c05d8e5dSAndroid Build Coastguard Worker inline _LIBCPP_INLINE_VISIBILITY
163*c05d8e5dSAndroid Build Coastguard Worker bool __libcpp_atomic_compare_exchange(_ValueType* __val,
164*c05d8e5dSAndroid Build Coastguard Worker _ValueType* __expected, _ValueType __after,
165*c05d8e5dSAndroid Build Coastguard Worker int = 0, int = 0)
166*c05d8e5dSAndroid Build Coastguard Worker {
167*c05d8e5dSAndroid Build Coastguard Worker if (*__val == *__expected) {
168*c05d8e5dSAndroid Build Coastguard Worker *__val = __after;
169*c05d8e5dSAndroid Build Coastguard Worker return true;
170*c05d8e5dSAndroid Build Coastguard Worker }
171*c05d8e5dSAndroid Build Coastguard Worker *__expected = *__val;
172*c05d8e5dSAndroid Build Coastguard Worker return false;
173*c05d8e5dSAndroid Build Coastguard Worker }
174*c05d8e5dSAndroid Build Coastguard Worker
175*c05d8e5dSAndroid Build Coastguard Worker #endif // _LIBCPP_HAS_NO_THREADS
176*c05d8e5dSAndroid Build Coastguard Worker
177*c05d8e5dSAndroid Build Coastguard Worker } // end namespace
178*c05d8e5dSAndroid Build Coastguard Worker
179*c05d8e5dSAndroid Build Coastguard Worker _LIBCPP_END_NAMESPACE_STD
180*c05d8e5dSAndroid Build Coastguard Worker
181*c05d8e5dSAndroid Build Coastguard Worker namespace {
182*c05d8e5dSAndroid Build Coastguard Worker
183*c05d8e5dSAndroid Build Coastguard Worker template <class IntType>
184*c05d8e5dSAndroid Build Coastguard Worker class AtomicInt {
185*c05d8e5dSAndroid Build Coastguard Worker public:
186*c05d8e5dSAndroid Build Coastguard Worker using MemoryOrder = std::__libcpp_atomic_order;
187*c05d8e5dSAndroid Build Coastguard Worker
AtomicInt(IntType * b)188*c05d8e5dSAndroid Build Coastguard Worker explicit AtomicInt(IntType *b) : b(b) {}
189*c05d8e5dSAndroid Build Coastguard Worker AtomicInt(AtomicInt const&) = delete;
190*c05d8e5dSAndroid Build Coastguard Worker AtomicInt& operator=(AtomicInt const&) = delete;
191*c05d8e5dSAndroid Build Coastguard Worker
load(MemoryOrder ord)192*c05d8e5dSAndroid Build Coastguard Worker IntType load(MemoryOrder ord) {
193*c05d8e5dSAndroid Build Coastguard Worker return std::__libcpp_atomic_load(b, ord);
194*c05d8e5dSAndroid Build Coastguard Worker }
store(IntType val,MemoryOrder ord)195*c05d8e5dSAndroid Build Coastguard Worker void store(IntType val, MemoryOrder ord) {
196*c05d8e5dSAndroid Build Coastguard Worker std::__libcpp_atomic_store(b, val, ord);
197*c05d8e5dSAndroid Build Coastguard Worker }
exchange(IntType new_val,MemoryOrder ord)198*c05d8e5dSAndroid Build Coastguard Worker IntType exchange(IntType new_val, MemoryOrder ord) {
199*c05d8e5dSAndroid Build Coastguard Worker return std::__libcpp_atomic_exchange(b, new_val, ord);
200*c05d8e5dSAndroid Build Coastguard Worker }
compare_exchange(IntType * expected,IntType desired,MemoryOrder ord_success,MemoryOrder ord_failure)201*c05d8e5dSAndroid Build Coastguard Worker bool compare_exchange(IntType *expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) {
202*c05d8e5dSAndroid Build Coastguard Worker return std::__libcpp_atomic_compare_exchange(b, expected, desired, ord_success, ord_failure);
203*c05d8e5dSAndroid Build Coastguard Worker }
204*c05d8e5dSAndroid Build Coastguard Worker
205*c05d8e5dSAndroid Build Coastguard Worker private:
206*c05d8e5dSAndroid Build Coastguard Worker IntType *b;
207*c05d8e5dSAndroid Build Coastguard Worker };
208*c05d8e5dSAndroid Build Coastguard Worker
209*c05d8e5dSAndroid Build Coastguard Worker } // end namespace
210*c05d8e5dSAndroid Build Coastguard Worker
211*c05d8e5dSAndroid Build Coastguard Worker #endif // ATOMIC_SUPPORT_H
212