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
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, class _FromType>
107 inline _LIBCPP_INLINE_VISIBILITY
108 void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val)
109 {
110     *__dest = __val;
111 }
112 
113 template <class _ValueType>
114 inline _LIBCPP_INLINE_VISIBILITY
115 _ValueType __libcpp_atomic_load(_ValueType const* __val,
116                                 int = 0)
117 {
118     return *__val;
119 }
120 
121 template <class _ValueType, class _AddType>
122 inline _LIBCPP_INLINE_VISIBILITY
123 _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a,
124                                int = 0)
125 {
126     return *__val += __a;
127 }
128 
129 template <class _ValueType>
130 inline _LIBCPP_INLINE_VISIBILITY
131 bool __libcpp_atomic_compare_exchange(_ValueType* __val,
132     _ValueType* __expected, _ValueType __after,
133     int = 0, int = 0)
134 {
135     if (*__val == *__expected) {
136         *__val = __after;
137         return true;
138     }
139     *__expected = *__val;
140     return false;
141 }
142 
143 #endif // _LIBCPP_HAS_NO_THREADS
144 
145 } // end namespace
146 
147 _LIBCPP_END_NAMESPACE_STD
148 
149 #endif // ATOMIC_SUPPORT_H
150