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