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