133 lines · c
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-exception6//7//===----------------------------------------------------------------------===////8 9#ifndef ATOMIC_SUPPORT_H10#define ATOMIC_SUPPORT_H11 12#include <__config>13#include <memory> // for __libcpp_relaxed_load14 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_BUILTINS20#elif defined(_LIBCPP_COMPILER_GCC)21# define _LIBCPP_HAS_ATOMIC_BUILTINS22#endif23 24#if !defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && _LIBCPP_HAS_THREADS25# if defined(_LIBCPP_WARNING)26_LIBCPP_WARNING("Building libc++ without __atomic builtins is unsupported")27# else28# warning Building libc++ without __atomic builtins is unsupported29# endif30#endif31 32_LIBCPP_BEGIN_NAMESPACE_STD33 34namespace {35 36#if defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && _LIBCPP_HAS_THREADS37 38enum __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_CST45};46 47template <class _ValueType, class _FromType>48inline _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 52template <class _ValueType, class _FromType>53inline _LIBCPP_HIDE_FROM_ABI void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val) {54 __atomic_store_n(__dest, __val, _AO_Relaxed);55}56 57template <class _ValueType>58inline _LIBCPP_HIDE_FROM_ABI _ValueType __libcpp_atomic_load(_ValueType const* __val, int __order = _AO_Seq) {59 return __atomic_load_n(__val, __order);60}61 62template <class _ValueType, class _AddType>63inline _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 67template <class _ValueType>68inline _LIBCPP_HIDE_FROM_ABI _ValueType69__libcpp_atomic_exchange(_ValueType* __target, _ValueType __value, int __order = _AO_Seq) {70 return __atomic_exchange_n(__target, __value, __order);71}72 73template <class _ValueType>74inline _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_THREADS84 85enum __libcpp_atomic_order { _AO_Relaxed, _AO_Consume, _AO_Acquire, _AO_Release, _AO_Acq_Rel, _AO_Seq };86 87template <class _ValueType, class _FromType>88inline _LIBCPP_HIDE_FROM_ABI void __libcpp_atomic_store(_ValueType* __dest, _FromType __val, int = 0) {89 *__dest = __val;90}91 92template <class _ValueType, class _FromType>93inline _LIBCPP_HIDE_FROM_ABI void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val) {94 *__dest = __val;95}96 97template <class _ValueType>98inline _LIBCPP_HIDE_FROM_ABI _ValueType __libcpp_atomic_load(_ValueType const* __val, int = 0) {99 return *__val;100}101 102template <class _ValueType, class _AddType>103inline _LIBCPP_HIDE_FROM_ABI _ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a, int = 0) {104 return *__val += __a;105}106 107template <class _ValueType>108inline _LIBCPP_HIDE_FROM_ABI _ValueType109__libcpp_atomic_exchange(_ValueType* __target, _ValueType __value, int = _AO_Seq) {110 _ValueType old = *__target;111 *__target = __value;112 return old;113}114 115template <class _ValueType>116inline _LIBCPP_HIDE_FROM_ABI bool117__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_THREADS127 128} // namespace129 130_LIBCPP_END_NAMESPACE_STD131 132#endif // ATOMIC_SUPPORT_H133