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