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