xref: /minix3/external/bsd/libc++/dist/libcxx/src/include/atomic_support.h (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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