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