libcxx

libcxx mirror with random patches
git clone https://git.neptards.moe/neptards/libcxx.git
Log | Files | Refs

atomic_support.h (5242B)


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