• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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