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