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