Path: blob/main/contrib/llvm-project/libcxx/include/__atomic/support/gcc.h
213799 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef _LIBCPP___ATOMIC_SUPPORT_GCC_H9#define _LIBCPP___ATOMIC_SUPPORT_GCC_H1011#include <__atomic/memory_order.h>12#include <__atomic/to_gcc_order.h>13#include <__config>14#include <__memory/addressof.h>15#include <__type_traits/enable_if.h>16#include <__type_traits/is_assignable.h>17#include <__type_traits/remove_const.h>1819#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)20# pragma GCC system_header21#endif2223//24// This file implements support for GCC-style atomics25//2627_LIBCPP_BEGIN_NAMESPACE_STD2829// [atomics.types.generic]p1 guarantees _Tp is trivially copyable. Because30// the default operator= in an object is not volatile, a byte-by-byte copy31// is required.32template <typename _Tp, typename _Tv, __enable_if_t<is_assignable<_Tp&, _Tv>::value, int> = 0>33_LIBCPP_HIDE_FROM_ABI void __cxx_atomic_assign_volatile(_Tp& __a_value, _Tv const& __val) {34__a_value = __val;35}36template <typename _Tp, typename _Tv, __enable_if_t<is_assignable<_Tp&, _Tv>::value, int> = 0>37_LIBCPP_HIDE_FROM_ABI void __cxx_atomic_assign_volatile(_Tp volatile& __a_value, _Tv volatile const& __val) {38volatile char* __to = reinterpret_cast<volatile char*>(std::addressof(__a_value));39volatile char* __end = __to + sizeof(_Tp);40volatile const char* __from = reinterpret_cast<volatile const char*>(std::addressof(__val));41while (__to != __end)42*__to++ = *__from++;43}4445template <typename _Tp>46struct __cxx_atomic_base_impl {47_LIBCPP_HIDE_FROM_ABI48#ifndef _LIBCPP_CXX03_LANG49__cxx_atomic_base_impl() _NOEXCEPT = default;50#else51__cxx_atomic_base_impl() _NOEXCEPT : __a_value() {52}53#endif // _LIBCPP_CXX03_LANG54_LIBCPP_CONSTEXPR explicit __cxx_atomic_base_impl(_Tp value) _NOEXCEPT : __a_value(value) {}55_Tp __a_value;56};5758template <typename _Tp>59_LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val) {60__cxx_atomic_assign_volatile(__a->__a_value, __val);61}6263template <typename _Tp>64_LIBCPP_HIDE_FROM_ABI void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val) {65__a->__a_value = __val;66}6768_LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_thread_fence(memory_order __order) {69__atomic_thread_fence(__to_gcc_order(__order));70}7172_LIBCPP_HIDE_FROM_ABI inline void __cxx_atomic_signal_fence(memory_order __order) {73__atomic_signal_fence(__to_gcc_order(__order));74}7576template <typename _Tp>77_LIBCPP_HIDE_FROM_ABI void78__cxx_atomic_store(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) {79__atomic_store(std::addressof(__a->__a_value), std::addressof(__val), __to_gcc_order(__order));80}8182template <typename _Tp>83_LIBCPP_HIDE_FROM_ABI void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val, memory_order __order) {84__atomic_store(std::addressof(__a->__a_value), std::addressof(__val), __to_gcc_order(__order));85}8687template <typename _Tp>88_LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_load(const volatile __cxx_atomic_base_impl<_Tp>* __a, memory_order __order) {89_Tp __ret;90__atomic_load(std::addressof(__a->__a_value), std::addressof(__ret), __to_gcc_order(__order));91return __ret;92}9394template <typename _Tp>95_LIBCPP_HIDE_FROM_ABI void96__cxx_atomic_load_inplace(const volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp* __dst, memory_order __order) {97__atomic_load(std::addressof(__a->__a_value), __dst, __to_gcc_order(__order));98}99100template <typename _Tp>101_LIBCPP_HIDE_FROM_ABI void102__cxx_atomic_load_inplace(const __cxx_atomic_base_impl<_Tp>* __a, _Tp* __dst, memory_order __order) {103__atomic_load(std::addressof(__a->__a_value), __dst, __to_gcc_order(__order));104}105106template <typename _Tp>107_LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_load(const __cxx_atomic_base_impl<_Tp>* __a, memory_order __order) {108_Tp __ret;109__atomic_load(std::addressof(__a->__a_value), std::addressof(__ret), __to_gcc_order(__order));110return __ret;111}112113template <typename _Tp>114_LIBCPP_HIDE_FROM_ABI _Tp115__cxx_atomic_exchange(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) {116_Tp __ret;117__atomic_exchange(118std::addressof(__a->__a_value), std::addressof(__value), std::addressof(__ret), __to_gcc_order(__order));119return __ret;120}121122template <typename _Tp>123_LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp>* __a, _Tp __value, memory_order __order) {124_Tp __ret;125__atomic_exchange(126std::addressof(__a->__a_value), std::addressof(__value), std::addressof(__ret), __to_gcc_order(__order));127return __ret;128}129130template <typename _Tp>131_LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong(132volatile __cxx_atomic_base_impl<_Tp>* __a,133_Tp* __expected,134_Tp __value,135memory_order __success,136memory_order __failure) {137return __atomic_compare_exchange(138std::addressof(__a->__a_value),139__expected,140std::addressof(__value),141false,142__to_gcc_order(__success),143__to_gcc_failure_order(__failure));144}145146template <typename _Tp>147_LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_strong(148__cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) {149return __atomic_compare_exchange(150std::addressof(__a->__a_value),151__expected,152std::addressof(__value),153false,154__to_gcc_order(__success),155__to_gcc_failure_order(__failure));156}157158template <typename _Tp>159_LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak(160volatile __cxx_atomic_base_impl<_Tp>* __a,161_Tp* __expected,162_Tp __value,163memory_order __success,164memory_order __failure) {165return __atomic_compare_exchange(166std::addressof(__a->__a_value),167__expected,168std::addressof(__value),169true,170__to_gcc_order(__success),171__to_gcc_failure_order(__failure));172}173174template <typename _Tp>175_LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_compare_exchange_weak(176__cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) {177return __atomic_compare_exchange(178std::addressof(__a->__a_value),179__expected,180std::addressof(__value),181true,182__to_gcc_order(__success),183__to_gcc_failure_order(__failure));184}185186template <typename _Tp>187struct __skip_amt {188enum { value = 1 };189};190191template <typename _Tp>192struct __skip_amt<_Tp*> {193enum { value = sizeof(_Tp) };194};195196// FIXME: Haven't figured out what the spec says about using arrays with197// atomic_fetch_add. Force a failure rather than creating bad behavior.198template <typename _Tp>199struct __skip_amt<_Tp[]> {};200template <typename _Tp, int n>201struct __skip_amt<_Tp[n]> {};202203template <typename _Tp, typename _Td>204_LIBCPP_HIDE_FROM_ABI _Tp205__cxx_atomic_fetch_add(volatile __cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) {206return __atomic_fetch_add(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order));207}208209template <typename _Tp, typename _Td>210_LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) {211return __atomic_fetch_add(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order));212}213214template <typename _Tp, typename _Td>215_LIBCPP_HIDE_FROM_ABI _Tp216__cxx_atomic_fetch_sub(volatile __cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) {217return __atomic_fetch_sub(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order));218}219220template <typename _Tp, typename _Td>221_LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, memory_order __order) {222return __atomic_fetch_sub(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order));223}224225template <typename _Tp>226_LIBCPP_HIDE_FROM_ABI _Tp227__cxx_atomic_fetch_and(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) {228return __atomic_fetch_and(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order));229}230231template <typename _Tp>232_LIBCPP_HIDE_FROM_ABI _Tp233__cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) {234return __atomic_fetch_and(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order));235}236237template <typename _Tp>238_LIBCPP_HIDE_FROM_ABI _Tp239__cxx_atomic_fetch_or(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) {240return __atomic_fetch_or(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order));241}242243template <typename _Tp>244_LIBCPP_HIDE_FROM_ABI _Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) {245return __atomic_fetch_or(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order));246}247248template <typename _Tp>249_LIBCPP_HIDE_FROM_ABI _Tp250__cxx_atomic_fetch_xor(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) {251return __atomic_fetch_xor(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order));252}253254template <typename _Tp>255_LIBCPP_HIDE_FROM_ABI _Tp256__cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, memory_order __order) {257return __atomic_fetch_xor(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order));258}259260#define __cxx_atomic_is_lock_free(__s) __atomic_is_lock_free(__s, 0)261262_LIBCPP_END_NAMESPACE_STD263264#endif // _LIBCPP___ATOMIC_SUPPORT_GCC_H265266267