xref: /aosp_15_r20/external/libcxxabi/src/include/atomic_support.h (revision c05d8e5dc3e10f6ce4317e8bc22cc4a25f55fa94)
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