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