update boost

This commit is contained in:
2023-11-24 12:56:13 -06:00
parent cfc99971af
commit 19d727037a
9260 changed files with 849256 additions and 299957 deletions

View File

@@ -5,33 +5,182 @@
*
* Copyright (c) 2011 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
* Copyright (c) 2014, 2020 Andrey Semashev
*/
/*!
* \file atomic/atomic.hpp
*
* This header contains definition of \c atomic template and \c atomic_flag.
* This header contains definition of \c atomic template.
*/
#ifndef BOOST_ATOMIC_ATOMIC_HPP_INCLUDED_
#define BOOST_ATOMIC_ATOMIC_HPP_INCLUDED_
#include <cstddef>
#include <boost/cstdint.hpp>
#include <boost/static_assert.hpp>
#include <boost/memory_order.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/fences.hpp>
#include <boost/atomic/atomic_flag.hpp>
#include <boost/atomic/detail/atomic_template.hpp>
#include <boost/atomic/detail/operations.hpp>
#include <boost/atomic/detail/extra_operations.hpp>
#if !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
#include <boost/atomic/detail/fp_operations.hpp>
#include <boost/atomic/detail/extra_fp_operations.hpp>
#endif
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/classify.hpp>
#include <boost/atomic/detail/atomic_impl.hpp>
#include <boost/atomic/detail/type_traits/is_trivially_copyable.hpp>
#include <boost/atomic/detail/type_traits/is_nothrow_default_constructible.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
//! Atomic object
template< typename T >
class atomic :
public atomics::detail::base_atomic< T, typename atomics::detail::classify< T >::type, false >
{
private:
typedef atomics::detail::base_atomic< T, typename atomics::detail::classify< T >::type, false > base_type;
typedef typename base_type::value_arg_type value_arg_type;
public:
typedef typename base_type::value_type value_type;
BOOST_STATIC_ASSERT_MSG(sizeof(value_type) > 0u, "boost::atomic<T> requires T to be a complete type");
#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_IS_TRIVIALLY_COPYABLE)
BOOST_STATIC_ASSERT_MSG(atomics::detail::is_trivially_copyable< value_type >::value, "boost::atomic<T> requires T to be a trivially copyable type");
#endif
public:
BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT atomic() BOOST_NOEXCEPT_IF(atomics::detail::is_nothrow_default_constructible< value_type >::value) : base_type()
{
}
BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT atomic(value_arg_type v) BOOST_NOEXCEPT : base_type(v)
{
}
BOOST_FORCEINLINE value_type operator= (value_arg_type v) BOOST_NOEXCEPT
{
this->store(v);
return v;
}
BOOST_FORCEINLINE value_type operator= (value_arg_type v) volatile BOOST_NOEXCEPT
{
this->store(v);
return v;
}
BOOST_FORCEINLINE operator value_type() const volatile BOOST_NOEXCEPT
{
return this->load();
}
BOOST_DELETED_FUNCTION(atomic(atomic const&))
BOOST_DELETED_FUNCTION(atomic& operator= (atomic const&))
BOOST_DELETED_FUNCTION(atomic& operator= (atomic const&) volatile)
};
typedef atomic< char > atomic_char;
typedef atomic< unsigned char > atomic_uchar;
typedef atomic< signed char > atomic_schar;
typedef atomic< uint8_t > atomic_uint8_t;
typedef atomic< int8_t > atomic_int8_t;
typedef atomic< unsigned short > atomic_ushort;
typedef atomic< short > atomic_short;
typedef atomic< uint16_t > atomic_uint16_t;
typedef atomic< int16_t > atomic_int16_t;
typedef atomic< unsigned int > atomic_uint;
typedef atomic< int > atomic_int;
typedef atomic< uint32_t > atomic_uint32_t;
typedef atomic< int32_t > atomic_int32_t;
typedef atomic< unsigned long > atomic_ulong;
typedef atomic< long > atomic_long;
typedef atomic< uint64_t > atomic_uint64_t;
typedef atomic< int64_t > atomic_int64_t;
#ifdef BOOST_HAS_LONG_LONG
typedef atomic< boost::ulong_long_type > atomic_ullong;
typedef atomic< boost::long_long_type > atomic_llong;
#endif
typedef atomic< void* > atomic_address;
typedef atomic< bool > atomic_bool;
typedef atomic< wchar_t > atomic_wchar_t;
#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811
typedef atomic< char8_t > atomic_char8_t;
#endif
#if !defined(BOOST_NO_CXX11_CHAR16_T)
typedef atomic< char16_t > atomic_char16_t;
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T)
typedef atomic< char32_t > atomic_char32_t;
#endif
typedef atomic< int_least8_t > atomic_int_least8_t;
typedef atomic< uint_least8_t > atomic_uint_least8_t;
typedef atomic< int_least16_t > atomic_int_least16_t;
typedef atomic< uint_least16_t > atomic_uint_least16_t;
typedef atomic< int_least32_t > atomic_int_least32_t;
typedef atomic< uint_least32_t > atomic_uint_least32_t;
typedef atomic< int_least64_t > atomic_int_least64_t;
typedef atomic< uint_least64_t > atomic_uint_least64_t;
typedef atomic< int_fast8_t > atomic_int_fast8_t;
typedef atomic< uint_fast8_t > atomic_uint_fast8_t;
typedef atomic< int_fast16_t > atomic_int_fast16_t;
typedef atomic< uint_fast16_t > atomic_uint_fast16_t;
typedef atomic< int_fast32_t > atomic_int_fast32_t;
typedef atomic< uint_fast32_t > atomic_uint_fast32_t;
typedef atomic< int_fast64_t > atomic_int_fast64_t;
typedef atomic< uint_fast64_t > atomic_uint_fast64_t;
typedef atomic< intmax_t > atomic_intmax_t;
typedef atomic< uintmax_t > atomic_uintmax_t;
#if !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
typedef atomic< float > atomic_float_t;
typedef atomic< double > atomic_double_t;
typedef atomic< long double > atomic_long_double_t;
#endif
typedef atomic< std::size_t > atomic_size_t;
typedef atomic< std::ptrdiff_t > atomic_ptrdiff_t;
#if defined(BOOST_HAS_INTPTR_T)
typedef atomic< boost::intptr_t > atomic_intptr_t;
typedef atomic< boost::uintptr_t > atomic_uintptr_t;
#endif
// Select the lock-free atomic types that has natively supported waiting/notifying operations.
// Prefer 32-bit types the most as those have the best performance on current 32 and 64-bit architectures.
#if BOOST_ATOMIC_INT32_LOCK_FREE == 2 && BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY == 2
typedef atomic< uint32_t > atomic_unsigned_lock_free;
typedef atomic< int32_t > atomic_signed_lock_free;
#elif BOOST_ATOMIC_INT64_LOCK_FREE == 2 && BOOST_ATOMIC_HAS_NATIVE_INT64_WAIT_NOTIFY == 2
typedef atomic< uint64_t > atomic_unsigned_lock_free;
typedef atomic< int64_t > atomic_signed_lock_free;
#elif BOOST_ATOMIC_INT16_LOCK_FREE == 2 && BOOST_ATOMIC_HAS_NATIVE_INT16_WAIT_NOTIFY == 2
typedef atomic< uint16_t > atomic_unsigned_lock_free;
typedef atomic< int16_t > atomic_signed_lock_free;
#elif BOOST_ATOMIC_INT8_LOCK_FREE == 2 && BOOST_ATOMIC_HAS_NATIVE_INT8_WAIT_NOTIFY == 2
typedef atomic< uint8_t > atomic_unsigned_lock_free;
typedef atomic< int8_t > atomic_signed_lock_free;
#elif BOOST_ATOMIC_INT32_LOCK_FREE == 2
typedef atomic< uint32_t > atomic_unsigned_lock_free;
typedef atomic< int32_t > atomic_signed_lock_free;
#elif BOOST_ATOMIC_INT64_LOCK_FREE == 2
typedef atomic< uint64_t > atomic_unsigned_lock_free;
typedef atomic< int64_t > atomic_signed_lock_free;
#elif BOOST_ATOMIC_INT16_LOCK_FREE == 2
typedef atomic< uint16_t > atomic_unsigned_lock_free;
typedef atomic< int16_t > atomic_signed_lock_free;
#elif BOOST_ATOMIC_INT8_LOCK_FREE == 2
typedef atomic< uint8_t > atomic_unsigned_lock_free;
typedef atomic< int8_t > atomic_signed_lock_free;
#else
#define BOOST_ATOMIC_DETAIL_NO_LOCK_FREE_TYPEDEFS
#endif
} // namespace atomics
using atomics::atomic;
@@ -59,6 +208,9 @@ using atomics::atomic_llong;
using atomics::atomic_address;
using atomics::atomic_bool;
using atomics::atomic_wchar_t;
#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811
using atomics::atomic_char8_t;
#endif
#if !defined(BOOST_NO_CXX11_CHAR16_T)
using atomics::atomic_char16_t;
#endif
@@ -99,6 +251,14 @@ using atomics::atomic_intptr_t;
using atomics::atomic_uintptr_t;
#endif
#if !defined(BOOST_ATOMIC_DETAIL_NO_LOCK_FREE_TYPEDEFS)
using atomics::atomic_unsigned_lock_free;
using atomics::atomic_signed_lock_free;
#endif
#undef BOOST_ATOMIC_DETAIL_NO_LOCK_FREE_TYPEDEFS
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_ATOMIC_HPP_INCLUDED_

View File

@@ -5,7 +5,7 @@
*
* Copyright (c) 2011 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
* Copyright (c) 2014, 2020 Andrey Semashev
*/
/*!
* \file atomic/atomic_flag.hpp
@@ -17,17 +17,26 @@
#define BOOST_ATOMIC_ATOMIC_FLAG_HPP_INCLUDED_
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/operations.hpp>
#include <boost/atomic/detail/atomic_flag.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/atomic_flag_impl.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
//! Atomic flag
typedef atomics::detail::atomic_flag_impl< false > atomic_flag;
} // namespace atomics
using atomics::atomic_flag;
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_ATOMIC_FLAG_HPP_INCLUDED_

View File

@@ -0,0 +1,98 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020-2021 Andrey Semashev
*/
/*!
* \file atomic/atomic_ref.hpp
*
* This header contains definition of \c atomic_ref template.
*/
#ifndef BOOST_ATOMIC_ATOMIC_REF_HPP_INCLUDED_
#define BOOST_ATOMIC_ATOMIC_REF_HPP_INCLUDED_
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/memory_order.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/intptr.hpp>
#include <boost/atomic/detail/classify.hpp>
#include <boost/atomic/detail/atomic_ref_impl.hpp>
#include <boost/atomic/detail/type_traits/is_trivially_copyable.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
//! Atomic reference to external object
template< typename T >
class atomic_ref :
public atomics::detail::base_atomic_ref< T, typename atomics::detail::classify< T >::type, false >
{
private:
typedef atomics::detail::base_atomic_ref< T, typename atomics::detail::classify< T >::type, false > base_type;
typedef typename base_type::value_arg_type value_arg_type;
public:
typedef typename base_type::value_type value_type;
BOOST_STATIC_ASSERT_MSG(sizeof(value_type) > 0u, "boost::atomic_ref<T> requires T to be a complete type");
#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_IS_TRIVIALLY_COPYABLE)
BOOST_STATIC_ASSERT_MSG(atomics::detail::is_trivially_copyable< value_type >::value, "boost::atomic_ref<T> requires T to be a trivially copyable type");
#endif
private:
typedef typename base_type::storage_type storage_type;
public:
BOOST_DEFAULTED_FUNCTION(atomic_ref(atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {})
BOOST_FORCEINLINE explicit atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v)
{
// Check that referenced object alignment satisfies required alignment
BOOST_ASSERT((((atomics::detail::uintptr_t)this->m_value) & (base_type::required_alignment - 1u)) == 0u);
}
BOOST_FORCEINLINE value_type operator= (value_arg_type v) const BOOST_NOEXCEPT
{
this->store(v);
return v;
}
BOOST_FORCEINLINE operator value_type() const BOOST_NOEXCEPT
{
return this->load();
}
BOOST_DELETED_FUNCTION(atomic_ref& operator= (atomic_ref const&))
};
#if !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES)
template< typename T >
atomic_ref(T&) -> atomic_ref< T >;
#endif // !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES)
//! Atomic reference factory function
template< typename T >
BOOST_FORCEINLINE atomic_ref< T > make_atomic_ref(T& value) BOOST_NOEXCEPT
{
return atomic_ref< T >(value);
}
} // namespace atomics
using atomics::atomic_ref;
using atomics::make_atomic_ref;
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_ATOMIC_REF_HPP_INCLUDED_

View File

@@ -15,196 +15,7 @@
#define BOOST_ATOMIC_CAPABILITIES_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/platform.hpp>
#include <boost/atomic/detail/int_sizes.hpp>
#if !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
#include <boost/atomic/detail/float_sizes.hpp>
#endif
#if !defined(BOOST_ATOMIC_EMULATED)
#include BOOST_ATOMIC_DETAIL_BACKEND_HEADER(boost/atomic/detail/caps_)
#endif
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#ifndef BOOST_ATOMIC_INT8_LOCK_FREE
#define BOOST_ATOMIC_INT8_LOCK_FREE 0
#endif
#ifndef BOOST_ATOMIC_INT16_LOCK_FREE
#define BOOST_ATOMIC_INT16_LOCK_FREE 0
#endif
#ifndef BOOST_ATOMIC_INT32_LOCK_FREE
#define BOOST_ATOMIC_INT32_LOCK_FREE 0
#endif
#ifndef BOOST_ATOMIC_INT64_LOCK_FREE
#define BOOST_ATOMIC_INT64_LOCK_FREE 0
#endif
#ifndef BOOST_ATOMIC_INT128_LOCK_FREE
#define BOOST_ATOMIC_INT128_LOCK_FREE 0
#endif
#ifndef BOOST_ATOMIC_CHAR_LOCK_FREE
#define BOOST_ATOMIC_CHAR_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#endif
#ifndef BOOST_ATOMIC_CHAR16_T_LOCK_FREE
#define BOOST_ATOMIC_CHAR16_T_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#endif
#ifndef BOOST_ATOMIC_CHAR32_T_LOCK_FREE
#define BOOST_ATOMIC_CHAR32_T_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#endif
#ifndef BOOST_ATOMIC_WCHAR_T_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 1
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 2
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 4
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 8
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#else
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE 0
#endif
#endif
#ifndef BOOST_ATOMIC_SHORT_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 1
#define BOOST_ATOMIC_SHORT_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 2
#define BOOST_ATOMIC_SHORT_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 4
#define BOOST_ATOMIC_SHORT_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 8
#define BOOST_ATOMIC_SHORT_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#else
#define BOOST_ATOMIC_SHORT_LOCK_FREE 0
#endif
#endif
#ifndef BOOST_ATOMIC_INT_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_SIZEOF_INT == 1
#define BOOST_ATOMIC_INT_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 2
#define BOOST_ATOMIC_INT_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 4
#define BOOST_ATOMIC_INT_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 8
#define BOOST_ATOMIC_INT_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#else
#define BOOST_ATOMIC_INT_LOCK_FREE 0
#endif
#endif
#ifndef BOOST_ATOMIC_LONG_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 1
#define BOOST_ATOMIC_LONG_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 2
#define BOOST_ATOMIC_LONG_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 4
#define BOOST_ATOMIC_LONG_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 8
#define BOOST_ATOMIC_LONG_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#else
#define BOOST_ATOMIC_LONG_LOCK_FREE 0
#endif
#endif
#ifndef BOOST_ATOMIC_LLONG_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 1
#define BOOST_ATOMIC_LLONG_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 2
#define BOOST_ATOMIC_LLONG_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 4
#define BOOST_ATOMIC_LLONG_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 8
#define BOOST_ATOMIC_LLONG_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#else
#define BOOST_ATOMIC_LLONG_LOCK_FREE 0
#endif
#endif
#ifndef BOOST_ATOMIC_POINTER_LOCK_FREE
#if (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER + 0) == 8
#define BOOST_ATOMIC_POINTER_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#elif (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER + 0) == 4
#define BOOST_ATOMIC_POINTER_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#else
#define BOOST_ATOMIC_POINTER_LOCK_FREE 0
#endif
#endif
#define BOOST_ATOMIC_ADDRESS_LOCK_FREE BOOST_ATOMIC_POINTER_LOCK_FREE
#ifndef BOOST_ATOMIC_BOOL_LOCK_FREE
// We store bools in 1-byte storage in all backends
#define BOOST_ATOMIC_BOOL_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#endif
#ifndef BOOST_ATOMIC_FLAG_LOCK_FREE
#define BOOST_ATOMIC_FLAG_LOCK_FREE BOOST_ATOMIC_BOOL_LOCK_FREE
#endif
#if !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
#if !defined(BOOST_ATOMIC_FLOAT_LOCK_FREE) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT)
#if BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 2
#define BOOST_ATOMIC_FLOAT_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 4
#define BOOST_ATOMIC_FLOAT_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 8
#define BOOST_ATOMIC_FLOAT_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 16
#define BOOST_ATOMIC_FLOAT_LOCK_FREE BOOST_ATOMIC_INT128_LOCK_FREE
#else
#define BOOST_ATOMIC_FLOAT_LOCK_FREE 0
#endif
#endif
#if !defined(BOOST_ATOMIC_DOUBLE_LOCK_FREE) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE)
#if BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 2
#define BOOST_ATOMIC_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 4
#define BOOST_ATOMIC_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 8
#define BOOST_ATOMIC_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 16
#define BOOST_ATOMIC_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT128_LOCK_FREE
#else
#define BOOST_ATOMIC_DOUBLE_LOCK_FREE 0
#endif
#endif
#if !defined(BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE)
#if BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 2
#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 4
#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 8
#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 16
#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT128_LOCK_FREE
#else
#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE 0
#endif
#endif
#endif // !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
#ifndef BOOST_ATOMIC_THREAD_FENCE
#define BOOST_ATOMIC_THREAD_FENCE 0
#endif
#ifndef BOOST_ATOMIC_SIGNAL_FENCE
#define BOOST_ATOMIC_SIGNAL_FENCE 0
#endif
#include <boost/atomic/detail/capabilities.hpp>
#include <boost/atomic/detail/wait_capabilities.hpp>
#endif // BOOST_ATOMIC_CAPABILITIES_HPP_INCLUDED_

View File

@@ -16,6 +16,7 @@
#define BOOST_ATOMIC_DETAIL_ADDRESSOF_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -37,7 +38,11 @@ namespace atomics {
namespace detail {
template< typename T >
BOOST_FORCEINLINE T* addressof(T& value) BOOST_NOEXCEPT
BOOST_FORCEINLINE
#if defined(BOOST_ATOMIC_DETAIL_HAS_BUILTIN_ADDRESSOF)
BOOST_CONSTEXPR
#endif
T* addressof(T& value) BOOST_NOEXCEPT
{
#if defined(BOOST_ATOMIC_DETAIL_HAS_BUILTIN_ADDRESSOF)
return __builtin_addressof(value);
@@ -55,4 +60,6 @@ BOOST_FORCEINLINE T* addressof(T& value) BOOST_NOEXCEPT
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_ADDRESSOF_HPP_INCLUDED_

View File

@@ -0,0 +1,57 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/aligned_variable.hpp
*
* This header defines a convenience macro for declaring aligned variables
*/
#ifndef BOOST_ATOMIC_DETAIL_ALIGNED_VARIABLE_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_ALIGNED_VARIABLE_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#if defined(BOOST_ATOMIC_DETAIL_NO_CXX11_ALIGNAS)
#include <boost/config/helper_macros.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
#endif
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_ALIGNAS)
#define BOOST_ATOMIC_DETAIL_ALIGNED_VAR(var_alignment, var_type, var_name) \
alignas(var_alignment) var_type var_name
#define BOOST_ATOMIC_DETAIL_ALIGNED_VAR_TPL(var_alignment, var_type, var_name) \
alignas(var_alignment) var_type var_name
#else // !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_ALIGNAS)
// Note: Some compilers cannot use constant expressions in alignment attributes or alignas, so we have to use the union trick
#define BOOST_ATOMIC_DETAIL_ALIGNED_VAR(var_alignment, var_type, var_name) \
union \
{ \
var_type var_name; \
boost::type_with_alignment< var_alignment >::type BOOST_JOIN(var_name, _aligner); \
}
#define BOOST_ATOMIC_DETAIL_ALIGNED_VAR_TPL(var_alignment, var_type, var_name) \
union \
{ \
var_type var_name; \
typename boost::type_with_alignment< var_alignment >::type BOOST_JOIN(var_name, _aligner); \
}
#endif // !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_ALIGNAS)
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_ALIGNED_VARIABLE_HPP_INCLUDED_

View File

@@ -1,71 +0,0 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/atomic_flag.hpp
*
* This header contains interface definition of \c atomic_flag.
*/
#ifndef BOOST_ATOMIC_DETAIL_ATOMIC_FLAG_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_ATOMIC_FLAG_HPP_INCLUDED_
#include <boost/assert.hpp>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/operations_lockfree.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
/*
* IMPLEMENTATION NOTE: All interface functions MUST be declared with BOOST_FORCEINLINE,
* see comment for convert_memory_order_to_gcc in ops_gcc_atomic.hpp.
*/
namespace boost {
namespace atomics {
#if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
#define BOOST_ATOMIC_NO_ATOMIC_FLAG_INIT
#else
#define BOOST_ATOMIC_FLAG_INIT {}
#endif
struct atomic_flag
{
typedef atomics::detail::operations< 1u, false > operations;
typedef operations::storage_type storage_type;
operations::aligned_storage_type m_storage;
BOOST_FORCEINLINE BOOST_CONSTEXPR atomic_flag() BOOST_NOEXCEPT : m_storage(0)
{
}
BOOST_FORCEINLINE bool test_and_set(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return operations::test_and_set(m_storage.value, order);
}
BOOST_FORCEINLINE void clear(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(order != memory_order_consume);
BOOST_ASSERT(order != memory_order_acquire);
BOOST_ASSERT(order != memory_order_acq_rel);
operations::clear(m_storage.value, order);
}
BOOST_DELETED_FUNCTION(atomic_flag(atomic_flag const&))
BOOST_DELETED_FUNCTION(atomic_flag& operator= (atomic_flag const&))
};
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_ATOMIC_FLAG_HPP_INCLUDED_

View File

@@ -0,0 +1,129 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2011 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2014, 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/atomic_flag_impl.hpp
*
* This header contains implementation of \c atomic_flag.
*/
#ifndef BOOST_ATOMIC_DETAIL_ATOMIC_FLAG_IMPL_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_ATOMIC_FLAG_IMPL_HPP_INCLUDED_
#include <boost/assert.hpp>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/core_operations.hpp>
#include <boost/atomic/detail/wait_operations.hpp>
#include <boost/atomic/detail/aligned_variable.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
/*
* IMPLEMENTATION NOTE: All interface functions MUST be declared with BOOST_FORCEINLINE,
* see comment for convert_memory_order_to_gcc in gcc_atomic_memory_order_utils.hpp.
*/
namespace boost {
namespace atomics {
namespace detail {
#if defined(BOOST_ATOMIC_DETAIL_NO_CXX11_CONSTEXPR_UNION_INIT) || defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
#define BOOST_ATOMIC_NO_ATOMIC_FLAG_INIT
#else
#define BOOST_ATOMIC_FLAG_INIT {}
#endif
//! Atomic flag implementation
template< bool IsInterprocess >
struct atomic_flag_impl
{
// Prefer 4-byte storage as most platforms support waiting/notifying operations without a lock pool for 32-bit integers
typedef atomics::detail::core_operations< 4u, false, IsInterprocess > core_operations;
typedef atomics::detail::wait_operations< core_operations > wait_operations;
typedef typename core_operations::storage_type storage_type;
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = core_operations::is_always_lock_free;
static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = wait_operations::always_has_native_wait_notify;
BOOST_ATOMIC_DETAIL_ALIGNED_VAR_TPL(core_operations::storage_alignment, storage_type, m_storage);
BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT atomic_flag_impl() BOOST_NOEXCEPT : m_storage(0u)
{
}
BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT
{
return is_always_lock_free;
}
BOOST_FORCEINLINE bool has_native_wait_notify() const volatile BOOST_NOEXCEPT
{
return wait_operations::has_native_wait_notify(m_storage);
}
BOOST_FORCEINLINE bool test(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(order != memory_order_release);
BOOST_ASSERT(order != memory_order_acq_rel);
return !!core_operations::load(m_storage, order);
}
BOOST_FORCEINLINE bool test_and_set(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
return core_operations::test_and_set(m_storage, order);
}
BOOST_FORCEINLINE void clear(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(order != memory_order_consume);
BOOST_ASSERT(order != memory_order_acquire);
BOOST_ASSERT(order != memory_order_acq_rel);
core_operations::clear(m_storage, order);
}
BOOST_FORCEINLINE bool wait(bool old_val, memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
{
BOOST_ASSERT(order != memory_order_release);
BOOST_ASSERT(order != memory_order_acq_rel);
return !!wait_operations::wait(m_storage, static_cast< storage_type >(old_val), order);
}
BOOST_FORCEINLINE void notify_one() volatile BOOST_NOEXCEPT
{
wait_operations::notify_one(m_storage);
}
BOOST_FORCEINLINE void notify_all() volatile BOOST_NOEXCEPT
{
wait_operations::notify_all(m_storage);
}
BOOST_DELETED_FUNCTION(atomic_flag_impl(atomic_flag_impl const&))
BOOST_DELETED_FUNCTION(atomic_flag_impl& operator= (atomic_flag_impl const&))
};
#if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
template< bool IsInterprocess >
BOOST_CONSTEXPR_OR_CONST bool atomic_flag_impl< IsInterprocess >::is_always_lock_free;
template< bool IsInterprocess >
BOOST_CONSTEXPR_OR_CONST bool atomic_flag_impl< IsInterprocess >::always_has_native_wait_notify;
#endif
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_ATOMIC_FLAG_IMPL_HPP_INCLUDED_

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2012 Tim Blechmann
* Copyright (c) 2013 - 2018 Andrey Semashev
* Copyright (c) 2013-2018, 2020-2021 Andrey Semashev
*/
/*!
* \file atomic/detail/bitwise_cast.hpp
@@ -20,43 +20,127 @@
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/addressof.hpp>
#include <boost/atomic/detail/string_ops.hpp>
#include <boost/atomic/detail/type_traits/remove_cv.hpp>
#include <boost/atomic/detail/type_traits/integral_constant.hpp>
#include <boost/atomic/detail/type_traits/has_unique_object_representations.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if !defined(BOOST_ATOMIC_DETAIL_NO_HAS_UNIQUE_OBJECT_REPRESENTATIONS)
#if defined(__has_builtin)
#if __has_builtin(__builtin_bit_cast)
#define BOOST_ATOMIC_DETAIL_BIT_CAST(x, y) __builtin_bit_cast(x, y)
#endif
#endif
#if !defined(BOOST_ATOMIC_DETAIL_BIT_CAST) && defined(BOOST_MSVC) && BOOST_MSVC >= 1926
#define BOOST_ATOMIC_DETAIL_BIT_CAST(x, y) __builtin_bit_cast(x, y)
#endif
#endif // !defined(BOOST_ATOMIC_DETAIL_NO_HAS_UNIQUE_OBJECT_REPRESENTATIONS)
#if defined(BOOST_NO_CXX11_CONSTEXPR) || !defined(BOOST_ATOMIC_DETAIL_BIT_CAST) || !defined(BOOST_ATOMIC_DETAIL_HAS_BUILTIN_ADDRESSOF)
#define BOOST_ATOMIC_DETAIL_NO_CXX11_CONSTEXPR_BITWISE_CAST
#endif
#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_CONSTEXPR_BITWISE_CAST)
#define BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST BOOST_CONSTEXPR
#else
#define BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST
#endif
#if defined(BOOST_GCC) && BOOST_GCC >= 80000
#pragma GCC diagnostic push
// copying an object of non-trivial type X from an array of Y. This is benign because we use memcpy to copy trivially copyable objects.
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#endif
namespace boost {
namespace atomics {
namespace detail {
template< std::size_t FromSize, typename To >
BOOST_FORCEINLINE void clear_padding(To& to, atomics::detail::true_type) BOOST_NOEXCEPT
template< std::size_t ValueSize, typename To >
BOOST_FORCEINLINE void clear_tail_padding_bits(To& to, atomics::detail::true_type) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_MEMSET(reinterpret_cast< unsigned char* >(atomics::detail::addressof(to)) + FromSize, 0, sizeof(To) - FromSize);
BOOST_ATOMIC_DETAIL_MEMSET(reinterpret_cast< unsigned char* >(atomics::detail::addressof(to)) + ValueSize, 0, sizeof(To) - ValueSize);
}
template< std::size_t FromSize, typename To >
BOOST_FORCEINLINE void clear_padding(To&, atomics::detail::false_type) BOOST_NOEXCEPT
template< std::size_t ValueSize, typename To >
BOOST_FORCEINLINE void clear_tail_padding_bits(To&, atomics::detail::false_type) BOOST_NOEXCEPT
{
}
template< typename To, std::size_t FromSize, typename From >
BOOST_FORCEINLINE To bitwise_cast(From const& from) BOOST_NOEXCEPT
template< std::size_t ValueSize, typename To >
BOOST_FORCEINLINE void clear_tail_padding_bits(To& to) BOOST_NOEXCEPT
{
To to;
atomics::detail::clear_tail_padding_bits< ValueSize >(to, atomics::detail::integral_constant< bool, ValueSize < sizeof(To) >());
}
template< typename To, std::size_t FromValueSize, typename From >
BOOST_FORCEINLINE To bitwise_cast_memcpy(From const& from) BOOST_NOEXCEPT
{
typedef typename atomics::detail::remove_cv< To >::type unqualified_to_t;
unqualified_to_t to;
#if !defined(BOOST_ATOMIC_NO_CLEAR_PADDING)
From from2(from);
BOOST_ATOMIC_DETAIL_CLEAR_PADDING(atomics::detail::addressof(from2));
BOOST_ATOMIC_DETAIL_MEMCPY
(
atomics::detail::addressof(to),
atomics::detail::addressof(from2),
(FromValueSize < sizeof(unqualified_to_t) ? FromValueSize : sizeof(unqualified_to_t))
);
#else
BOOST_ATOMIC_DETAIL_MEMCPY
(
atomics::detail::addressof(to),
atomics::detail::addressof(from),
(FromSize < sizeof(To) ? FromSize : sizeof(To))
(FromValueSize < sizeof(unqualified_to_t) ? FromValueSize : sizeof(unqualified_to_t))
);
atomics::detail::clear_padding< FromSize >(to, atomics::detail::integral_constant< bool, FromSize < sizeof(To) >());
#endif
atomics::detail::clear_tail_padding_bits< FromValueSize >(to);
return to;
}
template< typename To, typename From >
#if defined(BOOST_ATOMIC_DETAIL_BIT_CAST)
template< typename To, std::size_t FromValueSize, typename From >
BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST To bitwise_cast_impl(From const& from, atomics::detail::true_type) BOOST_NOEXCEPT
{
// This implementation is only called when the From type has no padding and From and To have the same size
return BOOST_ATOMIC_DETAIL_BIT_CAST(typename atomics::detail::remove_cv< To >::type, from);
}
template< typename To, std::size_t FromValueSize, typename From >
BOOST_FORCEINLINE To bitwise_cast_impl(From const& from, atomics::detail::false_type) BOOST_NOEXCEPT
{
return atomics::detail::bitwise_cast_memcpy< To, FromValueSize >(from);
}
template< typename To, std::size_t FromValueSize, typename From >
BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST To bitwise_cast(From const& from) BOOST_NOEXCEPT
{
return atomics::detail::bitwise_cast_impl< To, FromValueSize >(from, atomics::detail::integral_constant< bool,
FromValueSize == sizeof(To) && atomics::detail::has_unique_object_representations< From >::value >());
}
#else // defined(BOOST_ATOMIC_DETAIL_BIT_CAST)
template< typename To, std::size_t FromValueSize, typename From >
BOOST_FORCEINLINE To bitwise_cast(From const& from) BOOST_NOEXCEPT
{
return atomics::detail::bitwise_cast_memcpy< To, FromValueSize >(from);
}
#endif // defined(BOOST_ATOMIC_DETAIL_BIT_CAST)
//! Converts the source object to the target type, possibly by padding or truncating it on the right, and clearing any padding bits (if supported by compiler). Preserves value bits unchanged.
template< typename To, typename From >
BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST To bitwise_cast(From const& from) BOOST_NOEXCEPT
{
return atomics::detail::bitwise_cast< To, sizeof(From) >(from);
}
@@ -65,4 +149,10 @@ BOOST_FORCEINLINE To bitwise_cast(From const& from) BOOST_NOEXCEPT
} // namespace atomics
} // namespace boost
#if defined(BOOST_GCC) && BOOST_GCC >= 80000
#pragma GCC diagnostic pop
#endif
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_BITWISE_CAST_HPP_INCLUDED_

View File

@@ -3,7 +3,7 @@
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2018 Andrey Semashev
* Copyright (c) 2018, 2021 Andrey Semashev
*/
/*!
* \file atomic/detail/bitwise_fp_cast.hpp
@@ -18,6 +18,10 @@
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/float_sizes.hpp>
#include <boost/atomic/detail/bitwise_cast.hpp>
#if defined(BOOST_ATOMIC_DETAIL_BIT_CAST)
#include <boost/atomic/detail/type_traits/integral_constant.hpp>
#endif
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -31,17 +35,17 @@ namespace detail {
* \brief The type trait returns the size of the value of the specified floating point type
*
* This size may be less than <tt>sizeof(T)</tt> if the implementation uses padding bytes for a particular FP type. This is
* often the case with 80-bit extended double, which is stored in 12 or 16 bytes with padding filled with garbage.
* often the case with 80-bit extended double, which is stored in 12 or 16 initial bytes with tail padding filled with garbage.
*/
template< typename T >
struct value_sizeof
struct value_size_of
{
static BOOST_CONSTEXPR_OR_CONST std::size_t value = sizeof(T);
};
#if defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE)
template< >
struct value_sizeof< float >
struct value_size_of< float >
{
static BOOST_CONSTEXPR_OR_CONST std::size_t value = BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE;
};
@@ -49,7 +53,7 @@ struct value_sizeof< float >
#if defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE)
template< >
struct value_sizeof< double >
struct value_size_of< double >
{
static BOOST_CONSTEXPR_OR_CONST std::size_t value = BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE;
};
@@ -57,30 +61,58 @@ struct value_sizeof< double >
#if defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE)
template< >
struct value_sizeof< long double >
struct value_size_of< long double >
{
static BOOST_CONSTEXPR_OR_CONST std::size_t value = BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE;
};
#endif
template< typename T >
struct value_sizeof< const T > : value_sizeof< T > {};
struct value_size_of< const T > : value_size_of< T > {};
template< typename T >
struct value_sizeof< volatile T > : value_sizeof< T > {};
struct value_size_of< volatile T > : value_size_of< T > {};
template< typename T >
struct value_sizeof< const volatile T > : value_sizeof< T > {};
struct value_size_of< const volatile T > : value_size_of< T > {};
#if !defined(BOOST_ATOMIC_NO_CLEAR_PADDING)
// BOOST_ATOMIC_DETAIL_CLEAR_PADDING, which is used in bitwise_cast, will clear the tail padding bits in the source object.
// We don't need to specify the actual value size to avoid redundant zeroing of the tail padding.
#define BOOST_ATOMIC_DETAIL_BITWISE_FP_CAST_VALUE_SIZE_OF(x) sizeof(x)
#else
#define BOOST_ATOMIC_DETAIL_BITWISE_FP_CAST_VALUE_SIZE_OF(x) atomics::detail::value_size_of< x >::value
#endif
#if defined(BOOST_ATOMIC_DETAIL_BIT_CAST)
//! Similar to bitwise_cast, but either \c From or \c To is expected to be a floating point type. Attempts to detect the actual value size in the source object and considers the rest of the object as padding.
template< typename To, typename From >
BOOST_FORCEINLINE To bitwise_fp_cast(From const& from) BOOST_NOEXCEPT
BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST To bitwise_fp_cast(From const& from) BOOST_NOEXCEPT
{
return atomics::detail::bitwise_cast< To, atomics::detail::value_sizeof< From >::value >(from);
// For floating point types, has_unique_object_representations is typically false even if the type contains no padding bits.
// Here, we rely on our detection of the actual value size to select constexpr bit_cast implementation when possible. We assume
// here that floating point value bits are contiguous.
return atomics::detail::bitwise_cast_impl< To, BOOST_ATOMIC_DETAIL_BITWISE_FP_CAST_VALUE_SIZE_OF(From) >(from, atomics::detail::integral_constant< bool,
atomics::detail::value_size_of< From >::value == sizeof(From) && atomics::detail::value_size_of< From >::value == sizeof(To) >());
}
#else // defined(BOOST_ATOMIC_DETAIL_BIT_CAST)
//! Similar to bitwise_cast, but either \c From or \c To is expected to be a floating point type. Attempts to detect the actual value size in the source object and considers the rest of the object as padding.
template< typename To, typename From >
BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST To bitwise_fp_cast(From const& from) BOOST_NOEXCEPT
{
return atomics::detail::bitwise_cast< To, BOOST_ATOMIC_DETAIL_BITWISE_FP_CAST_VALUE_SIZE_OF(From) >(from);
}
#endif // defined(BOOST_ATOMIC_DETAIL_BIT_CAST)
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_BITWISE_FP_CAST_HPP_INCLUDED_

View File

@@ -0,0 +1,217 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/capabilities.hpp
*
* This header defines core feature capabilities macros.
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPABILITIES_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPABILITIES_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/platform.hpp>
#include <boost/atomic/detail/int_sizes.hpp>
#if !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
#include <boost/atomic/detail/float_sizes.hpp>
#endif
#if defined(BOOST_ATOMIC_DETAIL_CORE_BACKEND_HEADER)
#include BOOST_ATOMIC_DETAIL_CORE_BACKEND_HEADER(boost/atomic/detail/caps_)
#elif defined(BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND_HEADER)
#include BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND_HEADER(boost/atomic/detail/caps_arch_)
#endif
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#ifndef BOOST_ATOMIC_INT8_LOCK_FREE
#define BOOST_ATOMIC_INT8_LOCK_FREE 0
#endif
#ifndef BOOST_ATOMIC_INT16_LOCK_FREE
#define BOOST_ATOMIC_INT16_LOCK_FREE 0
#endif
#ifndef BOOST_ATOMIC_INT32_LOCK_FREE
#define BOOST_ATOMIC_INT32_LOCK_FREE 0
#endif
#ifndef BOOST_ATOMIC_INT64_LOCK_FREE
#define BOOST_ATOMIC_INT64_LOCK_FREE 0
#endif
#ifndef BOOST_ATOMIC_INT128_LOCK_FREE
#define BOOST_ATOMIC_INT128_LOCK_FREE 0
#endif
#ifndef BOOST_ATOMIC_CHAR_LOCK_FREE
#define BOOST_ATOMIC_CHAR_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#endif
#ifndef BOOST_ATOMIC_CHAR8_T_LOCK_FREE
#define BOOST_ATOMIC_CHAR8_T_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#endif
#ifndef BOOST_ATOMIC_CHAR16_T_LOCK_FREE
#define BOOST_ATOMIC_CHAR16_T_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#endif
#ifndef BOOST_ATOMIC_CHAR32_T_LOCK_FREE
#define BOOST_ATOMIC_CHAR32_T_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#endif
#ifndef BOOST_ATOMIC_WCHAR_T_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 1
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 2
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 4
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 8
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#else
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE 0
#endif
#endif
#ifndef BOOST_ATOMIC_SHORT_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 1
#define BOOST_ATOMIC_SHORT_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 2
#define BOOST_ATOMIC_SHORT_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 4
#define BOOST_ATOMIC_SHORT_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 8
#define BOOST_ATOMIC_SHORT_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#else
#define BOOST_ATOMIC_SHORT_LOCK_FREE 0
#endif
#endif
#ifndef BOOST_ATOMIC_INT_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_SIZEOF_INT == 1
#define BOOST_ATOMIC_INT_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 2
#define BOOST_ATOMIC_INT_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 4
#define BOOST_ATOMIC_INT_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 8
#define BOOST_ATOMIC_INT_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#else
#define BOOST_ATOMIC_INT_LOCK_FREE 0
#endif
#endif
#ifndef BOOST_ATOMIC_LONG_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 1
#define BOOST_ATOMIC_LONG_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 2
#define BOOST_ATOMIC_LONG_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 4
#define BOOST_ATOMIC_LONG_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 8
#define BOOST_ATOMIC_LONG_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#else
#define BOOST_ATOMIC_LONG_LOCK_FREE 0
#endif
#endif
#ifndef BOOST_ATOMIC_LLONG_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 1
#define BOOST_ATOMIC_LLONG_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 2
#define BOOST_ATOMIC_LLONG_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 4
#define BOOST_ATOMIC_LLONG_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 8
#define BOOST_ATOMIC_LLONG_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#else
#define BOOST_ATOMIC_LLONG_LOCK_FREE 0
#endif
#endif
#ifndef BOOST_ATOMIC_POINTER_LOCK_FREE
#if (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER + 0) == 8
#define BOOST_ATOMIC_POINTER_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#elif (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER + 0) == 4
#define BOOST_ATOMIC_POINTER_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#else
#define BOOST_ATOMIC_POINTER_LOCK_FREE 0
#endif
#endif
#define BOOST_ATOMIC_ADDRESS_LOCK_FREE BOOST_ATOMIC_POINTER_LOCK_FREE
#ifndef BOOST_ATOMIC_BOOL_LOCK_FREE
// We store bools in 1-byte storage in all backends
#define BOOST_ATOMIC_BOOL_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#endif
#ifndef BOOST_ATOMIC_FLAG_LOCK_FREE
// atomic_flag uses 4-byte storage
#define BOOST_ATOMIC_FLAG_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#endif
#if !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
#if !defined(BOOST_ATOMIC_FLOAT_LOCK_FREE) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT)
#if BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 2
#define BOOST_ATOMIC_FLOAT_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 4
#define BOOST_ATOMIC_FLOAT_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 8
#define BOOST_ATOMIC_FLOAT_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT > 8 && BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT <= 16
#define BOOST_ATOMIC_FLOAT_LOCK_FREE BOOST_ATOMIC_INT128_LOCK_FREE
#else
#define BOOST_ATOMIC_FLOAT_LOCK_FREE 0
#endif
#endif
#if !defined(BOOST_ATOMIC_DOUBLE_LOCK_FREE) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE)
#if BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 2
#define BOOST_ATOMIC_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 4
#define BOOST_ATOMIC_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 8
#define BOOST_ATOMIC_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE > 8 && BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE <= 16
#define BOOST_ATOMIC_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT128_LOCK_FREE
#else
#define BOOST_ATOMIC_DOUBLE_LOCK_FREE 0
#endif
#endif
#if !defined(BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE)
#if BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 2
#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 4
#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 8
#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE > 8 && BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE <= 16
#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT128_LOCK_FREE
#else
#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE 0
#endif
#endif
#endif // !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
#ifndef BOOST_ATOMIC_THREAD_FENCE
#define BOOST_ATOMIC_THREAD_FENCE 0
#endif
#ifndef BOOST_ATOMIC_SIGNAL_FENCE
#define BOOST_ATOMIC_SIGNAL_FENCE 0
#endif
#endif // BOOST_ATOMIC_DETAIL_CAPABILITIES_HPP_INCLUDED_

View File

@@ -0,0 +1,53 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020, 2022 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_arch_gcc_aarch32.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_AARCH32_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_AARCH32_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(__ARMEL__) || \
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
(defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \
defined(BOOST_WINDOWS)
#define BOOST_ATOMIC_DETAIL_AARCH32_LITTLE_ENDIAN
#elif defined(__ARMEB__) || \
defined(__ARM_BIG_ENDIAN) || \
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \
(defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__))
#define BOOST_ATOMIC_DETAIL_AARCH32_BIG_ENDIAN
#else
#include <boost/predef/other/endian.h>
#if BOOST_ENDIAN_LITTLE_BYTE
#define BOOST_ATOMIC_DETAIL_AARCH32_LITTLE_ENDIAN
#elif BOOST_ENDIAN_BIG_BYTE
#define BOOST_ATOMIC_DETAIL_AARCH32_BIG_ENDIAN
#else
#error "Boost.Atomic: Failed to determine AArch32 endianness, the target platform is not supported. Please, report to the developers (patches are welcome)."
#endif
#endif
#define BOOST_ATOMIC_INT8_LOCK_FREE 2
#define BOOST_ATOMIC_INT16_LOCK_FREE 2
#define BOOST_ATOMIC_INT32_LOCK_FREE 2
#define BOOST_ATOMIC_INT64_LOCK_FREE 2
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_AARCH32_HPP_INCLUDED_

View File

@@ -0,0 +1,65 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020, 2022 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_arch_gcc_aarch64.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_AARCH64_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_AARCH64_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(__AARCH64EL__) || \
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
(defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \
defined(BOOST_WINDOWS)
#define BOOST_ATOMIC_DETAIL_AARCH64_LITTLE_ENDIAN
#elif defined(__AARCH64EB__) || \
defined(__ARM_BIG_ENDIAN) || \
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \
(defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__))
#define BOOST_ATOMIC_DETAIL_AARCH64_BIG_ENDIAN
#else
#include <boost/predef/other/endian.h>
#if BOOST_ENDIAN_LITTLE_BYTE
#define BOOST_ATOMIC_DETAIL_AARCH64_LITTLE_ENDIAN
#elif BOOST_ENDIAN_BIG_BYTE
#define BOOST_ATOMIC_DETAIL_AARCH64_BIG_ENDIAN
#else
#error "Boost.Atomic: Failed to determine AArch64 endianness, the target platform is not supported. Please, report to the developers (patches are welcome)."
#endif
#endif
#if defined(__ARM_FEATURE_ATOMICS)
// ARMv8.1 added Large System Extensions, which includes cas, swp, and a number of other read-modify-write instructions
#define BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE
#endif
#if defined(__ARM_FEATURE_COMPLEX)
// ARMv8.3 added Release Consistency processor consistent (RCpc) memory model, which includes ldapr and similar instructions.
// Unfortunately, there seems to be no dedicated __ARM_FEATURE macro for this, so we use __ARM_FEATURE_COMPLEX, which is also defined starting ARMv8.3.
#define BOOST_ATOMIC_DETAIL_AARCH64_HAS_RCPC
#endif
#define BOOST_ATOMIC_INT8_LOCK_FREE 2
#define BOOST_ATOMIC_INT16_LOCK_FREE 2
#define BOOST_ATOMIC_INT32_LOCK_FREE 2
#define BOOST_ATOMIC_INT64_LOCK_FREE 2
#define BOOST_ATOMIC_INT128_LOCK_FREE 2
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_AARCH64_HPP_INCLUDED_

View File

@@ -8,13 +8,13 @@
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_gcc_alpha.hpp
* \file atomic/detail/caps_arch_gcc_alpha.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_GCC_ALPHA_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_GCC_ALPHA_HPP_INCLUDED_
#ifndef BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_ALPHA_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_ALPHA_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
@@ -31,4 +31,4 @@
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_GCC_ALPHA_HPP_INCLUDED_
#endif // BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_ALPHA_HPP_INCLUDED_

View File

@@ -3,16 +3,20 @@
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2017 Andrey Semashev
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2009 Phil Endecott
* Copyright (c) 2013 Tim Blechmann
* ARM Code by Phil Endecott, based on other architectures.
* Copyright (c) 2014, 2020, 2022 Andrey Semashev
*/
/*!
* \file atomic/detail/hwcaps_gcc_arm.hpp
* \file atomic/detail/caps_arch_gcc_arm.hpp
*
* This header defines hardware capabilities macros for ARM
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_HWCAPS_GCC_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_HWCAPS_GCC_ARM_HPP_INCLUDED_
#ifndef BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_ARM_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/platform.hpp>
@@ -21,7 +25,28 @@
#pragma once
#endif
#if defined(__GNUC__) && defined(__arm__) && (BOOST_ATOMIC_DETAIL_ARM_ARCH+0) >= 6
#if defined(__ARMEL__) || \
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
(defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \
defined(BOOST_WINDOWS)
#define BOOST_ATOMIC_DETAIL_ARM_LITTLE_ENDIAN
#elif defined(__ARMEB__) || \
defined(__ARM_BIG_ENDIAN) || \
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \
(defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__))
#define BOOST_ATOMIC_DETAIL_ARM_BIG_ENDIAN
#else
#include <boost/predef/other/endian.h>
#if BOOST_ENDIAN_LITTLE_BYTE
#define BOOST_ATOMIC_DETAIL_ARM_LITTLE_ENDIAN
#elif BOOST_ENDIAN_BIG_BYTE
#define BOOST_ATOMIC_DETAIL_ARM_BIG_ENDIAN
#else
#error "Boost.Atomic: Failed to determine ARM endianness, the target platform is not supported. Please, report to the developers (patches are welcome)."
#endif
#endif
#if defined(__GNUC__) && defined(__arm__) && (BOOST_ATOMIC_DETAIL_ARM_ARCH >= 6)
#if BOOST_ATOMIC_DETAIL_ARM_ARCH > 6
// ARMv7 and later have dmb instruction
@@ -62,6 +87,17 @@
#endif // defined(__ARM_FEATURE_LDREX)
#endif // defined(__GNUC__) && defined(__arm__) && (BOOST_ATOMIC_DETAIL_ARM_ARCH+0) >= 6
#endif // defined(__GNUC__) && defined(__arm__) && (BOOST_ATOMIC_DETAIL_ARM_ARCH >= 6)
#endif // BOOST_ATOMIC_DETAIL_HWCAPS_GCC_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_INT8_LOCK_FREE 2
#define BOOST_ATOMIC_INT16_LOCK_FREE 2
#define BOOST_ATOMIC_INT32_LOCK_FREE 2
#if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD)
#define BOOST_ATOMIC_INT64_LOCK_FREE 2
#endif
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_ARM_HPP_INCLUDED_

View File

@@ -3,16 +3,18 @@
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2017 Andrey Semashev
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/hwcaps_gcc_ppc.hpp
* \file atomic/detail/caps_arch_gcc_ppc.hpp
*
* This header defines hardware capabilities macros for PowerPC
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_HWCAPS_GCC_PPC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_HWCAPS_GCC_PPC_HPP_INCLUDED_
#ifndef BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_PPC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_PPC_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
@@ -39,4 +41,15 @@
#endif // defined(__POWERPC__) || defined(__PPC__)
#endif // BOOST_ATOMIC_DETAIL_HWCAPS_GCC_PPC_HPP_INCLUDED_
#define BOOST_ATOMIC_INT8_LOCK_FREE 2
#define BOOST_ATOMIC_INT16_LOCK_FREE 2
#define BOOST_ATOMIC_INT32_LOCK_FREE 2
#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX)
#define BOOST_ATOMIC_INT64_LOCK_FREE 2
#endif
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_PPC_HPP_INCLUDED_

View File

@@ -8,13 +8,13 @@
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_gcc_sparc.hpp
* \file atomic/detail/caps_arch_gcc_sparc.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_GCC_SPARC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_GCC_SPARC_HPP_INCLUDED_
#ifndef BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_SPARC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_SPARC_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
@@ -31,4 +31,4 @@
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_GCC_SPARC_HPP_INCLUDED_
#endif // BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_SPARC_HPP_INCLUDED_

View File

@@ -3,16 +3,18 @@
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2017 Andrey Semashev
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2012 Tim Blechmann
* Copyright (c) 2013 - 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/hwcaps_gcc_x86.hpp
* \file atomic/detail/caps_arch_gcc_x86.hpp
*
* This header defines hardware capabilities macros for x86
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_HWCAPS_GCC_X86_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_HWCAPS_GCC_X86_HPP_INCLUDED_
#ifndef BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_X86_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_X86_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
@@ -55,4 +57,18 @@
#endif // defined(__GNUC__)
#endif // BOOST_ATOMIC_DETAIL_HWCAPS_GCC_X86_HPP_INCLUDED_
#define BOOST_ATOMIC_INT8_LOCK_FREE 2
#define BOOST_ATOMIC_INT16_LOCK_FREE 2
#define BOOST_ATOMIC_INT32_LOCK_FREE 2
#if defined(__x86_64__) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B)
#define BOOST_ATOMIC_INT64_LOCK_FREE 2
#endif
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
#define BOOST_ATOMIC_INT128_LOCK_FREE 2
#endif
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_X86_HPP_INCLUDED_

View File

@@ -8,13 +8,13 @@
* Copyright (c) 2012 - 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_msvc_arm.hpp
* \file atomic/detail/caps_arch_msvc_arm.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_MSVC_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_MSVC_ARM_HPP_INCLUDED_
#ifndef BOOST_ATOMIC_DETAIL_CAPS_ARCH_MSVC_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_ARCH_MSVC_ARM_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
@@ -31,4 +31,4 @@
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_MSVC_ARM_HPP_INCLUDED_
#endif // BOOST_ATOMIC_DETAIL_CAPS_ARCH_MSVC_ARM_HPP_INCLUDED_

View File

@@ -8,13 +8,13 @@
* Copyright (c) 2012 - 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_msvc_x86.hpp
* \file atomic/detail/caps_arch_msvc_x86.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_MSVC_X86_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_MSVC_X86_HPP_INCLUDED_
#ifndef BOOST_ATOMIC_DETAIL_CAPS_ARCH_MSVC_X86_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_ARCH_MSVC_X86_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
@@ -26,9 +26,15 @@
#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B 1
#endif
#if _MSC_VER >= 1500 && defined(_M_AMD64) && !defined(BOOST_ATOMIC_NO_CMPXCHG16B)
#if defined(_M_AMD64) && !defined(BOOST_ATOMIC_NO_CMPXCHG16B)
#if defined(__clang__)
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)
#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B 1
#endif
#elif _MSC_VER >= 1500
#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B 1
#endif
#endif
#if defined(_MSC_VER) && (defined(_M_AMD64) || (defined(_M_IX86) && defined(_M_IX86_FP) && _M_IX86_FP >= 2))
// Use mfence only if SSE2 is available
@@ -43,7 +49,7 @@
#define BOOST_ATOMIC_INT64_LOCK_FREE 2
#endif
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) && (defined(BOOST_HAS_INT128) || !defined(BOOST_NO_ALIGNMENT))
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
#define BOOST_ATOMIC_INT128_LOCK_FREE 2
#endif
@@ -52,4 +58,4 @@
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_MSVC_X86_HPP_INCLUDED_
#endif // BOOST_ATOMIC_DETAIL_CAPS_ARCH_MSVC_X86_HPP_INCLUDED_

View File

@@ -1,39 +0,0 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2009 Phil Endecott
* Copyright (c) 2013 Tim Blechmann
* ARM Code by Phil Endecott, based on other architectures.
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_gcc_arm.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_GCC_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_GCC_ARM_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/hwcaps_gcc_arm.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#define BOOST_ATOMIC_INT8_LOCK_FREE 2
#define BOOST_ATOMIC_INT16_LOCK_FREE 2
#define BOOST_ATOMIC_INT32_LOCK_FREE 2
#if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD)
#define BOOST_ATOMIC_INT64_LOCK_FREE 2
#endif
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_GCC_ARM_HPP_INCLUDED_

View File

@@ -3,7 +3,7 @@
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
* Copyright (c) 2014, 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_gcc_atomic.hpp
@@ -16,118 +16,143 @@
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/int_sizes.hpp>
#if defined(__i386__) || defined(__x86_64__)
#include <boost/atomic/detail/hwcaps_gcc_x86.hpp>
#elif defined(__arm__)
#include <boost/atomic/detail/hwcaps_gcc_arm.hpp>
#elif defined(__POWERPC__) || defined(__PPC__)
#include <boost/atomic/detail/hwcaps_gcc_ppc.hpp>
#if defined(BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND_HEADER)
#include BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND_HEADER(boost/atomic/detail/caps_arch_)
#endif
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) && (defined(BOOST_HAS_INT128) || !defined(BOOST_NO_ALIGNMENT))
#define BOOST_ATOMIC_INT128_LOCK_FREE 2
#else
#define BOOST_ATOMIC_INT128_LOCK_FREE 0
#endif
#if (__GCC_ATOMIC_LLONG_LOCK_FREE == 2) || (defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) && BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 8)
#define BOOST_ATOMIC_LLONG_LOCK_FREE 2
#else
#define BOOST_ATOMIC_LLONG_LOCK_FREE BOOST_ATOMIC_INT128_LOCK_FREE
#endif
#if (__GCC_ATOMIC_LONG_LOCK_FREE == 2) || (defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) && BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 8)
#define BOOST_ATOMIC_LONG_LOCK_FREE 2
#else
#define BOOST_ATOMIC_LONG_LOCK_FREE BOOST_ATOMIC_LLONG_LOCK_FREE
#endif
#if __GCC_ATOMIC_INT_LOCK_FREE == 2
#define BOOST_ATOMIC_INT_LOCK_FREE 2
#else
#define BOOST_ATOMIC_INT_LOCK_FREE BOOST_ATOMIC_LONG_LOCK_FREE
#endif
#if __GCC_ATOMIC_SHORT_LOCK_FREE == 2
#define BOOST_ATOMIC_SHORT_LOCK_FREE 2
#else
#define BOOST_ATOMIC_SHORT_LOCK_FREE BOOST_ATOMIC_INT_LOCK_FREE
#endif
#if __GCC_ATOMIC_CHAR_LOCK_FREE == 2
#define BOOST_ATOMIC_CHAR_LOCK_FREE 2
#else
#define BOOST_ATOMIC_CHAR_LOCK_FREE BOOST_ATOMIC_SHORT_LOCK_FREE
#endif
#if __GCC_ATOMIC_POINTER_LOCK_FREE == 2
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#else
#define BOOST_ATOMIC_POINTER_LOCK_FREE 0
#endif
#define BOOST_ATOMIC_INT8_LOCK_FREE BOOST_ATOMIC_CHAR_LOCK_FREE
// Translate type-based lock-free macros to size-based ones
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT8_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 2
#define BOOST_ATOMIC_INT16_LOCK_FREE BOOST_ATOMIC_SHORT_LOCK_FREE
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 2
#define BOOST_ATOMIC_INT16_LOCK_FREE BOOST_ATOMIC_INT_LOCK_FREE
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 2
#define BOOST_ATOMIC_INT16_LOCK_FREE BOOST_ATOMIC_LONG_LOCK_FREE
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 2
#define BOOST_ATOMIC_INT16_LOCK_FREE BOOST_ATOMIC_LLONG_LOCK_FREE
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE
#else
#define BOOST_ATOMIC_INT16_LOCK_FREE 0
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE 0
#endif
#if BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 4
#define BOOST_ATOMIC_INT32_LOCK_FREE BOOST_ATOMIC_SHORT_LOCK_FREE
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 4
#define BOOST_ATOMIC_INT32_LOCK_FREE BOOST_ATOMIC_INT_LOCK_FREE
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 4
#define BOOST_ATOMIC_INT32_LOCK_FREE BOOST_ATOMIC_LONG_LOCK_FREE
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 4
#define BOOST_ATOMIC_INT32_LOCK_FREE BOOST_ATOMIC_LLONG_LOCK_FREE
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE
#else
#define BOOST_ATOMIC_INT32_LOCK_FREE 0
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE 0
#endif
#if BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 8
#define BOOST_ATOMIC_INT64_LOCK_FREE BOOST_ATOMIC_SHORT_LOCK_FREE
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 8
#define BOOST_ATOMIC_INT64_LOCK_FREE BOOST_ATOMIC_INT_LOCK_FREE
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 8
#define BOOST_ATOMIC_INT64_LOCK_FREE BOOST_ATOMIC_LONG_LOCK_FREE
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 8
#define BOOST_ATOMIC_INT64_LOCK_FREE BOOST_ATOMIC_LLONG_LOCK_FREE
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE
#else
#define BOOST_ATOMIC_INT64_LOCK_FREE 0
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE 0
#endif
#if __GCC_ATOMIC_WCHAR_T_LOCK_FREE == 2
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE 2
#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 8
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 4
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 2
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 1
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 16
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 16
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 16
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE
#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 16
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE
#else
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE 0
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE 0
#endif
#define BOOST_ATOMIC_CHAR32_T_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#define BOOST_ATOMIC_CHAR16_T_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
// On x86-64, clang 3.4 does not implement 128-bit __atomic* intrinsics even though it defines __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16:
// https://bugs.llvm.org/show_bug.cgi?id=19149
// Another problem exists with gcc 7 and later, as it requires to link with libatomic to use 16-byte intrinsics:
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80878
// Both clang and gcc do generate cmpxchg16b for __sync_val_compare_and_swap though.
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) &&\
(\
(defined(BOOST_CLANG) && (__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 5))) ||\
(defined(BOOST_GCC) && BOOST_GCC >= 70000)\
)
#undef BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE 0
#endif
// On 32-bit x86, there is a clang bug for 64-bit atomics: https://bugs.llvm.org/show_bug.cgi?id=19355. The compiler defines
// __GCC_ATOMIC_LLONG_LOCK_FREE to 1 when the target architecture supports 64-bit atomic instructions (i.e. the value should be 2).
// Additionally, any clang version requires to link with libatomic for 64-bit __atomic* intrinsics on x86. It does generate
// cmpxchg8b for __sync_val_compare_and_swap though.
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) && defined(BOOST_CLANG)
#undef BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE 0
#endif
// Override arch-specific macros if atomic intrinsics provide better guarantees
#if !defined(BOOST_ATOMIC_INT128_LOCK_FREE) || (BOOST_ATOMIC_INT128_LOCK_FREE < BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE)
#undef BOOST_ATOMIC_INT128_LOCK_FREE
#define BOOST_ATOMIC_INT128_LOCK_FREE BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE
#endif
#if !defined(BOOST_ATOMIC_INT64_LOCK_FREE) || (BOOST_ATOMIC_INT64_LOCK_FREE < BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE) || (BOOST_ATOMIC_INT64_LOCK_FREE < BOOST_ATOMIC_INT128_LOCK_FREE)
#undef BOOST_ATOMIC_INT64_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE >= BOOST_ATOMIC_INT128_LOCK_FREE
#define BOOST_ATOMIC_INT64_LOCK_FREE BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE
#else
#define BOOST_ATOMIC_INT64_LOCK_FREE BOOST_ATOMIC_INT128_LOCK_FREE
#endif
#endif
#if !defined(BOOST_ATOMIC_INT32_LOCK_FREE) || (BOOST_ATOMIC_INT32_LOCK_FREE < BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE) || (BOOST_ATOMIC_INT32_LOCK_FREE < BOOST_ATOMIC_INT64_LOCK_FREE)
#undef BOOST_ATOMIC_INT32_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE >= BOOST_ATOMIC_INT64_LOCK_FREE
#define BOOST_ATOMIC_INT32_LOCK_FREE BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE
#else
#define BOOST_ATOMIC_INT32_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE
#endif
#endif
#if !defined(BOOST_ATOMIC_INT16_LOCK_FREE) || (BOOST_ATOMIC_INT16_LOCK_FREE < BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE) || (BOOST_ATOMIC_INT16_LOCK_FREE < BOOST_ATOMIC_INT32_LOCK_FREE)
#undef BOOST_ATOMIC_INT16_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE >= BOOST_ATOMIC_INT32_LOCK_FREE
#define BOOST_ATOMIC_INT16_LOCK_FREE BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE
#else
#define BOOST_ATOMIC_INT16_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE
#endif
#endif
#if !defined(BOOST_ATOMIC_INT8_LOCK_FREE) || (BOOST_ATOMIC_INT8_LOCK_FREE < BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT8_LOCK_FREE) || (BOOST_ATOMIC_INT8_LOCK_FREE < BOOST_ATOMIC_INT16_LOCK_FREE)
#undef BOOST_ATOMIC_INT8_LOCK_FREE
#if BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT8_LOCK_FREE >= BOOST_ATOMIC_INT16_LOCK_FREE
#define BOOST_ATOMIC_INT8_LOCK_FREE BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT8_LOCK_FREE
#else
#define BOOST_ATOMIC_INT8_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE
#endif
#endif
#if !defined(BOOST_ATOMIC_POINTER_LOCK_FREE) || (BOOST_ATOMIC_POINTER_LOCK_FREE < __GCC_ATOMIC_POINTER_LOCK_FREE)
#undef BOOST_ATOMIC_POINTER_LOCK_FREE
#define BOOST_ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE
#endif
#if !defined(BOOST_ATOMIC_THREAD_FENCE) || (BOOST_ATOMIC_THREAD_FENCE < 2)
#undef BOOST_ATOMIC_THREAD_FENCE
#define BOOST_ATOMIC_THREAD_FENCE 2
#endif
#if !defined(BOOST_ATOMIC_SIGNAL_FENCE) || (BOOST_ATOMIC_SIGNAL_FENCE < 2)
#undef BOOST_ATOMIC_SIGNAL_FENCE
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif
#endif // BOOST_ATOMIC_DETAIL_CAPS_GCC_ATOMIC_HPP_INCLUDED_

View File

@@ -1,37 +0,0 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_gcc_ppc.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_GCC_PPC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_GCC_PPC_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/hwcaps_gcc_ppc.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#define BOOST_ATOMIC_INT8_LOCK_FREE 2
#define BOOST_ATOMIC_INT16_LOCK_FREE 2
#define BOOST_ATOMIC_INT32_LOCK_FREE 2
#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX)
#define BOOST_ATOMIC_INT64_LOCK_FREE 2
#endif
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_GCC_PPC_HPP_INCLUDED_

View File

@@ -17,13 +17,6 @@
#define BOOST_ATOMIC_DETAIL_CAPS_GCC_SYNC_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#if defined(__i386__) || defined(__x86_64__)
#include <boost/atomic/detail/hwcaps_gcc_x86.hpp>
#elif defined(__arm__)
#include <boost/atomic/detail/hwcaps_gcc_arm.hpp>
#elif defined(__POWERPC__) || defined(__PPC__)
#include <boost/atomic/detail/hwcaps_gcc_ppc.hpp>
#endif
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once

View File

@@ -1,40 +0,0 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2012 Tim Blechmann
* Copyright (c) 2013 - 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/caps_gcc_x86.hpp
*
* This header defines feature capabilities macros
*/
#ifndef BOOST_ATOMIC_DETAIL_CAPS_GCC_X86_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAPS_GCC_X86_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/hwcaps_gcc_x86.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#define BOOST_ATOMIC_INT8_LOCK_FREE 2
#define BOOST_ATOMIC_INT16_LOCK_FREE 2
#define BOOST_ATOMIC_INT32_LOCK_FREE 2
#if defined(__x86_64__) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B)
#define BOOST_ATOMIC_INT64_LOCK_FREE 2
#endif
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) && (defined(BOOST_HAS_INT128) || !defined(BOOST_NO_ALIGNMENT))
#define BOOST_ATOMIC_INT128_LOCK_FREE 2
#endif
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#define BOOST_ATOMIC_THREAD_FENCE 2
#define BOOST_ATOMIC_SIGNAL_FENCE 2
#endif // BOOST_ATOMIC_DETAIL_CAPS_GCC_X86_HPP_INCLUDED_

View File

@@ -0,0 +1,50 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/cas_based_exchange.hpp
*
* This header contains CAS-based implementation of exchange operation.
*/
#ifndef BOOST_ATOMIC_DETAIL_CAS_BASED_EXCHANGE_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CAS_BASED_EXCHANGE_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
template< typename Base >
struct cas_based_exchange :
public Base
{
typedef typename Base::storage_type storage_type;
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type old_val;
atomics::detail::non_atomic_load(storage, old_val);
while (!Base::compare_exchange_weak(storage, old_val, v, order, memory_order_relaxed)) {}
return old_val;
}
};
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_CAS_BASED_EXCHANGE_HPP_INCLUDED_

View File

@@ -0,0 +1,90 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020-2021 Andrey Semashev
*/
/*!
* \file atomic/detail/classify.hpp
*
* This header contains type traits for type classification.
*/
#ifndef BOOST_ATOMIC_DETAIL_CLASSIFY_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CLASSIFY_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/type_traits/is_enum.hpp>
#include <boost/atomic/detail/type_traits/is_integral.hpp>
#include <boost/atomic/detail/type_traits/is_function.hpp>
#include <boost/atomic/detail/type_traits/is_floating_point.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
template< typename T, bool IsFunction = atomics::detail::is_function< T >::value >
struct classify_pointer
{
typedef void* type;
};
template< typename T >
struct classify_pointer< T, true >
{
typedef void type;
};
template<
typename T,
bool IsInt = atomics::detail::is_integral< T >::value,
bool IsFloat = atomics::detail::is_floating_point< T >::value,
bool IsEnum = atomics::detail::is_enum< T >::value
>
struct classify
{
typedef void type;
};
template< typename T >
struct classify< T, true, false, false > { typedef int type; };
#if !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
template< typename T >
struct classify< T, false, true, false > { typedef float type; };
#endif
template< typename T >
struct classify< T, false, false, true > { typedef const int type; };
template< typename T >
struct classify< T*, false, false, false > { typedef typename classify_pointer< T >::type type; };
template< >
struct classify< void*, false, false, false > { typedef void type; };
template< >
struct classify< const void*, false, false, false > { typedef void type; };
template< >
struct classify< volatile void*, false, false, false > { typedef void type; };
template< >
struct classify< const volatile void*, false, false, false > { typedef void type; };
template< typename T, typename U >
struct classify< T U::*, false, false, false > { typedef void type; };
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_CLASSIFY_HPP_INCLUDED_

View File

@@ -4,7 +4,7 @@
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2012 Hartmut Kaiser
* Copyright (c) 2014 Andrey Semashev
* Copyright (c) 2014-2018, 2020-2021 Andrey Semashev
*/
/*!
* \file atomic/detail/config.hpp
@@ -36,24 +36,45 @@
#define BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA
#endif
#if (defined(__i386__) || defined(__x86_64__)) && (defined(__clang__) || (defined(BOOST_GCC) && (BOOST_GCC+0) < 40500) || defined(__SUNPRO_CC))
#if (defined(__i386__) || defined(__x86_64__)) && (defined(__clang__) || (defined(BOOST_GCC) && BOOST_GCC < 40500) || defined(__SUNPRO_CC))
// This macro indicates that the compiler does not support allocating eax:edx or rax:rdx register pairs ("A") in asm blocks
#define BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS
#endif
#if defined(__i386__) && (defined(__PIC__) || defined(__PIE__)) && !(defined(__clang__) || (defined(BOOST_GCC) && (BOOST_GCC+0) >= 50100))
#if defined(__i386__) && (defined(__PIC__) || defined(__PIE__)) && !(defined(__clang__) || (defined(BOOST_GCC) && BOOST_GCC >= 50100))
// This macro indicates that asm blocks should preserve ebx value unchanged. Some compilers are able to maintain ebx themselves
// around the asm blocks. For those compilers we don't need to save/restore ebx in asm blocks.
#define BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX
#endif
#if defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
#if !(defined(BOOST_LIBSTDCXX11) && (BOOST_LIBSTDCXX_VERSION+0) >= 40700) /* libstdc++ from gcc >= 4.7 in C++11 mode */
#if !(defined(BOOST_LIBSTDCXX11) && BOOST_LIBSTDCXX_VERSION >= 40700) /* libstdc++ from gcc >= 4.7 in C++11 mode */
// This macro indicates that there is not even a basic <type_traits> standard header that is sufficient for most Boost.Atomic needs.
#define BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS
#endif
#endif // defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
#if defined(BOOST_NO_CXX11_ALIGNAS) ||\
(defined(BOOST_GCC) && BOOST_GCC < 40900) ||\
(defined(BOOST_MSVC) && BOOST_MSVC < 1910 && defined(_M_IX86))
// gcc prior to 4.9 doesn't support alignas with a constant expression as an argument.
// MSVC 14.0 does support alignas, but in 32-bit mode emits "error C2719: formal parameter with requested alignment of N won't be aligned" for N > 4,
// when aligned types are used in function arguments, even though the std::max_align_t type has alignment of 8.
#define BOOST_ATOMIC_DETAIL_NO_CXX11_ALIGNAS
#endif
#if defined(BOOST_NO_CXX11_CONSTEXPR) || (defined(BOOST_GCC) && BOOST_GCC < 40800)
// This macro indicates that the compiler doesn't support constexpr constructors that initialize one member
// of an anonymous union member of the class.
#define BOOST_ATOMIC_DETAIL_NO_CXX11_CONSTEXPR_UNION_INIT
#endif
#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_CONSTEXPR_UNION_INIT)
#define BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT BOOST_CONSTEXPR
#else
#define BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT
#endif
// Enable pointer/reference casts between storage and value when possible.
// Note: Despite that MSVC does not employ strict aliasing rules for optimizations
// and does not require an explicit markup for types that may alias, we still don't
@@ -70,11 +91,31 @@
#define BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS
#endif
#if defined(BOOST_INTEL) || (defined(BOOST_GCC) && BOOST_GCC < 40700) ||\
(defined(BOOST_CLANG) && !defined(__apple_build_version__) && (__clang_major__ * 100 + __clang_minor__) < 302) ||\
(defined(__clang__) && defined(__apple_build_version__) && (__clang_major__ * 100 + __clang_minor__) < 402)
// Intel compiler (at least 18.0 update 1) breaks if noexcept specification is used in defaulted function declarations:
// error: the default constructor of "boost::atomics::atomic<T>" cannot be referenced -- it is a deleted function
// GCC 4.6 doesn't seem to support that either. Clang 3.1 deduces wrong noexcept for the defaulted function and fails as well.
#define BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL
#define BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL BOOST_NOEXCEPT
#else
#define BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL BOOST_NOEXCEPT
#define BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL
#endif
#if defined(__has_builtin)
#if __has_builtin(__builtin_constant_p)
#define BOOST_ATOMIC_DETAIL_IS_CONSTANT(x) __builtin_constant_p(x)
#endif
#elif defined(__GNUC__)
#if __has_builtin(__builtin_clear_padding)
#define BOOST_ATOMIC_DETAIL_CLEAR_PADDING(x) __builtin_clear_padding(x)
#elif __has_builtin(__builtin_zero_non_value_bits)
#define BOOST_ATOMIC_DETAIL_CLEAR_PADDING(x) __builtin_zero_non_value_bits(x)
#endif
#endif
#if !defined(BOOST_ATOMIC_DETAIL_IS_CONSTANT) && defined(__GNUC__)
#define BOOST_ATOMIC_DETAIL_IS_CONSTANT(x) __builtin_constant_p(x)
#endif
@@ -82,69 +123,21 @@
#define BOOST_ATOMIC_DETAIL_IS_CONSTANT(x) false
#endif
#if (defined(__BYTE_ORDER__) && defined(__FLOAT_WORD_ORDER__) && (__BYTE_ORDER__+0) == (__FLOAT_WORD_ORDER__+0)) ||\
#if !defined(BOOST_ATOMIC_DETAIL_CLEAR_PADDING) && defined(BOOST_MSVC) && BOOST_MSVC >= 1927
// Note that as of MSVC 19.29 this intrinsic does not clear padding in unions:
// https://developercommunity.visualstudio.com/t/__builtin_zero_non_value_bits-does-not-c/1551510
#define BOOST_ATOMIC_DETAIL_CLEAR_PADDING(x) __builtin_zero_non_value_bits(x)
#endif
#if !defined(BOOST_ATOMIC_DETAIL_CLEAR_PADDING)
#define BOOST_ATOMIC_NO_CLEAR_PADDING
#define BOOST_ATOMIC_DETAIL_CLEAR_PADDING(x)
#endif
#if (defined(__BYTE_ORDER__) && defined(__FLOAT_WORD_ORDER__) && __BYTE_ORDER__ == __FLOAT_WORD_ORDER__) ||\
defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
// This macro indicates that integer and floating point endianness is the same
#define BOOST_ATOMIC_DETAIL_INT_FP_ENDIAN_MATCH
#endif
// Deprecated symbols markup
#if !defined(BOOST_ATOMIC_DETAIL_DEPRECATED) && defined(_MSC_VER)
#if (_MSC_VER) >= 1400
#define BOOST_ATOMIC_DETAIL_DEPRECATED(msg) __declspec(deprecated(msg))
#else
// MSVC 7.1 only supports the attribute without a message
#define BOOST_ATOMIC_DETAIL_DEPRECATED(msg) __declspec(deprecated)
#endif
#endif
#if !defined(BOOST_ATOMIC_DETAIL_DEPRECATED) && defined(__has_extension)
#if __has_extension(attribute_deprecated_with_message)
#define BOOST_ATOMIC_DETAIL_DEPRECATED(msg) __attribute__((deprecated(msg)))
#endif
#endif
// gcc since 4.5 supports deprecated attribute with a message; older versions support the attribute without a message.
// Oracle Studio 12.4 supports deprecated attribute with a message; this is the first release that supports the attribute.
#if !defined(BOOST_ATOMIC_DETAIL_DEPRECATED) && (\
(defined(__GNUC__) && ((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0)) >= 405) ||\
(defined(__SUNPRO_CC) && (__SUNPRO_CC + 0) >= 0x5130))
#define BOOST_ATOMIC_DETAIL_DEPRECATED(msg) __attribute__((deprecated(msg)))
#endif
#if !defined(BOOST_ATOMIC_DETAIL_DEPRECATED) && __cplusplus >= 201402
#define BOOST_ATOMIC_DETAIL_DEPRECATED(msg) [[deprecated(msg)]]
#endif
#if !defined(BOOST_ATOMIC_DETAIL_DEPRECATED) && defined(__GNUC__)
#define BOOST_ATOMIC_DETAIL_DEPRECATED(msg) __attribute__((deprecated))
#endif
#if !defined(BOOST_ATOMIC_DETAIL_DEPRECATED) && defined(__has_attribute)
#if __has_attribute(deprecated)
#define BOOST_ATOMIC_DETAIL_DEPRECATED(msg) __attribute__((deprecated))
#endif
#endif
#if !defined(BOOST_ATOMIC_DETAIL_DEPRECATED)
#define BOOST_ATOMIC_DETAIL_DEPRECATED(msg)
#endif
// In Boost.Atomic 1.67 we changed (op)_and_test methods to return true when the result is non-zero. This would be more consistent
// with the other names used in Boost.Atomic and the C++ standard library. Since the methods were announced as experimental and
// the previous behavior was released only in Boost 1.66, it was decided to change the result without changing the method names.
// By defining BOOST_ATOMIC_HIGHLIGHT_OP_AND_TEST the user has a way to highlight all uses of the affected functions so
// that it is easier to find and update the affected code (which is typically adding or removing negation of the result). This
// highlighting functionality is a temporary measure to help users upgrade from Boost 1.66 to newer Boost versions. It will
// be removed eventually.
//
// More info at:
// https://github.com/boostorg/atomic/issues/11
// http://boost.2283326.n4.nabble.com/atomic-op-and-test-naming-tc4701445.html
#if defined(BOOST_ATOMIC_HIGHLIGHT_OP_AND_TEST)
#define BOOST_ATOMIC_DETAIL_HIGHLIGHT_OP_AND_TEST BOOST_ATOMIC_DETAIL_DEPRECATED("Boost.Atomic 1.67 has changed (op)_and_test result to the opposite. The functions now return true when the result is non-zero. Please, verify your use of the operation and undefine BOOST_ATOMIC_HIGHLIGHT_OP_AND_TEST.")
#else
#define BOOST_ATOMIC_DETAIL_HIGHLIGHT_OP_AND_TEST
#endif
#endif // BOOST_ATOMIC_DETAIL_CONFIG_HPP_INCLUDED_

View File

@@ -0,0 +1,50 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/core_arch_operations.hpp
*
* This header defines core atomic operations, including the emulated version.
*/
#ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPERATIONS_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPERATIONS_HPP_INCLUDED_
#include <boost/atomic/detail/core_arch_operations_fwd.hpp>
#include <boost/atomic/detail/core_operations_emulated.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/platform.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#if defined(BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND_HEADER)
#include BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND_HEADER(boost/atomic/detail/core_arch_ops_)
#endif
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
//! Default specialization that falls back to lock-based implementation
template< std::size_t Size, bool Signed, bool Interprocess >
struct core_arch_operations :
public core_operations_emulated< Size, storage_traits< Size >::alignment, Signed, Interprocess >
{
};
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_CORE_ARCH_OPERATIONS_HPP_INCLUDED_

View File

@@ -0,0 +1,38 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/core_arch_operations_fwd.hpp
*
* This header contains forward declaration of the \c core_arch_operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPERATIONS_FWD_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPERATIONS_FWD_HPP_INCLUDED_
#include <cstddef>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
template< std::size_t Size, bool Signed, bool Interprocess >
struct core_arch_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_CORE_ARCH_OPERATIONS_FWD_HPP_INCLUDED_

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -8,20 +8,20 @@
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_gcc_alpha.hpp
* \file atomic/detail/core_arch_ops_gcc_alpha.hpp
*
* This header contains implementation of the \c operations template.
* This header contains implementation of the \c core_arch_operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_ALPHA_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_GCC_ALPHA_HPP_INCLUDED_
#ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_ALPHA_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_ALPHA_HPP_INCLUDED_
#include <cstddef>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#include <boost/atomic/detail/core_arch_operations_fwd.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -62,7 +62,7 @@ namespace detail {
as it apparently does not hurt either.
*/
struct gcc_alpha_operations_base
struct core_arch_operations_gcc_alpha_base
{
static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false;
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
@@ -87,15 +87,16 @@ struct gcc_alpha_operations_base
};
template< bool Signed >
struct operations< 4u, Signed > :
public gcc_alpha_operations_base
template< bool Signed, bool Interprocess >
struct core_arch_operations< 4u, Signed, Interprocess > :
public core_arch_operations_gcc_alpha_base
{
typedef typename make_storage_type< 4u >::type storage_type;
typedef typename make_storage_type< 4u >::aligned aligned_storage_type;
typedef typename storage_traits< 4u >::type storage_type;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 4u;
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
@@ -117,15 +118,15 @@ struct operations< 4u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"mov %3, %1\n"
"ldl_l %0, %2\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"mov %3, %1\n\t"
"ldl_l %0, %2\n\t"
"stl_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (tmp) // %1
@@ -145,16 +146,16 @@ struct operations< 4u, Signed > :
storage_type current;
__asm__ __volatile__
(
"1:\n"
"ldl_l %2, %4\n" // current = *(&storage)
"cmpeq %2, %0, %3\n" // success = current == expected
"mov %2, %0\n" // expected = current
"beq %3, 2f\n" // if (success == 0) goto end
"stl_c %1, %4\n" // storage = desired; desired = store succeeded
"mov %1, %3\n" // success = desired
"2:\n"
: "+&r" (expected), // %0
"+&r" (desired), // %1
"1:\n\t"
"ldl_l %2, %4\n\t" // current = *(&storage)
"cmpeq %2, %0, %3\n\t" // success = current == expected
"mov %2, %0\n\t" // expected = current
"beq %3, 2f\n\t" // if (success == 0) goto end
"stl_c %1, %4\n\t" // storage = desired; desired = store succeeded
"mov %1, %3\n\t" // success = desired
"2:\n\t"
: "+r" (expected), // %0
"+r" (desired), // %1
"=&r" (current), // %2
"=&r" (success) // %3
: "m" (storage) // %4
@@ -175,22 +176,22 @@ struct operations< 4u, Signed > :
fence_before(success_order);
__asm__ __volatile__
(
"1:\n"
"mov %5, %1\n" // tmp = desired
"ldl_l %2, %4\n" // current = *(&storage)
"cmpeq %2, %0, %3\n" // success = current == expected
"mov %2, %0\n" // expected = current
"beq %3, 2f\n" // if (success == 0) goto end
"stl_c %1, %4\n" // storage = tmp; tmp = store succeeded
"beq %1, 3f\n" // if (tmp == 0) goto retry
"mov %1, %3\n" // success = tmp
"2:\n"
"1:\n\t"
"mov %5, %1\n\t" // tmp = desired
"ldl_l %2, %4\n\t" // current = *(&storage)
"cmpeq %2, %0, %3\n\t" // success = current == expected
"mov %2, %0\n\t" // expected = current
"beq %3, 2f\n\t" // if (success == 0) goto end
"stl_c %1, %4\n\t" // storage = tmp; tmp = store succeeded
"beq %1, 3f\n\t" // if (tmp == 0) goto retry
"mov %1, %3\n\t" // success = tmp
"2:\n\t"
".subsection 2\n"
"3: br 1b\n"
".previous\n"
".subsection 2\n\t"
"3: br 1b\n\t"
".previous\n\t"
: "+&r" (expected), // %0
: "+r" (expected), // %0
"=&r" (tmp), // %1
"=&r" (current), // %2
"=&r" (success) // %3
@@ -211,15 +212,15 @@ struct operations< 4u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"addl %0, %3, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"ldl_l %0, %2\n\t"
"addl %0, %3, %1\n\t"
"stl_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (modified) // %1
@@ -237,15 +238,15 @@ struct operations< 4u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"subl %0, %3, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"ldl_l %0, %2\n\t"
"subl %0, %3, %1\n\t"
"stl_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (modified) // %1
@@ -263,15 +264,15 @@ struct operations< 4u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"and %0, %3, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"ldl_l %0, %2\n\t"
"and %0, %3, %1\n\t"
"stl_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (modified) // %1
@@ -289,15 +290,15 @@ struct operations< 4u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"bis %0, %3, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"ldl_l %0, %2\n\t"
"bis %0, %3, %1\n\t"
"stl_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (modified) // %1
@@ -315,15 +316,15 @@ struct operations< 4u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"xor %0, %3, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"ldl_l %0, %2\n\t"
"xor %0, %3, %1\n\t"
"stl_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (modified) // %1
@@ -347,29 +348,29 @@ struct operations< 4u, Signed > :
};
template< >
struct operations< 1u, false > :
public operations< 4u, false >
template< bool Interprocess >
struct core_arch_operations< 1u, false, Interprocess > :
public core_arch_operations< 4u, false, Interprocess >
{
typedef operations< 4u, false > base_type;
typedef base_type::storage_type storage_type;
typedef core_arch_operations< 4u, false, Interprocess > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
base_type::fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"addl %0, %3, %1\n"
"zapnot %1, #1, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"ldl_l %0, %2\n\t"
"addl %0, %3, %1\n\t"
"zapnot %1, 1, %1\n\t"
"stl_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (modified) // %1
@@ -377,26 +378,26 @@ struct operations< 1u, false > :
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
base_type::fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
base_type::fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"subl %0, %3, %1\n"
"zapnot %1, #1, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"ldl_l %0, %2\n\t"
"subl %0, %3, %1\n\t"
"zapnot %1, 1, %1\n\t"
"stl_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (modified) // %1
@@ -404,34 +405,34 @@ struct operations< 1u, false > :
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
base_type::fence_after(order);
return original;
}
};
template< >
struct operations< 1u, true > :
public operations< 4u, true >
template< bool Interprocess >
struct core_arch_operations< 1u, true, Interprocess > :
public core_arch_operations< 4u, true, Interprocess >
{
typedef operations< 4u, true > base_type;
typedef base_type::storage_type storage_type;
typedef core_arch_operations< 4u, true, Interprocess > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
base_type::fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"addl %0, %3, %1\n"
"sextb %1, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"ldl_l %0, %2\n\t"
"addl %0, %3, %1\n\t"
"sextb %1, %1\n\t"
"stl_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (modified) // %1
@@ -439,26 +440,26 @@ struct operations< 1u, true > :
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
base_type::fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
base_type::fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"subl %0, %3, %1\n"
"sextb %1, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"ldl_l %0, %2\n\t"
"subl %0, %3, %1\n\t"
"sextb %1, %1\n\t"
"stl_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (modified) // %1
@@ -466,35 +467,35 @@ struct operations< 1u, true > :
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
base_type::fence_after(order);
return original;
}
};
template< >
struct operations< 2u, false > :
public operations< 4u, false >
template< bool Interprocess >
struct core_arch_operations< 2u, false, Interprocess > :
public core_arch_operations< 4u, false, Interprocess >
{
typedef operations< 4u, false > base_type;
typedef base_type::storage_type storage_type;
typedef core_arch_operations< 4u, false, Interprocess > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
base_type::fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"addl %0, %3, %1\n"
"zapnot %1, #3, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"ldl_l %0, %2\n\t"
"addl %0, %3, %1\n\t"
"zapnot %1, 3, %1\n\t"
"stl_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (modified) // %1
@@ -502,26 +503,26 @@ struct operations< 2u, false > :
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
base_type::fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
base_type::fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"subl %0, %3, %1\n"
"zapnot %1, #3, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"ldl_l %0, %2\n\t"
"subl %0, %3, %1\n\t"
"zapnot %1, 3, %1\n\t"
"stl_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (modified) // %1
@@ -529,34 +530,34 @@ struct operations< 2u, false > :
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
base_type::fence_after(order);
return original;
}
};
template< >
struct operations< 2u, true > :
public operations< 4u, true >
template< bool Interprocess >
struct core_arch_operations< 2u, true, Interprocess > :
public core_arch_operations< 4u, true, Interprocess >
{
typedef operations< 4u, true > base_type;
typedef base_type::storage_type storage_type;
typedef core_arch_operations< 4u, true, Interprocess > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
base_type::fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"addl %0, %3, %1\n"
"sextw %1, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"ldl_l %0, %2\n\t"
"addl %0, %3, %1\n\t"
"sextw %1, %1\n\t"
"stl_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (modified) // %1
@@ -564,26 +565,26 @@ struct operations< 2u, true > :
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
base_type::fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, modified;
fence_before(order);
base_type::fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldl_l %0, %2\n"
"subl %0, %3, %1\n"
"sextw %1, %1\n"
"stl_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"ldl_l %0, %2\n\t"
"subl %0, %3, %1\n\t"
"sextw %1, %1\n\t"
"stl_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (modified) // %1
@@ -591,21 +592,22 @@ struct operations< 2u, true > :
"r" (v) // %3
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
base_type::fence_after(order);
return original;
}
};
template< bool Signed >
struct operations< 8u, Signed > :
public gcc_alpha_operations_base
template< bool Signed, bool Interprocess >
struct core_arch_operations< 8u, Signed, Interprocess > :
public core_arch_operations_gcc_alpha_base
{
typedef typename make_storage_type< 8u >::type storage_type;
typedef typename make_storage_type< 8u >::aligned aligned_storage_type;
typedef typename storage_traits< 8u >::type storage_type;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 8u;
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
@@ -627,15 +629,15 @@ struct operations< 8u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"mov %3, %1\n"
"ldq_l %0, %2\n"
"stq_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"mov %3, %1\n\t"
"ldq_l %0, %2\n\t"
"stq_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (tmp) // %1
@@ -655,16 +657,16 @@ struct operations< 8u, Signed > :
storage_type current;
__asm__ __volatile__
(
"1:\n"
"ldq_l %2, %4\n" // current = *(&storage)
"cmpeq %2, %0, %3\n" // success = current == expected
"mov %2, %0\n" // expected = current
"beq %3, 2f\n" // if (success == 0) goto end
"stq_c %1, %4\n" // storage = desired; desired = store succeeded
"mov %1, %3\n" // success = desired
"2:\n"
: "+&r" (expected), // %0
"+&r" (desired), // %1
"1:\n\t"
"ldq_l %2, %4\n\t" // current = *(&storage)
"cmpeq %2, %0, %3\n\t" // success = current == expected
"mov %2, %0\n\t" // expected = current
"beq %3, 2f\n\t" // if (success == 0) goto end
"stq_c %1, %4\n\t" // storage = desired; desired = store succeeded
"mov %1, %3\n\t" // success = desired
"2:\n\t"
: "+r" (expected), // %0
"+r" (desired), // %1
"=&r" (current), // %2
"=&r" (success) // %3
: "m" (storage) // %4
@@ -685,22 +687,22 @@ struct operations< 8u, Signed > :
fence_before(success_order);
__asm__ __volatile__
(
"1:\n"
"mov %5, %1\n" // tmp = desired
"ldq_l %2, %4\n" // current = *(&storage)
"cmpeq %2, %0, %3\n" // success = current == expected
"mov %2, %0\n" // expected = current
"beq %3, 2f\n" // if (success == 0) goto end
"stq_c %1, %4\n" // storage = tmp; tmp = store succeeded
"beq %1, 3f\n" // if (tmp == 0) goto retry
"mov %1, %3\n" // success = tmp
"2:\n"
"1:\n\t"
"mov %5, %1\n\t" // tmp = desired
"ldq_l %2, %4\n\t" // current = *(&storage)
"cmpeq %2, %0, %3\n\t" // success = current == expected
"mov %2, %0\n\t" // expected = current
"beq %3, 2f\n\t" // if (success == 0) goto end
"stq_c %1, %4\n\t" // storage = tmp; tmp = store succeeded
"beq %1, 3f\n\t" // if (tmp == 0) goto retry
"mov %1, %3\n\t" // success = tmp
"2:\n\t"
".subsection 2\n"
"3: br 1b\n"
".previous\n"
".subsection 2\n\t"
"3: br 1b\n\t"
".previous\n\t"
: "+&r" (expected), // %0
: "+r" (expected), // %0
"=&r" (tmp), // %1
"=&r" (current), // %2
"=&r" (success) // %3
@@ -721,15 +723,15 @@ struct operations< 8u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldq_l %0, %2\n"
"addq %0, %3, %1\n"
"stq_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"ldq_l %0, %2\n\t"
"addq %0, %3, %1\n\t"
"stq_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (modified) // %1
@@ -747,15 +749,15 @@ struct operations< 8u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldq_l %0, %2\n"
"subq %0, %3, %1\n"
"stq_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"ldq_l %0, %2\n\t"
"subq %0, %3, %1\n\t"
"stq_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (modified) // %1
@@ -773,15 +775,15 @@ struct operations< 8u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldq_l %0, %2\n"
"and %0, %3, %1\n"
"stq_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"ldq_l %0, %2\n\t"
"and %0, %3, %1\n\t"
"stq_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (modified) // %1
@@ -799,15 +801,15 @@ struct operations< 8u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldq_l %0, %2\n"
"bis %0, %3, %1\n"
"stq_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"ldq_l %0, %2\n\t"
"bis %0, %3, %1\n\t"
"stq_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (modified) // %1
@@ -825,15 +827,15 @@ struct operations< 8u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n"
"ldq_l %0, %2\n"
"xor %0, %3, %1\n"
"stq_c %1, %2\n"
"beq %1, 2f\n"
"1:\n\t"
"ldq_l %0, %2\n\t"
"xor %0, %3, %1\n\t"
"stq_c %1, %2\n\t"
"beq %1, 2f\n\t"
".subsection 2\n"
"2: br 1b\n"
".previous\n"
".subsection 2\n\t"
"2: br 1b\n\t"
".previous\n\t"
: "=&r" (original), // %0
"=&r" (modified) // %1
@@ -852,25 +854,14 @@ struct operations< 8u, Signed > :
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
store(storage, 0, order);
store(storage, (storage_type)0, order);
}
};
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("mb" ::: "memory");
}
BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("" ::: "memory");
}
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_ALPHA_HPP_INCLUDED_
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_ALPHA_HPP_INCLUDED_

View File

@@ -8,21 +8,23 @@
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_gcc_ppc.hpp
* \file atomic/detail/core_arch_ops_gcc_ppc.hpp
*
* This header contains implementation of the \c operations template.
* This header contains implementation of the \c core_arch_operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_HPP_INCLUDED_
#ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_PPC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_PPC_HPP_INCLUDED_
#include <cstddef>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#include <boost/atomic/detail/core_arch_operations_fwd.hpp>
#include <boost/atomic/detail/ops_gcc_ppc_common.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/gcc_ppc_asm_common.hpp>
#include <boost/atomic/detail/capabilities.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -79,15 +81,16 @@ namespace detail {
to pose a problem.
*/
template< bool Signed >
struct operations< 4u, Signed > :
public gcc_ppc_operations_base
template< bool Signed, bool Interprocess >
struct core_arch_operations< 4u, Signed, Interprocess > :
public core_arch_operations_gcc_ppc_base
{
typedef typename make_storage_type< 4u >::type storage_type;
typedef typename make_storage_type< 4u >::aligned aligned_storage_type;
typedef typename storage_traits< 4u >::type storage_type;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 4u;
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
@@ -111,8 +114,8 @@ struct operations< 4u, Signed > :
(
"lwz %0, %1\n\t"
"cmpw %0, %0\n\t"
"bne- 1f\n\t"
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+4")
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"isync\n\t"
: "=&r" (v)
: "m" (storage)
@@ -137,10 +140,10 @@ struct operations< 4u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y1\n\t"
"stwcx. %2,%y1\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-8")
: "=&b" (original), "+Z" (storage)
: "b" (v)
: "cr0"
@@ -159,11 +162,11 @@ struct operations< 4u, Signed > :
"li %1, 0\n\t"
"lwarx %0,%y2\n\t"
"cmpw %0, %3\n\t"
"bne- 1f\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+16")
"stwcx. %4,%y2\n\t"
"bne- 1f\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+8")
"li %1, 1\n\t"
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
: "=&b" (expected), "=&b" (success), "+Z" (storage)
: "b" (expected), "b" (desired)
: "cr0"
@@ -183,13 +186,14 @@ struct operations< 4u, Signed > :
__asm__ __volatile__
(
"li %1, 0\n\t"
"0: lwarx %0,%y2\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("0")
"lwarx %0,%y2\n\t"
"cmpw %0, %3\n\t"
"bne- 1f\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+16")
"stwcx. %4,%y2\n\t"
"bne- 0b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "0b", "-16")
"li %1, 1\n\t"
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
: "=&b" (expected), "=&b" (success), "+Z" (storage)
: "b" (expected), "b" (desired)
: "cr0"
@@ -207,11 +211,11 @@ struct operations< 4u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"add %1,%0,%3\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -226,11 +230,11 @@ struct operations< 4u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"sub %1,%0,%3\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -245,11 +249,11 @@ struct operations< 4u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"and %1,%0,%3\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -264,11 +268,11 @@ struct operations< 4u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"or %1,%0,%3\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -283,11 +287,11 @@ struct operations< 4u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"xor %1,%0,%3\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -303,21 +307,22 @@ struct operations< 4u, Signed > :
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
store(storage, 0, order);
store(storage, (storage_type)0, order);
}
};
#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX)
template< bool Signed >
struct operations< 1u, Signed > :
public gcc_ppc_operations_base
template< bool Signed, bool Interprocess >
struct core_arch_operations< 1u, Signed, Interprocess > :
public core_arch_operations_gcc_ppc_base
{
typedef typename make_storage_type< 1u >::type storage_type;
typedef typename make_storage_type< 1u >::aligned aligned_storage_type;
typedef typename storage_traits< 1u >::type storage_type;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 1u;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 1u;
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
@@ -341,8 +346,8 @@ struct operations< 1u, Signed > :
(
"lbz %0, %1\n\t"
"cmpw %0, %0\n\t"
"bne- 1f\n\t"
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+4")
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"isync\n\t"
: "=&r" (v)
: "m" (storage)
@@ -367,10 +372,10 @@ struct operations< 1u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lbarx %0,%y1\n\t"
"stbcx. %2,%y1\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-8")
: "=&b" (original), "+Z" (storage)
: "b" (v)
: "cr0"
@@ -389,11 +394,11 @@ struct operations< 1u, Signed > :
"li %1, 0\n\t"
"lbarx %0,%y2\n\t"
"cmpw %0, %3\n\t"
"bne- 1f\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+16")
"stbcx. %4,%y2\n\t"
"bne- 1f\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+8")
"li %1, 1\n\t"
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
: "=&b" (expected), "=&b" (success), "+Z" (storage)
: "b" (expected), "b" (desired)
: "cr0"
@@ -413,13 +418,14 @@ struct operations< 1u, Signed > :
__asm__ __volatile__
(
"li %1, 0\n\t"
"0: lbarx %0,%y2\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("0")
"lbarx %0,%y2\n\t"
"cmpw %0, %3\n\t"
"bne- 1f\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+16")
"stbcx. %4,%y2\n\t"
"bne- 0b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "0b", "-16")
"li %1, 1\n\t"
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
: "=&b" (expected), "=&b" (success), "+Z" (storage)
: "b" (expected), "b" (desired)
: "cr0"
@@ -437,11 +443,11 @@ struct operations< 1u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lbarx %0,%y2\n\t"
"add %1,%0,%3\n\t"
"stbcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -456,11 +462,11 @@ struct operations< 1u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lbarx %0,%y2\n\t"
"sub %1,%0,%3\n\t"
"stbcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -475,11 +481,11 @@ struct operations< 1u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lbarx %0,%y2\n\t"
"and %1,%0,%3\n\t"
"stbcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -494,11 +500,11 @@ struct operations< 1u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lbarx %0,%y2\n\t"
"or %1,%0,%3\n\t"
"stbcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -513,11 +519,11 @@ struct operations< 1u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lbarx %0,%y2\n\t"
"xor %1,%0,%3\n\t"
"stbcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -533,104 +539,104 @@ struct operations< 1u, Signed > :
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
store(storage, 0, order);
store(storage, (storage_type)0, order);
}
};
#else // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX)
template< >
struct operations< 1u, false > :
public operations< 4u, false >
template< bool Interprocess >
struct core_arch_operations< 1u, false, Interprocess > :
public core_arch_operations< 4u, false, Interprocess >
{
typedef operations< 4u, false > base_type;
typedef base_type::storage_type storage_type;
typedef core_arch_operations< 4u, false, Interprocess > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
fence_before(order);
base_type::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"add %1,%0,%3\n\t"
"rlwinm %1, %1, 0, 0xff\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-16")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
base_type::fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
fence_before(order);
base_type::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"sub %1,%0,%3\n\t"
"rlwinm %1, %1, 0, 0xff\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-16")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
base_type::fence_after(order);
return original;
}
};
template< >
struct operations< 1u, true > :
public operations< 4u, true >
template< bool Interprocess >
struct core_arch_operations< 1u, true, Interprocess > :
public core_arch_operations< 4u, true, Interprocess >
{
typedef operations< 4u, true > base_type;
typedef base_type::storage_type storage_type;
typedef core_arch_operations< 4u, true, Interprocess > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
fence_before(order);
base_type::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"add %1,%0,%3\n\t"
"extsb %1, %1\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-16")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
base_type::fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
fence_before(order);
base_type::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"sub %1,%0,%3\n\t"
"extsb %1, %1\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-16")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
base_type::fence_after(order);
return original;
}
};
@@ -639,15 +645,16 @@ struct operations< 1u, true > :
#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX)
template< bool Signed >
struct operations< 2u, Signed > :
public gcc_ppc_operations_base
template< bool Signed, bool Interprocess >
struct core_arch_operations< 2u, Signed, Interprocess > :
public core_arch_operations_gcc_ppc_base
{
typedef typename make_storage_type< 2u >::type storage_type;
typedef typename make_storage_type< 2u >::aligned aligned_storage_type;
typedef typename storage_traits< 2u >::type storage_type;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 2u;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 2u;
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
@@ -671,8 +678,8 @@ struct operations< 2u, Signed > :
(
"lhz %0, %1\n\t"
"cmpw %0, %0\n\t"
"bne- 1f\n\t"
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+4")
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"isync\n\t"
: "=&r" (v)
: "m" (storage)
@@ -697,10 +704,10 @@ struct operations< 2u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lharx %0,%y1\n\t"
"sthcx. %2,%y1\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-8")
: "=&b" (original), "+Z" (storage)
: "b" (v)
: "cr0"
@@ -719,11 +726,11 @@ struct operations< 2u, Signed > :
"li %1, 0\n\t"
"lharx %0,%y2\n\t"
"cmpw %0, %3\n\t"
"bne- 1f\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+16")
"sthcx. %4,%y2\n\t"
"bne- 1f\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+8")
"li %1, 1\n\t"
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
: "=&b" (expected), "=&b" (success), "+Z" (storage)
: "b" (expected), "b" (desired)
: "cr0"
@@ -743,13 +750,14 @@ struct operations< 2u, Signed > :
__asm__ __volatile__
(
"li %1, 0\n\t"
"0: lharx %0,%y2\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("0")
"lharx %0,%y2\n\t"
"cmpw %0, %3\n\t"
"bne- 1f\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+16")
"sthcx. %4,%y2\n\t"
"bne- 0b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "0b", "-16")
"li %1, 1\n\t"
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
: "=&b" (expected), "=&b" (success), "+Z" (storage)
: "b" (expected), "b" (desired)
: "cr0"
@@ -767,11 +775,11 @@ struct operations< 2u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lharx %0,%y2\n\t"
"add %1,%0,%3\n\t"
"sthcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -786,11 +794,11 @@ struct operations< 2u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lharx %0,%y2\n\t"
"sub %1,%0,%3\n\t"
"sthcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -805,11 +813,11 @@ struct operations< 2u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lharx %0,%y2\n\t"
"and %1,%0,%3\n\t"
"sthcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -824,11 +832,11 @@ struct operations< 2u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lharx %0,%y2\n\t"
"or %1,%0,%3\n\t"
"sthcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -843,11 +851,11 @@ struct operations< 2u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lharx %0,%y2\n\t"
"xor %1,%0,%3\n\t"
"sthcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -863,104 +871,104 @@ struct operations< 2u, Signed > :
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
store(storage, 0, order);
store(storage, (storage_type)0, order);
}
};
#else // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX)
template< >
struct operations< 2u, false > :
public operations< 4u, false >
template< bool Interprocess >
struct core_arch_operations< 2u, false, Interprocess > :
public core_arch_operations< 4u, false, Interprocess >
{
typedef operations< 4u, false > base_type;
typedef base_type::storage_type storage_type;
typedef core_arch_operations< 4u, false, Interprocess > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
fence_before(order);
base_type::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"add %1,%0,%3\n\t"
"rlwinm %1, %1, 0, 0xffff\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-16")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
base_type::fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
fence_before(order);
base_type::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"sub %1,%0,%3\n\t"
"rlwinm %1, %1, 0, 0xffff\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-16")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
base_type::fence_after(order);
return original;
}
};
template< >
struct operations< 2u, true > :
public operations< 4u, true >
template< bool Interprocess >
struct core_arch_operations< 2u, true, Interprocess > :
public core_arch_operations< 4u, true, Interprocess >
{
typedef operations< 4u, true > base_type;
typedef base_type::storage_type storage_type;
typedef core_arch_operations< 4u, true, Interprocess > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
fence_before(order);
base_type::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"add %1,%0,%3\n\t"
"extsh %1, %1\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-16")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
base_type::fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
fence_before(order);
base_type::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"sub %1,%0,%3\n\t"
"extsh %1, %1\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-16")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
fence_after(order);
base_type::fence_after(order);
return original;
}
};
@@ -969,15 +977,16 @@ struct operations< 2u, true > :
#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX)
template< bool Signed >
struct operations< 8u, Signed > :
public gcc_ppc_operations_base
template< bool Signed, bool Interprocess >
struct core_arch_operations< 8u, Signed, Interprocess > :
public core_arch_operations_gcc_ppc_base
{
typedef typename make_storage_type< 8u >::type storage_type;
typedef typename make_storage_type< 8u >::aligned aligned_storage_type;
typedef typename storage_traits< 8u >::type storage_type;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 8u;
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
@@ -1001,8 +1010,8 @@ struct operations< 8u, Signed > :
(
"ld %0, %1\n\t"
"cmpd %0, %0\n\t"
"bne- 1f\n\t"
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+4")
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"isync\n\t"
: "=&b" (v)
: "m" (storage)
@@ -1027,10 +1036,10 @@ struct operations< 8u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"ldarx %0,%y1\n\t"
"stdcx. %2,%y1\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-8")
: "=&b" (original), "+Z" (storage)
: "b" (v)
: "cr0"
@@ -1049,11 +1058,11 @@ struct operations< 8u, Signed > :
"li %1, 0\n\t"
"ldarx %0,%y2\n\t"
"cmpd %0, %3\n\t"
"bne- 1f\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+16")
"stdcx. %4,%y2\n\t"
"bne- 1f\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+8")
"li %1, 1\n\t"
"1:"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
: "=&b" (expected), "=&b" (success), "+Z" (storage)
: "b" (expected), "b" (desired)
: "cr0"
@@ -1073,13 +1082,14 @@ struct operations< 8u, Signed > :
__asm__ __volatile__
(
"li %1, 0\n\t"
"0: ldarx %0,%y2\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("0")
"ldarx %0,%y2\n\t"
"cmpd %0, %3\n\t"
"bne- 1f\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+16")
"stdcx. %4,%y2\n\t"
"bne- 0b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "0b", "-16")
"li %1, 1\n\t"
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
: "=&b" (expected), "=&b" (success), "+Z" (storage)
: "b" (expected), "b" (desired)
: "cr0"
@@ -1097,11 +1107,11 @@ struct operations< 8u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"ldarx %0,%y2\n\t"
"add %1,%0,%3\n\t"
"stdcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -1116,11 +1126,11 @@ struct operations< 8u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"ldarx %0,%y2\n\t"
"sub %1,%0,%3\n\t"
"stdcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -1135,11 +1145,11 @@ struct operations< 8u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"ldarx %0,%y2\n\t"
"and %1,%0,%3\n\t"
"stdcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -1154,11 +1164,11 @@ struct operations< 8u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"ldarx %0,%y2\n\t"
"or %1,%0,%3\n\t"
"stdcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -1173,11 +1183,11 @@ struct operations< 8u, Signed > :
fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"ldarx %0,%y2\n\t"
"xor %1,%0,%3\n\t"
"stdcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
@@ -1193,40 +1203,16 @@ struct operations< 8u, Signed > :
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
store(storage, 0, order);
store(storage, (storage_type)0, order);
}
};
#endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX)
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
{
#if defined(__powerpc64__) || defined(__PPC64__)
if (order != memory_order_seq_cst)
__asm__ __volatile__ ("lwsync" ::: "memory");
else
__asm__ __volatile__ ("sync" ::: "memory");
#else
__asm__ __volatile__ ("sync" ::: "memory");
#endif
}
}
BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
#if defined(__ibmxl__) || defined(__IBMCPP__)
__fence();
#else
__asm__ __volatile__ ("" ::: "memory");
#endif
}
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_HPP_INCLUDED_
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_PPC_HPP_INCLUDED_

View File

@@ -8,22 +8,23 @@
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_gcc_sparc.hpp
* \file atomic/detail/core_arch_ops_gcc_sparc.hpp
*
* This header contains implementation of the \c operations template.
* This header contains implementation of the \c core_arch_operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_SPARC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_GCC_SPARC_HPP_INCLUDED_
#ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_SPARC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_SPARC_HPP_INCLUDED_
#include <cstddef>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/ops_cas_based.hpp>
#include <boost/atomic/detail/ops_extending_cas_based.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#include <boost/atomic/detail/core_arch_operations_fwd.hpp>
#include <boost/atomic/detail/core_ops_cas_based.hpp>
#include <boost/atomic/detail/cas_based_exchange.hpp>
#include <boost/atomic/detail/extending_cas_based_arithmetic.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -61,15 +62,16 @@ struct gcc_sparc_cas_base
}
};
template< bool Signed >
template< bool Signed, bool Interprocess >
struct gcc_sparc_cas32 :
public gcc_sparc_cas_base
{
typedef typename make_storage_type< 4u >::type storage_type;
typedef typename make_storage_type< 4u >::aligned aligned_storage_type;
typedef typename storage_traits< 4u >::type storage_type;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 4u;
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
@@ -127,33 +129,34 @@ struct gcc_sparc_cas32 :
}
};
template< bool Signed >
struct operations< 4u, Signed > :
public cas_based_operations< gcc_sparc_cas32< Signed > >
template< bool Signed, bool Interprocess >
struct core_arch_operations< 4u, Signed, Interprocess > :
public core_operations_cas_based< gcc_sparc_cas32< Signed, Interprocess > >
{
};
template< bool Signed >
struct operations< 1u, Signed > :
public extending_cas_based_operations< operations< 4u, Signed >, 1u, Signed >
template< bool Signed, bool Interprocess >
struct core_arch_operations< 1u, Signed, Interprocess > :
public extending_cas_based_arithmetic< core_arch_operations< 4u, Signed, Interprocess >, 1u, Signed >
{
};
template< bool Signed >
struct operations< 2u, Signed > :
public extending_cas_based_operations< operations< 4u, Signed >, 2u, Signed >
template< bool Signed, bool Interprocess >
struct core_arch_operations< 2u, Signed, Interprocess > :
public extending_cas_based_arithmetic< core_arch_operations< 4u, Signed, Interprocess >, 2u, Signed >
{
};
template< bool Signed >
template< bool Signed, bool Interprocess >
struct gcc_sparc_cas64 :
public gcc_sparc_cas_base
{
typedef typename make_storage_type< 8u >::type storage_type;
typedef typename make_storage_type< 8u >::aligned aligned_storage_type;
typedef typename storage_traits< 8u >::type storage_type;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 8u;
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
@@ -197,44 +200,16 @@ struct gcc_sparc_cas64 :
}
};
template< bool Signed >
struct operations< 8u, Signed > :
public cas_based_operations< cas_based_exchange< gcc_sparc_cas64< Signed > > >
template< bool Signed, bool Interprocess >
struct core_arch_operations< 8u, Signed, Interprocess > :
public core_operations_cas_based< cas_based_exchange< gcc_sparc_cas64< Signed, Interprocess > > >
{
};
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_release:
__asm__ __volatile__ ("membar #StoreStore | #LoadStore" ::: "memory");
break;
case memory_order_consume:
case memory_order_acquire:
__asm__ __volatile__ ("membar #LoadLoad | #LoadStore" ::: "memory");
break;
case memory_order_acq_rel:
__asm__ __volatile__ ("membar #LoadLoad | #LoadStore | #StoreStore" ::: "memory");
break;
case memory_order_seq_cst:
__asm__ __volatile__ ("membar #Sync" ::: "memory");
break;
case memory_order_relaxed:
default:
break;
}
}
BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("" ::: "memory");
}
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_SPARC_HPP_INCLUDED_
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_ARCH_OPS_GCC_SPARC_HPP_INCLUDED_

File diff suppressed because it is too large Load Diff

View File

@@ -8,29 +8,50 @@
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_msvc_arm.hpp
* \file atomic/detail/core_arch_ops_msvc_arm.hpp
*
* This header contains implementation of the \c operations template.
* This header contains implementation of the \c core_arch_operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_MSVC_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_MSVC_ARM_HPP_INCLUDED_
#ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_MSVC_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_MSVC_ARM_HPP_INCLUDED_
#include <intrin.h>
#include <cstddef>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/interlocked.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#include <boost/atomic/detail/core_arch_operations_fwd.hpp>
#include <boost/atomic/detail/type_traits/make_signed.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/ops_msvc_common.hpp>
#include <boost/atomic/detail/fence_arch_operations.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
extern "C" {
__int8 __iso_volatile_load8(const volatile __int8*);
__int16 __iso_volatile_load16(const volatile __int16*);
__int32 __iso_volatile_load32(const volatile __int32*);
__int64 __iso_volatile_load64(const volatile __int64*);
void __iso_volatile_store8(volatile __int8*, __int8);
void __iso_volatile_store16(volatile __int16*, __int16);
void __iso_volatile_store32(volatile __int32*, __int32);
void __iso_volatile_store64(volatile __int64*, __int64);
}
#if defined(BOOST_MSVC)
#pragma intrinsic(__iso_volatile_load8)
#pragma intrinsic(__iso_volatile_load16)
#pragma intrinsic(__iso_volatile_load32)
#pragma intrinsic(__iso_volatile_load64)
#pragma intrinsic(__iso_volatile_store8)
#pragma intrinsic(__iso_volatile_store16)
#pragma intrinsic(__iso_volatile_store32)
#pragma intrinsic(__iso_volatile_store64)
#endif
#define BOOST_ATOMIC_DETAIL_ARM_LOAD8(p) __iso_volatile_load8((const volatile __int8*)(p))
#define BOOST_ATOMIC_DETAIL_ARM_LOAD16(p) __iso_volatile_load16((const volatile __int16*)(p))
#define BOOST_ATOMIC_DETAIL_ARM_LOAD32(p) __iso_volatile_load32((const volatile __int32*)(p))
@@ -52,22 +73,17 @@ namespace detail {
// control of. See this thread: http://lists.boost.org/Archives/boost/2014/06/213890.php.
// For this reason we promote memory_order_consume to memory_order_acquire.
struct msvc_arm_operations_base
struct core_arch_operations_msvc_arm_base
{
static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false;
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
{
__dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
}
static BOOST_FORCEINLINE void fence_before_store(memory_order order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u)
hardware_full_fence();
fence_arch_operations::hardware_full_fence();
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
@@ -77,7 +93,7 @@ struct msvc_arm_operations_base
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
if (order == memory_order_seq_cst)
hardware_full_fence();
fence_arch_operations::hardware_full_fence();
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
@@ -87,7 +103,7 @@ struct msvc_arm_operations_base
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
hardware_full_fence();
fence_arch_operations::hardware_full_fence();
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
@@ -100,15 +116,16 @@ struct msvc_arm_operations_base
}
};
template< std::size_t Size, bool Signed, typename Derived >
struct msvc_arm_operations :
public msvc_arm_operations_base
template< std::size_t Size, bool Signed, bool Interprocess, typename Derived >
struct core_arch_operations_msvc_arm :
public core_arch_operations_msvc_arm_base
{
typedef typename make_storage_type< Size >::type storage_type;
typedef typename make_storage_type< Size >::aligned aligned_storage_type;
typedef typename storage_traits< Size >::type storage_type;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = storage_traits< Size >::alignment;
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
@@ -133,11 +150,11 @@ struct msvc_arm_operations :
}
};
template< bool Signed >
struct operations< 1u, Signed > :
public msvc_arm_operations< 1u, Signed, operations< 1u, Signed > >
template< bool Signed, bool Interprocess >
struct core_arch_operations< 1u, Signed, Interprocess > :
public core_arch_operations_msvc_arm< 1u, Signed, Interprocess, core_arch_operations< 1u, Signed, Interprocess > >
{
typedef msvc_arm_operations< 1u, Signed, operations< 1u, Signed > > base_type;
typedef core_arch_operations_msvc_arm< 1u, Signed, Interprocess, core_arch_operations< 1u, Signed, Interprocess > > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
@@ -205,7 +222,7 @@ struct operations< 1u, Signed > :
{
storage_type previous = expected, old_val;
switch (cas_common_order(success_order, failure_order))
switch (base_type::cas_common_order(success_order, failure_order))
{
case memory_order_relaxed:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8_RELAXED(&storage, desired, previous));
@@ -298,11 +315,11 @@ struct operations< 1u, Signed > :
}
};
template< bool Signed >
struct operations< 2u, Signed > :
public msvc_arm_operations< 2u, Signed, operations< 2u, Signed > >
template< bool Signed, bool Interprocess >
struct core_arch_operations< 2u, Signed, Interprocess > :
public core_arch_operations_msvc_arm< 2u, Signed, Interprocess, core_arch_operations< 2u, Signed, Interprocess > >
{
typedef msvc_arm_operations< 2u, Signed, operations< 2u, Signed > > base_type;
typedef core_arch_operations_msvc_arm< 2u, Signed, Interprocess, core_arch_operations< 2u, Signed, Interprocess > > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
@@ -370,7 +387,7 @@ struct operations< 2u, Signed > :
{
storage_type previous = expected, old_val;
switch (cas_common_order(success_order, failure_order))
switch (base_type::cas_common_order(success_order, failure_order))
{
case memory_order_relaxed:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16_RELAXED(&storage, desired, previous));
@@ -463,11 +480,11 @@ struct operations< 2u, Signed > :
}
};
template< bool Signed >
struct operations< 4u, Signed > :
public msvc_arm_operations< 4u, Signed, operations< 4u, Signed > >
template< bool Signed, bool Interprocess >
struct core_arch_operations< 4u, Signed, Interprocess > :
public core_arch_operations_msvc_arm< 4u, Signed, Interprocess, core_arch_operations< 4u, Signed, Interprocess > >
{
typedef msvc_arm_operations< 4u, Signed, operations< 4u, Signed > > base_type;
typedef core_arch_operations_msvc_arm< 4u, Signed, Interprocess, core_arch_operations< 4u, Signed, Interprocess > > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
@@ -535,7 +552,7 @@ struct operations< 4u, Signed > :
{
storage_type previous = expected, old_val;
switch (cas_common_order(success_order, failure_order))
switch (base_type::cas_common_order(success_order, failure_order))
{
case memory_order_relaxed:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_RELAXED(&storage, desired, previous));
@@ -628,11 +645,11 @@ struct operations< 4u, Signed > :
}
};
template< bool Signed >
struct operations< 8u, Signed > :
public msvc_arm_operations< 8u, Signed, operations< 8u, Signed > >
template< bool Signed, bool Interprocess >
struct core_arch_operations< 8u, Signed, Interprocess > :
public core_arch_operations_msvc_arm< 8u, Signed, Interprocess, core_arch_operations< 8u, Signed, Interprocess > >
{
typedef msvc_arm_operations< 8u, Signed, operations< 8u, Signed > > base_type;
typedef core_arch_operations_msvc_arm< 8u, Signed, Interprocess, core_arch_operations< 8u, Signed, Interprocess > > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
@@ -700,7 +717,7 @@ struct operations< 8u, Signed > :
{
storage_type previous = expected, old_val;
switch (cas_common_order(success_order, failure_order))
switch (base_type::cas_common_order(success_order, failure_order))
{
case memory_order_relaxed:
old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64_RELAXED(&storage, desired, previous));
@@ -793,21 +810,6 @@ struct operations< 8u, Signed > :
}
};
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
if (order != memory_order_relaxed)
msvc_arm_operations_base::hardware_full_fence();
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
} // namespace detail
} // namespace atomics
} // namespace boost
@@ -821,4 +823,6 @@ BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
#undef BOOST_ATOMIC_DETAIL_ARM_STORE32
#undef BOOST_ATOMIC_DETAIL_ARM_STORE64
#endif // BOOST_ATOMIC_DETAIL_OPS_MSVC_ARM_HPP_INCLUDED_
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_MSVC_ARM_HPP_INCLUDED_

View File

@@ -8,48 +8,43 @@
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_msvc_x86.hpp
* \file atomic/detail/core_arch_ops_msvc_x86.hpp
*
* This header contains implementation of the \c operations template.
* This header contains implementation of the \c core_arch_operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_MSVC_X86_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_MSVC_X86_HPP_INCLUDED_
#ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_MSVC_X86_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_MSVC_X86_HPP_INCLUDED_
#include <cstddef>
#include <boost/cstdint.hpp>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/intptr.hpp>
#include <boost/atomic/detail/interlocked.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#include <boost/atomic/detail/core_arch_operations_fwd.hpp>
#include <boost/atomic/detail/type_traits/make_signed.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/capabilities.hpp>
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
#include <boost/cstdint.hpp>
#include <boost/atomic/detail/ops_cas_based.hpp>
#include <boost/atomic/detail/cas_based_exchange.hpp>
#include <boost/atomic/detail/core_ops_cas_based.hpp>
#endif
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) && defined(__AVX__)
#include <emmintrin.h>
#include <boost/atomic/detail/string_ops.hpp>
#endif
#include <boost/atomic/detail/ops_msvc_common.hpp>
#if !defined(_M_IX86) && !(defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8) && defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16))
#include <boost/atomic/detail/ops_extending_cas_based.hpp>
#include <boost/atomic/detail/extending_cas_based_arithmetic.hpp>
#endif
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(BOOST_MSVC)
#pragma warning(push)
// frame pointer register 'ebx' modified by inline assembly code. See the note below.
#pragma warning(disable: 4731)
#endif
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_MFENCE)
extern "C" void _mm_mfence(void);
#if defined(BOOST_MSVC)
#pragma intrinsic(_mm_mfence)
#endif
#endif
namespace boost {
namespace atomics {
namespace detail {
@@ -67,25 +62,15 @@ namespace detail {
* Either move the eight-byte aligned types out of the function, or avoid using EBX.
*
* Since we have no way of knowing that the compiler uses FPO, we have to always save and restore ebx
* whenever we have to clobber it. Additionally, we disable warning C4731 above so that the compiler
* whenever we have to clobber it. Additionally, we disable warning C4731 in header.hpp so that the compiler
* doesn't spam about ebx use.
*/
struct msvc_x86_operations_base
struct core_arch_operations_msvc_x86_base
{
static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false;
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
{
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_MFENCE)
_mm_mfence();
#else
long tmp;
BOOST_ATOMIC_INTERLOCKED_EXCHANGE(&tmp, 0);
#endif
}
static BOOST_FORCEINLINE void fence_before(memory_order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
@@ -108,15 +93,16 @@ struct msvc_x86_operations_base
}
};
template< std::size_t Size, bool Signed, typename Derived >
struct msvc_x86_operations :
public msvc_x86_operations_base
template< std::size_t Size, bool Signed, bool Interprocess, typename Derived >
struct core_arch_operations_msvc_x86 :
public core_arch_operations_msvc_x86_base
{
typedef typename make_storage_type< Size >::type storage_type;
typedef typename make_storage_type< Size >::aligned aligned_storage_type;
typedef typename storage_traits< Size >::type storage_type;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = storage_traits< Size >::alignment;
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
@@ -162,11 +148,11 @@ struct msvc_x86_operations :
}
};
template< bool Signed >
struct operations< 4u, Signed > :
public msvc_x86_operations< 4u, Signed, operations< 4u, Signed > >
template< bool Signed, bool Interprocess >
struct core_arch_operations< 4u, Signed, Interprocess > :
public core_arch_operations_msvc_x86< 4u, Signed, Interprocess, core_arch_operations< 4u, Signed, Interprocess > >
{
typedef msvc_x86_operations< 4u, Signed, operations< 4u, Signed > > base_type;
typedef core_arch_operations_msvc_x86< 4u, Signed, Interprocess, core_arch_operations< 4u, Signed, Interprocess > > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
@@ -233,11 +219,11 @@ struct operations< 4u, Signed > :
#if defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8)
template< bool Signed >
struct operations< 1u, Signed > :
public msvc_x86_operations< 1u, Signed, operations< 1u, Signed > >
template< bool Signed, bool Interprocess >
struct core_arch_operations< 1u, Signed, Interprocess > :
public core_arch_operations_msvc_x86< 1u, Signed, Interprocess, core_arch_operations< 1u, Signed, Interprocess > >
{
typedef msvc_x86_operations< 1u, Signed, operations< 1u, Signed > > base_type;
typedef core_arch_operations_msvc_x86< 1u, Signed, Interprocess, core_arch_operations< 1u, Signed, Interprocess > > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
@@ -277,11 +263,11 @@ struct operations< 1u, Signed > :
#elif defined(_M_IX86)
template< bool Signed >
struct operations< 1u, Signed > :
public msvc_x86_operations< 1u, Signed, operations< 1u, Signed > >
template< bool Signed, bool Interprocess >
struct core_arch_operations< 1u, Signed, Interprocess > :
public core_arch_operations_msvc_x86< 1u, Signed, Interprocess, core_arch_operations< 1u, Signed, Interprocess > >
{
typedef msvc_x86_operations< 1u, Signed, operations< 1u, Signed > > base_type;
typedef core_arch_operations_msvc_x86< 1u, Signed, Interprocess, core_arch_operations< 1u, Signed, Interprocess > > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
@@ -398,9 +384,9 @@ struct operations< 1u, Signed > :
#else
template< bool Signed >
struct operations< 1u, Signed > :
public extending_cas_based_operations< operations< 4u, Signed >, 1u, Signed >
template< bool Signed, bool Interprocess >
struct core_arch_operations< 1u, Signed, Interprocess > :
public extending_cas_based_arithmetic< core_arch_operations< 4u, Signed, Interprocess >, 1u, Signed >
{
};
@@ -408,11 +394,11 @@ struct operations< 1u, Signed > :
#if defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16)
template< bool Signed >
struct operations< 2u, Signed > :
public msvc_x86_operations< 2u, Signed, operations< 2u, Signed > >
template< bool Signed, bool Interprocess >
struct core_arch_operations< 2u, Signed, Interprocess > :
public core_arch_operations_msvc_x86< 2u, Signed, Interprocess, core_arch_operations< 2u, Signed, Interprocess > >
{
typedef msvc_x86_operations< 2u, Signed, operations< 2u, Signed > > base_type;
typedef core_arch_operations_msvc_x86< 2u, Signed, Interprocess, core_arch_operations< 2u, Signed, Interprocess > > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
@@ -452,11 +438,11 @@ struct operations< 2u, Signed > :
#elif defined(_M_IX86)
template< bool Signed >
struct operations< 2u, Signed > :
public msvc_x86_operations< 2u, Signed, operations< 2u, Signed > >
template< bool Signed, bool Interprocess >
struct core_arch_operations< 2u, Signed, Interprocess > :
public core_arch_operations_msvc_x86< 2u, Signed, Interprocess, core_arch_operations< 2u, Signed, Interprocess > >
{
typedef msvc_x86_operations< 2u, Signed, operations< 2u, Signed > > base_type;
typedef core_arch_operations_msvc_x86< 2u, Signed, Interprocess, core_arch_operations< 2u, Signed, Interprocess > > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
@@ -573,9 +559,9 @@ struct operations< 2u, Signed > :
#else
template< bool Signed >
struct operations< 2u, Signed > :
public extending_cas_based_operations< operations< 4u, Signed >, 2u, Signed >
template< bool Signed, bool Interprocess >
struct core_arch_operations< 2u, Signed, Interprocess > :
public extending_cas_based_arithmetic< core_arch_operations< 4u, Signed, Interprocess >, 2u, Signed >
{
};
@@ -584,16 +570,17 @@ struct operations< 2u, Signed > :
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B)
template< bool Signed >
template< bool Signed, bool Interprocess >
struct msvc_dcas_x86
{
typedef typename make_storage_type< 8u >::type storage_type;
typedef typename make_storage_type< 8u >::aligned aligned_storage_type;
typedef typename storage_traits< 8u >::type storage_type;
static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = true;
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 8u;
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
// Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 3A, 8.1.1. Guaranteed Atomic Operations:
@@ -604,12 +591,12 @@ struct msvc_dcas_x86
// Luckily, the memory is almost always 8-byte aligned in our case because atomic<> uses 64 bit native types for storage and dynamic memory allocations
// have at least 8 byte alignment. The only unfortunate case is when atomic is placed on the stack and it is not 8-byte aligned (like on 32 bit Windows).
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
storage_type volatile* p = &storage;
if (((uint32_t)p & 0x00000007) == 0)
if (BOOST_LIKELY(order != memory_order_seq_cst && ((uintptr_t)p & 7u) == 0u))
{
#if defined(_M_IX86_FP) && _M_IX86_FP >= 2
#if defined(__AVX__)
@@ -665,7 +652,7 @@ struct msvc_dcas_x86
storage_type const volatile* p = &storage;
storage_type value;
if (((uint32_t)p & 0x00000007) == 0)
if (BOOST_LIKELY(((uintptr_t)p & 7u) == 0u))
{
#if defined(_M_IX86_FP) && _M_IX86_FP >= 2
#if defined(__AVX__)
@@ -783,19 +770,19 @@ struct msvc_dcas_x86
}
};
template< bool Signed >
struct operations< 8u, Signed > :
public cas_based_operations< msvc_dcas_x86< Signed > >
template< bool Signed, bool Interprocess >
struct core_arch_operations< 8u, Signed, Interprocess > :
public core_operations_cas_based< msvc_dcas_x86< Signed, Interprocess > >
{
};
#elif defined(_M_AMD64)
template< bool Signed >
struct operations< 8u, Signed > :
public msvc_x86_operations< 8u, Signed, operations< 8u, Signed > >
template< bool Signed, bool Interprocess >
struct core_arch_operations< 8u, Signed, Interprocess > :
public core_arch_operations_msvc_x86< 8u, Signed, Interprocess, core_arch_operations< 8u, Signed, Interprocess > >
{
typedef msvc_x86_operations< 8u, Signed, operations< 8u, Signed > > base_type;
typedef core_arch_operations_msvc_x86< 8u, Signed, Interprocess, core_arch_operations< 8u, Signed, Interprocess > > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
@@ -837,27 +824,51 @@ struct operations< 8u, Signed > :
#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
template< bool Signed >
template< bool Signed, bool Interprocess >
struct msvc_dcas_x86_64
{
typedef typename make_storage_type< 16u >::type storage_type;
typedef typename make_storage_type< 16u >::aligned aligned_storage_type;
typedef typename storage_traits< 16u >::type storage_type;
static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = true;
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 16u;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 16u;
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
#if defined(__AVX__)
if (BOOST_LIKELY(order != memory_order_seq_cst && (((uintptr_t)&storage) & 15u) == 0u))
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
__m128i value;
BOOST_ATOMIC_DETAIL_MEMCPY(&value, &v, sizeof(value));
_mm_store_si128(const_cast< __m128i* >(reinterpret_cast< volatile __m128i* >(&storage)), value);
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
return;
}
#endif // defined(__AVX__)
storage_type value = const_cast< storage_type& >(storage);
while (!BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE128(&storage, v, &value)) {}
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT
{
storage_type value = storage_type();
storage_type value;
#if defined(__AVX__)
if (BOOST_LIKELY((((uintptr_t)&storage) & 15u) == 0u))
{
__m128i v = _mm_load_si128(const_cast< const __m128i* >(reinterpret_cast< const volatile __m128i* >(&storage)));
BOOST_ATOMIC_DETAIL_MEMCPY(&value, &v, sizeof(value));
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
return value;
}
#endif // defined(__AVX__)
value = storage_type();
BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE128(&storage, value, &value);
return value;
}
@@ -875,34 +886,18 @@ struct msvc_dcas_x86_64
}
};
template< bool Signed >
struct operations< 16u, Signed > :
public cas_based_operations< cas_based_exchange< msvc_dcas_x86_64< Signed > > >
template< bool Signed, bool Interprocess >
struct core_arch_operations< 16u, Signed, Interprocess > :
public core_operations_cas_based< cas_based_exchange< msvc_dcas_x86_64< Signed, Interprocess > > >
{
};
#endif // defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
if (order == memory_order_seq_cst)
msvc_x86_operations_base::hardware_full_fence();
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
} // namespace detail
} // namespace atomics
} // namespace boost
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_OPS_MSVC_X86_HPP_INCLUDED_
#endif // BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_MSVC_X86_HPP_INCLUDED_

View File

@@ -0,0 +1,49 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/core_operations.hpp
*
* This header defines core atomic operations.
*/
#ifndef BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/platform.hpp>
#include <boost/atomic/detail/core_arch_operations.hpp>
#include <boost/atomic/detail/core_operations_fwd.hpp>
#if defined(BOOST_ATOMIC_DETAIL_CORE_BACKEND_HEADER)
#include BOOST_ATOMIC_DETAIL_CORE_BACKEND_HEADER(boost/atomic/detail/core_ops_)
#endif
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
//! Default specialization that falls back to architecture-specific implementation
template< std::size_t Size, bool Signed, bool Interprocess >
struct core_operations :
public core_arch_operations< Size, Signed, Interprocess >
{
};
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_HPP_INCLUDED_

View File

@@ -0,0 +1,195 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014, 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/core_operations_emulated.hpp
*
* This header contains lock pool-based implementation of the core atomic operations.
*/
#ifndef BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_EMULATED_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_EMULATED_HPP_INCLUDED_
#include <cstddef>
#include <boost/static_assert.hpp>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#include <boost/atomic/detail/core_operations_emulated_fwd.hpp>
#include <boost/atomic/detail/lock_pool.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
template< std::size_t Size, std::size_t Alignment, bool = Alignment >= storage_traits< Size >::native_alignment >
struct core_operations_emulated_base
{
typedef typename storage_traits< Size >::type storage_type;
};
template< std::size_t Size, std::size_t Alignment >
struct core_operations_emulated_base< Size, Alignment, false >
{
typedef buffer_storage< Size, Alignment > storage_type;
};
//! Emulated implementation of core atomic operations
template< std::size_t Size, std::size_t Alignment, bool Signed, bool Interprocess >
struct core_operations_emulated :
public core_operations_emulated_base< Size, Alignment >
{
typedef core_operations_emulated_base< Size, Alignment > base_type;
// Define storage_type to have alignment not greater than Alignment. This will allow operations to work with value_types
// that possibly have weaker alignment requirements than storage_traits< Size >::type would. This is important for atomic_ref<>.
// atomic<> will allow higher alignment requirement than its value_type.
// Note that storage_type should be an integral type, if possible, so that arithmetic and bitwise operations are possible.
typedef typename base_type::storage_type storage_type;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = Alignment >= storage_traits< Size >::alignment ? storage_traits< Size >::alignment : Alignment;
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false;
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = false;
typedef lock_pool::scoped_lock< storage_alignment > scoped_lock;
static void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
scoped_lock lock(&storage);
const_cast< storage_type& >(storage) = v;
}
static storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
scoped_lock lock(&storage);
return const_cast< storage_type const& >(storage);
}
static storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
scoped_lock lock(&storage);
storage_type old_val = s;
s += v;
return old_val;
}
static storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
scoped_lock lock(&storage);
storage_type old_val = s;
s -= v;
return old_val;
}
static storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
scoped_lock lock(&storage);
storage_type old_val = s;
s = v;
return old_val;
}
static bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
scoped_lock lock(&storage);
storage_type old_val = s;
const bool res = old_val == expected;
if (res)
s = desired;
expected = old_val;
return res;
}
static bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
{
// Note: This function is the exact copy of compare_exchange_strong. The reason we're not just forwarding the call
// is that MSVC-12 ICEs in this case.
BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
scoped_lock lock(&storage);
storage_type old_val = s;
const bool res = old_val == expected;
if (res)
s = desired;
expected = old_val;
return res;
}
static storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
scoped_lock lock(&storage);
storage_type old_val = s;
s &= v;
return old_val;
}
static storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
scoped_lock lock(&storage);
storage_type old_val = s;
s |= v;
return old_val;
}
static storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
scoped_lock lock(&storage);
storage_type old_val = s;
s ^= v;
return old_val;
}
static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
return !!exchange(storage, (storage_type)1, order);
}
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
store(storage, (storage_type)0, order);
}
};
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_EMULATED_HPP_INCLUDED_

View File

@@ -0,0 +1,38 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/core_operations_emulated_fwd.hpp
*
* This header forward-declares lock pool-based implementation of the core atomic operations.
*/
#ifndef BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_EMULATED_FWD_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_EMULATED_FWD_HPP_INCLUDED_
#include <cstddef>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
template< std::size_t Size, std::size_t Alignment, bool Signed, bool Interprocess >
struct core_operations_emulated;
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_EMULATED_FWD_HPP_INCLUDED_

View File

@@ -0,0 +1,38 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/core_operations_fwd.hpp
*
* This header contains forward declaration of the \c core_operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_FWD_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_FWD_HPP_INCLUDED_
#include <cstddef>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
template< std::size_t Size, bool Signed, bool Interprocess >
struct core_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_FWD_HPP_INCLUDED_

View File

@@ -6,17 +6,17 @@
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_cas_based.hpp
* \file atomic/detail/core_ops_cas_based.hpp
*
* This header contains CAS-based implementation of the \c operations template.
* This header contains CAS-based implementation of core atomic operations.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_CAS_BASED_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_CAS_BASED_HPP_INCLUDED_
#ifndef BOOST_ATOMIC_DETAIL_CORE_OPS_CAS_BASED_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CORE_OPS_CAS_BASED_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -27,22 +27,7 @@ namespace atomics {
namespace detail {
template< typename Base >
struct cas_based_exchange :
public Base
{
typedef typename Base::storage_type storage_type;
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type old_val;
atomics::detail::non_atomic_load(storage, old_val);
while (!Base::compare_exchange_weak(storage, old_val, v, order, memory_order_relaxed)) {}
return old_val;
}
};
template< typename Base >
struct cas_based_operations :
struct core_operations_cas_based :
public Base
{
typedef typename Base::storage_type storage_type;
@@ -104,4 +89,6 @@ struct cas_based_operations :
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPS_CAS_BASED_HPP_INCLUDED_
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_CORE_OPS_CAS_BASED_HPP_INCLUDED_

View File

@@ -0,0 +1,306 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014, 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/core_ops_gcc_atomic.hpp
*
* This header contains implementation of the \c core_operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_CORE_OPS_GCC_ATOMIC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CORE_OPS_GCC_ATOMIC_HPP_INCLUDED_
#include <cstddef>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#include <boost/atomic/detail/core_operations_fwd.hpp>
#include <boost/atomic/detail/core_arch_operations.hpp>
#include <boost/atomic/detail/capabilities.hpp>
#include <boost/atomic/detail/gcc_atomic_memory_order_utils.hpp>
#if BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT8_LOCK_FREE < BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE || BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE < BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE ||\
BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE < BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE || BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE < BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE
// There are platforms where we need to use larger storage types
#include <boost/atomic/detail/int_sizes.hpp>
#include <boost/atomic/detail/extending_cas_based_arithmetic.hpp>
#endif
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(__INTEL_COMPILER)
// This is used to suppress warning #32013 described in gcc_atomic_memory_order_utils.hpp
// for Intel Compiler.
// In debug builds the compiler does not inline any functions, so basically
// every atomic function call results in this warning. I don't know any other
// way to selectively disable just this one warning.
#pragma system_header
#endif
namespace boost {
namespace atomics {
namespace detail {
template< std::size_t Size, bool Signed, bool Interprocess >
struct core_operations_gcc_atomic
{
typedef typename storage_traits< Size >::type storage_type;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = storage_traits< Size >::alignment;
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false;
// Note: In the current implementation, core_operations_gcc_atomic are used only when the particularly sized __atomic
// intrinsics are always lock-free (i.e. the corresponding LOCK_FREE macro is 2). Therefore it is safe to
// always set is_always_lock_free to true here.
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
#if defined(BOOST_GCC) && BOOST_GCC < 100100 && (defined(__x86_64__) || defined(__i386__))
// gcc up to 10.1 generates mov + mfence for seq_cst stores, which is slower than xchg
if (order != memory_order_seq_cst)
__atomic_store_n(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
else
__atomic_exchange_n(&storage, v, __ATOMIC_SEQ_CST);
#else
__atomic_store_n(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
#endif
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
{
#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_RCPC)
// At least gcc 9.3 and clang 10 do not generate relaxed ldapr instructions that are available in ARMv8.3-RCPC extension.
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95751
typedef atomics::detail::core_arch_operations< storage_size, is_signed, is_interprocess > core_arch_operations;
return core_arch_operations::load(storage, order);
#else
return __atomic_load_n(&storage, atomics::detail::convert_memory_order_to_gcc(order));
#endif
}
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
return __atomic_fetch_add(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
}
static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
return __atomic_fetch_sub(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
}
static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
return __atomic_exchange_n(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
}
static BOOST_FORCEINLINE bool compare_exchange_strong(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
return __atomic_compare_exchange_n
(
&storage, &expected, desired, false,
atomics::detail::convert_memory_order_to_gcc(success_order),
atomics::detail::convert_memory_order_to_gcc(failure_order)
);
}
static BOOST_FORCEINLINE bool compare_exchange_weak(
storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
return __atomic_compare_exchange_n
(
&storage, &expected, desired, true,
atomics::detail::convert_memory_order_to_gcc(success_order),
atomics::detail::convert_memory_order_to_gcc(failure_order)
);
}
static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
return __atomic_fetch_and(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
}
static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
return __atomic_fetch_or(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
}
static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
return __atomic_fetch_xor(&storage, v, atomics::detail::convert_memory_order_to_gcc(order));
}
static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
return __atomic_test_and_set(&storage, atomics::detail::convert_memory_order_to_gcc(order));
}
static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
__atomic_clear(const_cast< storage_type* >(&storage), atomics::detail::convert_memory_order_to_gcc(order));
}
};
// We want to only enable __atomic* intrinsics when the corresponding BOOST_ATOMIC_DETAIL_GCC_ATOMIC_*_LOCK_FREE macro indicates
// the same or better lock-free guarantees as the BOOST_ATOMIC_*_LOCK_FREE macro. Otherwise, we want to leave core_operations
// unspecialized, so that core_arch_operations is used instead.
#if BOOST_ATOMIC_INT128_LOCK_FREE > 0 && BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE >= BOOST_ATOMIC_INT128_LOCK_FREE
template< bool Signed, bool Interprocess >
struct core_operations< 16u, Signed, Interprocess > :
public core_operations_gcc_atomic< 16u, Signed, Interprocess >
{
};
#endif
#if BOOST_ATOMIC_INT64_LOCK_FREE > 0
#if BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE >= BOOST_ATOMIC_INT64_LOCK_FREE
template< bool Signed, bool Interprocess >
struct core_operations< 8u, Signed, Interprocess > :
public core_operations_gcc_atomic< 8u, Signed, Interprocess >
{
};
#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE >= BOOST_ATOMIC_INT64_LOCK_FREE
template< bool Signed, bool Interprocess >
struct core_operations< 8u, Signed, Interprocess > :
public extending_cas_based_arithmetic< core_operations_gcc_atomic< 16u, Signed, Interprocess >, 8u, Signed >
{
};
#endif
#endif // BOOST_ATOMIC_INT64_LOCK_FREE > 0
#if BOOST_ATOMIC_INT32_LOCK_FREE > 0
#if BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE >= BOOST_ATOMIC_INT32_LOCK_FREE
template< bool Signed, bool Interprocess >
struct core_operations< 4u, Signed, Interprocess > :
public core_operations_gcc_atomic< 4u, Signed, Interprocess >
{
};
#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE >= BOOST_ATOMIC_INT32_LOCK_FREE
template< bool Signed, bool Interprocess >
struct core_operations< 4u, Signed, Interprocess > :
public extending_cas_based_arithmetic< core_operations_gcc_atomic< 8u, Signed, Interprocess >, 4u, Signed >
{
};
#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE >= BOOST_ATOMIC_INT32_LOCK_FREE
template< bool Signed, bool Interprocess >
struct core_operations< 8u, Signed, Interprocess > :
public extending_cas_based_arithmetic< core_operations_gcc_atomic< 16u, Signed, Interprocess >, 4u, Signed >
{
};
#endif
#endif // BOOST_ATOMIC_INT32_LOCK_FREE > 0
#if BOOST_ATOMIC_INT16_LOCK_FREE > 0
#if BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE >= BOOST_ATOMIC_INT16_LOCK_FREE
template< bool Signed, bool Interprocess >
struct core_operations< 2u, Signed, Interprocess > :
public core_operations_gcc_atomic< 2u, Signed, Interprocess >
{
};
#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE >= BOOST_ATOMIC_INT16_LOCK_FREE
template< bool Signed, bool Interprocess >
struct core_operations< 2u, Signed, Interprocess > :
public extending_cas_based_arithmetic< core_operations_gcc_atomic< 4u, Signed, Interprocess >, 2u, Signed >
{
};
#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE >= BOOST_ATOMIC_INT16_LOCK_FREE
template< bool Signed, bool Interprocess >
struct core_operations< 2u, Signed, Interprocess > :
public extending_cas_based_arithmetic< core_operations_gcc_atomic< 8u, Signed, Interprocess >, 2u, Signed >
{
};
#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE >= BOOST_ATOMIC_INT16_LOCK_FREE
template< bool Signed, bool Interprocess >
struct core_operations< 2u, Signed, Interprocess > :
public extending_cas_based_arithmetic< core_operations_gcc_atomic< 16u, Signed, Interprocess >, 2u, Signed >
{
};
#endif
#endif // BOOST_ATOMIC_INT16_LOCK_FREE > 0
#if BOOST_ATOMIC_INT8_LOCK_FREE > 0
#if BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT8_LOCK_FREE >= BOOST_ATOMIC_INT8_LOCK_FREE
template< bool Signed, bool Interprocess >
struct core_operations< 1u, Signed, Interprocess > :
public core_operations_gcc_atomic< 1u, Signed, Interprocess >
{
};
#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE >= BOOST_ATOMIC_INT8_LOCK_FREE
template< bool Signed, bool Interprocess >
struct core_operations< 1u, Signed, Interprocess > :
public extending_cas_based_arithmetic< core_operations_gcc_atomic< 2u, Signed, Interprocess >, 1u, Signed >
{
};
#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE >= BOOST_ATOMIC_INT8_LOCK_FREE
template< bool Signed, bool Interprocess >
struct core_operations< 1u, Signed, Interprocess > :
public extending_cas_based_arithmetic< core_operations_gcc_atomic< 4u, Signed, Interprocess >, 1u, Signed >
{
};
#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE >= BOOST_ATOMIC_INT8_LOCK_FREE
template< bool Signed, bool Interprocess >
struct core_operations< 1u, Signed, Interprocess > :
public extending_cas_based_arithmetic< core_operations_gcc_atomic< 8u, Signed, Interprocess >, 1u, Signed >
{
};
#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE >= BOOST_ATOMIC_INT8_LOCK_FREE
template< bool Signed, bool Interprocess >
struct core_operations< 1u, Signed, Interprocess > :
public extending_cas_based_arithmetic< core_operations_gcc_atomic< 16u, Signed, Interprocess >, 1u, Signed >
{
};
#endif
#endif // BOOST_ATOMIC_INT8_LOCK_FREE > 0
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_CORE_OPS_GCC_ATOMIC_HPP_INCLUDED_

View File

@@ -8,21 +8,23 @@
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_gcc_sync.hpp
* \file atomic/detail/core_ops_gcc_sync.hpp
*
* This header contains implementation of the \c operations template.
* This header contains implementation of the \c core_operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_SYNC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_GCC_SYNC_HPP_INCLUDED_
#ifndef BOOST_ATOMIC_DETAIL_CORE_OPS_GCC_SYNC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CORE_OPS_GCC_SYNC_HPP_INCLUDED_
#include <cstddef>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/detail/ops_extending_cas_based.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#include <boost/atomic/detail/core_operations_fwd.hpp>
#include <boost/atomic/detail/extending_cas_based_arithmetic.hpp>
#include <boost/atomic/detail/type_traits/integral_constant.hpp>
#include <boost/atomic/detail/capabilities.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -32,7 +34,7 @@ namespace boost {
namespace atomics {
namespace detail {
struct gcc_sync_operations_base
struct core_operations_gcc_sync_base
{
static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false;
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
@@ -56,30 +58,61 @@ struct gcc_sync_operations_base
}
};
template< std::size_t Size, bool Signed >
struct gcc_sync_operations :
public gcc_sync_operations_base
template< std::size_t Size, bool Signed, bool Interprocess >
struct core_operations_gcc_sync :
public core_operations_gcc_sync_base
{
typedef typename make_storage_type< Size >::type storage_type;
typedef typename make_storage_type< Size >::aligned aligned_storage_type;
typedef typename storage_traits< Size >::type storage_type;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = storage_traits< storage_size >::alignment;
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
// In general, we cannot guarantee atomicity of plain loads and stores of anything larger than a single byte on
// an arbitrary CPU architecture. However, all modern architectures seem to guarantee atomic loads and stores of
// suitably aligned objects of up to a pointer size. For larger objects we should probably use intrinsics to guarantee
// atomicity. If there appears an architecture where this doesn't hold, this threshold needs to be updated (patches are welcome).
typedef atomics::detail::integral_constant< bool, storage_size <= sizeof(void*) > plain_stores_loads_are_atomic;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
store(storage, v, order, plain_stores_loads_are_atomic());
}
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order, atomics::detail::true_type) BOOST_NOEXCEPT
{
fence_before_store(order);
storage = v;
fence_after_store(order);
}
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order, atomics::detail::false_type) BOOST_NOEXCEPT
{
exchange(storage, v, order);
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
{
return load(storage, order, plain_stores_loads_are_atomic());
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order, atomics::detail::true_type) BOOST_NOEXCEPT
{
storage_type v = storage;
fence_after_load(order);
return v;
}
static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order, atomics::detail::false_type) BOOST_NOEXCEPT
{
// Note: don't use fetch_add or other arithmetics here since storage_type may not be an arithmetic type.
storage_type expected = storage_type();
storage_type desired = expected;
// We don't care if CAS succeeds or not. If it does, it will just write the same value there was before.
return __sync_val_compare_and_swap(const_cast< storage_type volatile* >(&storage), expected, desired);
}
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
return __sync_fetch_and_add(&storage, v);
@@ -154,87 +187,77 @@ struct gcc_sync_operations :
};
#if BOOST_ATOMIC_INT8_LOCK_FREE > 0
template< bool Signed >
struct operations< 1u, Signed > :
template< bool Signed, bool Interprocess >
struct core_operations< 1u, Signed, Interprocess > :
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1)
public gcc_sync_operations< 1u, Signed >
public core_operations_gcc_sync< 1u, Signed, Interprocess >
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)
public extending_cas_based_operations< gcc_sync_operations< 2u, Signed >, 1u, Signed >
public extending_cas_based_arithmetic< core_operations_gcc_sync< 2u, Signed, Interprocess >, 1u, Signed >
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
public extending_cas_based_operations< gcc_sync_operations< 4u, Signed >, 1u, Signed >
public extending_cas_based_arithmetic< core_operations_gcc_sync< 4u, Signed, Interprocess >, 1u, Signed >
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
public extending_cas_based_operations< gcc_sync_operations< 8u, Signed >, 1u, Signed >
public extending_cas_based_arithmetic< core_operations_gcc_sync< 8u, Signed, Interprocess >, 1u, Signed >
#else
public extending_cas_based_operations< gcc_sync_operations< 16u, Signed >, 1u, Signed >
public extending_cas_based_arithmetic< core_operations_gcc_sync< 16u, Signed, Interprocess >, 1u, Signed >
#endif
{
};
#endif
#if BOOST_ATOMIC_INT16_LOCK_FREE > 0
template< bool Signed >
struct operations< 2u, Signed > :
template< bool Signed, bool Interprocess >
struct core_operations< 2u, Signed, Interprocess > :
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)
public gcc_sync_operations< 2u, Signed >
public core_operations_gcc_sync< 2u, Signed, Interprocess >
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
public extending_cas_based_operations< gcc_sync_operations< 4u, Signed >, 2u, Signed >
public extending_cas_based_arithmetic< core_operations_gcc_sync< 4u, Signed, Interprocess >, 2u, Signed >
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
public extending_cas_based_operations< gcc_sync_operations< 8u, Signed >, 2u, Signed >
public extending_cas_based_arithmetic< core_operations_gcc_sync< 8u, Signed, Interprocess >, 2u, Signed >
#else
public extending_cas_based_operations< gcc_sync_operations< 16u, Signed >, 2u, Signed >
public extending_cas_based_arithmetic< core_operations_gcc_sync< 16u, Signed, Interprocess >, 2u, Signed >
#endif
{
};
#endif
#if BOOST_ATOMIC_INT32_LOCK_FREE > 0
template< bool Signed >
struct operations< 4u, Signed > :
template< bool Signed, bool Interprocess >
struct core_operations< 4u, Signed, Interprocess > :
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
public gcc_sync_operations< 4u, Signed >
public core_operations_gcc_sync< 4u, Signed, Interprocess >
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
public extending_cas_based_operations< gcc_sync_operations< 8u, Signed >, 4u, Signed >
public extending_cas_based_arithmetic< core_operations_gcc_sync< 8u, Signed, Interprocess >, 4u, Signed >
#else
public extending_cas_based_operations< gcc_sync_operations< 16u, Signed >, 4u, Signed >
public extending_cas_based_arithmetic< core_operations_gcc_sync< 16u, Signed, Interprocess >, 4u, Signed >
#endif
{
};
#endif
#if BOOST_ATOMIC_INT64_LOCK_FREE > 0
template< bool Signed >
struct operations< 8u, Signed > :
template< bool Signed, bool Interprocess >
struct core_operations< 8u, Signed, Interprocess > :
#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
public gcc_sync_operations< 8u, Signed >
public core_operations_gcc_sync< 8u, Signed, Interprocess >
#else
public extending_cas_based_operations< gcc_sync_operations< 16u, Signed >, 8u, Signed >
public extending_cas_based_arithmetic< core_operations_gcc_sync< 16u, Signed, Interprocess >, 8u, Signed >
#endif
{
};
#endif
#if BOOST_ATOMIC_INT128_LOCK_FREE > 0
template< bool Signed >
struct operations< 16u, Signed > :
public gcc_sync_operations< 16u, Signed >
template< bool Signed, bool Interprocess >
struct core_operations< 16u, Signed, Interprocess > :
public core_operations_gcc_sync< 16u, Signed, Interprocess >
{
};
#endif
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__sync_synchronize();
}
BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("" ::: "memory");
}
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_SYNC_HPP_INCLUDED_
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_CORE_OPS_GCC_SYNC_HPP_INCLUDED_

View File

@@ -10,22 +10,24 @@
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_linux_arm.hpp
* \file atomic/detail/core_ops_linux_arm.hpp
*
* This header contains implementation of the \c operations template.
* This header contains implementation of the \c core_operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_LINUX_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_LINUX_ARM_HPP_INCLUDED_
#ifndef BOOST_ATOMIC_DETAIL_CORE_OPS_LINUX_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CORE_OPS_LINUX_ARM_HPP_INCLUDED_
#include <cstddef>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/ops_cas_based.hpp>
#include <boost/atomic/detail/ops_extending_cas_based.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#include <boost/atomic/detail/core_operations_fwd.hpp>
#include <boost/atomic/detail/core_ops_cas_based.hpp>
#include <boost/atomic/detail/cas_based_exchange.hpp>
#include <boost/atomic/detail/extending_cas_based_arithmetic.hpp>
#include <boost/atomic/detail/fence_operations.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -44,6 +46,8 @@ namespace detail {
// this facility is slightly slower than inline assembler would be, but much
// faster than a system call.
//
// https://lwn.net/Articles/314561/
//
// While this emulated CAS is "strong" in the sense that it does not fail
// "spuriously" (i.e.: it never fails to perform the exchange when the value
// found equals the value expected), it does not return the found value on
@@ -64,37 +68,32 @@ struct linux_arm_cas_base
static BOOST_FORCEINLINE void fence_before_store(memory_order order) BOOST_NOEXCEPT
{
if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u)
hardware_full_fence();
fence_operations::hardware_full_fence();
}
static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT
{
if (order == memory_order_seq_cst)
hardware_full_fence();
fence_operations::hardware_full_fence();
}
static BOOST_FORCEINLINE void fence_after_load(memory_order order) BOOST_NOEXCEPT
{
if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
hardware_full_fence();
}
static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
{
typedef void (*kernel_dmb_t)(void);
((kernel_dmb_t)0xffff0fa0)();
fence_operations::hardware_full_fence();
}
};
template< bool Signed >
template< bool Signed, bool Interprocess >
struct linux_arm_cas :
public linux_arm_cas_base
{
typedef typename make_storage_type< 4u >::type storage_type;
typedef typename make_storage_type< 4u >::aligned aligned_storage_type;
typedef typename storage_traits< 4u >::type storage_type;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 4u;
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
@@ -143,38 +142,28 @@ struct linux_arm_cas :
}
};
template< bool Signed >
struct operations< 1u, Signed > :
public extending_cas_based_operations< cas_based_operations< cas_based_exchange< linux_arm_cas< Signed > > >, 1u, Signed >
template< bool Signed, bool Interprocess >
struct core_operations< 1u, Signed, Interprocess > :
public extending_cas_based_arithmetic< core_operations_cas_based< cas_based_exchange< linux_arm_cas< Signed, Interprocess > > >, 1u, Signed >
{
};
template< bool Signed >
struct operations< 2u, Signed > :
public extending_cas_based_operations< cas_based_operations< cas_based_exchange< linux_arm_cas< Signed > > >, 2u, Signed >
template< bool Signed, bool Interprocess >
struct core_operations< 2u, Signed, Interprocess > :
public extending_cas_based_arithmetic< core_operations_cas_based< cas_based_exchange< linux_arm_cas< Signed, Interprocess > > >, 2u, Signed >
{
};
template< bool Signed >
struct operations< 4u, Signed > :
public cas_based_operations< cas_based_exchange< linux_arm_cas< Signed > > >
template< bool Signed, bool Interprocess >
struct core_operations< 4u, Signed, Interprocess > :
public core_operations_cas_based< cas_based_exchange< linux_arm_cas< Signed, Interprocess > > >
{
};
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
linux_arm_cas_base::hardware_full_fence();
}
BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("" ::: "memory");
}
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPS_LINUX_ARM_HPP_INCLUDED_
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_CORE_OPS_LINUX_ARM_HPP_INCLUDED_

View File

@@ -8,9 +8,9 @@
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_windows.hpp
* \file atomic/detail/core_ops_windows.hpp
*
* This header contains implementation of the \c operations template.
* This header contains implementation of the \c core_operations template.
*
* This implementation is the most basic version for Windows. It should
* work for any non-MSVC-like compilers as long as there are Interlocked WinAPI
@@ -20,19 +20,19 @@
* versions based on compiler intrinsics.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_WINDOWS_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_WINDOWS_HPP_INCLUDED_
#ifndef BOOST_ATOMIC_DETAIL_CORE_OPS_WINDOWS_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_CORE_OPS_WINDOWS_HPP_INCLUDED_
#include <cstddef>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/interlocked.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/operations_fwd.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#include <boost/atomic/detail/core_operations_fwd.hpp>
#include <boost/atomic/detail/type_traits/make_signed.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/ops_msvc_common.hpp>
#include <boost/atomic/detail/ops_extending_cas_based.hpp>
#include <boost/atomic/detail/extending_cas_based_arithmetic.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -42,17 +42,11 @@ namespace boost {
namespace atomics {
namespace detail {
struct windows_operations_base
struct core_operations_windows_base
{
static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false;
static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
{
long tmp;
BOOST_ATOMIC_INTERLOCKED_EXCHANGE(&tmp, 0);
}
static BOOST_FORCEINLINE void fence_before(memory_order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
@@ -64,15 +58,16 @@ struct windows_operations_base
}
};
template< std::size_t Size, bool Signed, typename Derived >
struct windows_operations :
public windows_operations_base
template< std::size_t Size, bool Signed, bool Interprocess, typename Derived >
struct core_operations_windows :
public core_operations_windows_base
{
typedef typename make_storage_type< Size >::type storage_type;
typedef typename make_storage_type< Size >::aligned aligned_storage_type;
typedef typename storage_traits< Size >::type storage_type;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size;
static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = storage_traits< Size >::alignment;
static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
@@ -107,11 +102,11 @@ struct windows_operations :
}
};
template< bool Signed >
struct operations< 4u, Signed > :
public windows_operations< 4u, Signed, operations< 4u, Signed > >
template< bool Signed, bool Interprocess >
struct core_operations< 4u, Signed, bool Interprocess > :
public core_operations_windows< 4u, Signed, Interprocess, core_operations< 4u, Signed, Interprocess > >
{
typedef windows_operations< 4u, Signed, operations< 4u, Signed > > base_type;
typedef core_operations_windows< 4u, Signed, Interprocess, core_operations< 4u, Signed, Interprocess > > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
@@ -185,34 +180,22 @@ struct operations< 4u, Signed > :
}
};
template< bool Signed >
struct operations< 1u, Signed > :
public extending_cas_based_operations< operations< 4u, Signed >, 1u, Signed >
template< bool Signed, bool Interprocess >
struct core_operations< 1u, Signed, Interprocess > :
public extending_cas_based_arithmetic< core_operations< 4u, Signed, Interprocess >, 1u, Signed >
{
};
template< bool Signed >
struct operations< 2u, Signed > :
public extending_cas_based_operations< operations< 4u, Signed >, 2u, Signed >
template< bool Signed, bool Interprocess >
struct core_operations< 2u, Signed, Interprocess > :
public extending_cas_based_arithmetic< core_operations< 4u, Signed, Interprocess >, 2u, Signed >
{
};
BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
if (order == memory_order_seq_cst)
windows_operations_base::hardware_full_fence();
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPS_WINDOWS_HPP_INCLUDED_
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_CORE_OPS_WINDOWS_HPP_INCLUDED_

View File

@@ -6,19 +6,20 @@
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/ops_extending_cas_based.hpp
* \file atomic/detail/extending_cas_based_arithmetic.hpp
*
* This header contains a boilerplate of the \c operations template implementation that requires sign/zero extension in arithmetic operations.
* This header contains a boilerplate of core atomic operations that require sign/zero extension in arithmetic operations.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPS_EXTENDING_CAS_BASED_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPS_EXTENDING_CAS_BASED_HPP_INCLUDED_
#ifndef BOOST_ATOMIC_DETAIL_EXTENDING_CAS_BASED_ARITHMETIC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_EXTENDING_CAS_BASED_ARITHMETIC_HPP_INCLUDED_
#include <cstddef>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/integral_extend.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#include <boost/atomic/detail/integral_conversions.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -29,11 +30,11 @@ namespace atomics {
namespace detail {
template< typename Base, std::size_t Size, bool Signed >
struct extending_cas_based_operations :
struct extending_cas_based_arithmetic :
public Base
{
typedef typename Base::storage_type storage_type;
typedef typename make_storage_type< Size >::type emulated_storage_type;
typedef typename storage_traits< Size >::type emulated_storage_type;
static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
@@ -66,4 +67,6 @@ struct extending_cas_based_operations :
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPS_EXTENDING_CAS_BASED_HPP_INCLUDED_
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_EXTENDING_CAS_BASED_ARITHMETIC_HPP_INCLUDED_

View File

@@ -16,6 +16,7 @@
#include <cstddef>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -25,11 +26,13 @@ namespace boost {
namespace atomics {
namespace detail {
template< typename Base, typename Value, std::size_t Size, bool = Base::is_always_lock_free >
template< typename Base, typename Value = typename Base::value_type, std::size_t Size = sizeof(typename Base::storage_type), bool = Base::is_always_lock_free >
struct extra_fp_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_EXTRA_FP_OPERATIONS_FWD_HPP_INCLUDED_

View File

@@ -15,11 +15,12 @@
#define BOOST_ATOMIC_DETAIL_EXTRA_FP_OPS_EMULATED_HPP_INCLUDED_
#include <cstddef>
#include <boost/static_assert.hpp>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/bitwise_fp_cast.hpp>
#include <boost/atomic/detail/extra_fp_operations_fwd.hpp>
#include <boost/atomic/detail/lockpool.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -29,49 +30,54 @@ namespace boost {
namespace atomics {
namespace detail {
//! Generic implementation of extra floating point operations
//! Emulated implementation of extra floating point operations
template< typename Base, typename Value, std::size_t Size >
struct emulated_extra_fp_operations :
struct extra_fp_operations_emulated :
public Base
{
typedef Base base_type;
typedef typename base_type::storage_type storage_type;
typedef Value value_type;
typedef typename base_type::scoped_lock scoped_lock;
static BOOST_FORCEINLINE value_type fetch_negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
static value_type fetch_negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
scoped_lock lock(&storage);
value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s);
value_type new_val = -old_val;
s = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
return old_val;
}
static BOOST_FORCEINLINE value_type negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
static value_type negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
scoped_lock lock(&storage);
value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s);
value_type new_val = -old_val;
s = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
return new_val;
}
static BOOST_FORCEINLINE value_type add(storage_type volatile& storage, value_type v, memory_order) BOOST_NOEXCEPT
static value_type add(storage_type volatile& storage, value_type v, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
scoped_lock lock(&storage);
value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s);
value_type new_val = old_val + v;
s = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
return new_val;
}
static BOOST_FORCEINLINE value_type sub(storage_type volatile& storage, value_type v, memory_order) BOOST_NOEXCEPT
static value_type sub(storage_type volatile& storage, value_type v, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
scoped_lock lock(&storage);
value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s);
value_type new_val = old_val - v;
s = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
@@ -80,23 +86,26 @@ struct emulated_extra_fp_operations :
static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
fetch_negate(storage, order);
}
static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
base_type::fetch_add(storage, v, order);
}
static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
base_type::fetch_sub(storage, v, order);
}
};
template< typename Base, typename Value, std::size_t Size >
struct extra_fp_operations< Base, Value, Size, false > :
public emulated_extra_fp_operations< Base, Value, Size >
public extra_fp_operations_emulated< Base, Value, Size >
{
};
@@ -104,4 +113,6 @@ struct extra_fp_operations< Base, Value, Size, false > :
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_EXTRA_FP_OPS_EMULATED_HPP_INCLUDED_

View File

@@ -18,16 +18,17 @@
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/bitwise_fp_cast.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#include <boost/atomic/detail/extra_fp_operations_fwd.hpp>
#include <boost/atomic/detail/type_traits/is_iec559.hpp>
#include <boost/atomic/detail/type_traits/is_integral.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(BOOST_GCC) && (BOOST_GCC+0) >= 60000
#if defined(BOOST_GCC) && BOOST_GCC >= 60000
#pragma GCC diagnostic push
// ignoring attributes on template argument X - this warning is because we need to pass storage_type as a template argument; no problem in this case
#pragma GCC diagnostic ignored "-Wignored-attributes"
@@ -46,7 +47,7 @@ template<
, bool = atomics::detail::is_iec559< Value >::value && atomics::detail::is_integral< typename Base::storage_type >::value
#endif
>
struct generic_extra_fp_negate :
struct extra_fp_negate_generic :
public Base
{
typedef Base base_type;
@@ -93,7 +94,7 @@ struct generic_extra_fp_negate :
//! Negate implementation for IEEE 754 / IEC 559 floating point types. We leverage the fact that the sign bit is the most significant bit in the value.
template< typename Base, typename Value, std::size_t Size >
struct generic_extra_fp_negate< Base, Value, Size, true > :
struct extra_fp_negate_generic< Base, Value, Size, true > :
public Base
{
typedef Base base_type;
@@ -101,7 +102,7 @@ struct generic_extra_fp_negate< Base, Value, Size, true > :
typedef Value value_type;
//! The mask with only one sign bit set to 1
static BOOST_CONSTEXPR_OR_CONST storage_type sign_mask = static_cast< storage_type >(1u) << (atomics::detail::value_sizeof< value_type >::value * 8u - 1u);
static BOOST_CONSTEXPR_OR_CONST storage_type sign_mask = static_cast< storage_type >(1u) << (atomics::detail::value_size_of< value_type >::value * 8u - 1u);
static BOOST_FORCEINLINE value_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
@@ -123,10 +124,10 @@ struct generic_extra_fp_negate< Base, Value, Size, true > :
//! Generic implementation of floating point operations
template< typename Base, typename Value, std::size_t Size >
struct generic_extra_fp_operations :
public generic_extra_fp_negate< Base, Value, Size >
struct extra_fp_operations_generic :
public extra_fp_negate_generic< Base, Value, Size >
{
typedef generic_extra_fp_negate< Base, Value, Size > base_type;
typedef extra_fp_negate_generic< Base, Value, Size > base_type;
typedef typename base_type::storage_type storage_type;
typedef Value value_type;
@@ -174,7 +175,7 @@ struct generic_extra_fp_operations :
// Default extra_fp_operations template definition will be used unless specialized for a specific platform
template< typename Base, typename Value, std::size_t Size >
struct extra_fp_operations< Base, Value, Size, true > :
public generic_extra_fp_operations< Base, Value, Size >
public extra_fp_operations_generic< Base, Value, Size >
{
};
@@ -182,8 +183,10 @@ struct extra_fp_operations< Base, Value, Size, true > :
} // namespace atomics
} // namespace boost
#if defined(BOOST_GCC) && (BOOST_GCC+0) >= 60000
#if defined(BOOST_GCC) && BOOST_GCC >= 60000
#pragma GCC diagnostic pop
#endif
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_FP_OPS_GENERIC_HPP_INCLUDED_

View File

@@ -16,6 +16,7 @@
#include <cstddef>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -25,11 +26,13 @@ namespace boost {
namespace atomics {
namespace detail {
template< typename Base, std::size_t Size, bool Signed, bool = Base::is_always_lock_free >
template< typename Base, std::size_t Size = sizeof(typename Base::storage_type), bool Signed = Base::is_signed, bool = Base::is_always_lock_free >
struct extra_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPERATIONS_FWD_HPP_INCLUDED_

View File

@@ -15,115 +15,120 @@
#define BOOST_ATOMIC_DETAIL_EXTRA_OPS_EMULATED_HPP_INCLUDED_
#include <cstddef>
#include <boost/static_assert.hpp>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#include <boost/atomic/detail/extra_operations_fwd.hpp>
#include <boost/atomic/detail/lockpool.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(BOOST_MSVC)
#pragma warning(push)
// unary minus operator applied to unsigned type, result still unsigned
#pragma warning(disable: 4146)
#endif
namespace boost {
namespace atomics {
namespace detail {
//! Generic implementation of extra operations
//! Emulated implementation of extra operations
template< typename Base, std::size_t Size, bool Signed >
struct emulated_extra_operations :
struct extra_operations_emulated :
public Base
{
typedef Base base_type;
typedef typename base_type::storage_type storage_type;
typedef typename base_type::scoped_lock scoped_lock;
static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
static storage_type fetch_negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
scoped_lock lock(&storage);
storage_type old_val = s;
s = static_cast< storage_type >(-old_val);
return old_val;
}
static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
static storage_type negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
scoped_lock lock(&storage);
storage_type new_val = static_cast< storage_type >(-s);
s = new_val;
return new_val;
}
static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
static storage_type add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
scoped_lock lock(&storage);
storage_type new_val = s;
new_val += v;
s = new_val;
return new_val;
}
static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
static storage_type sub(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
scoped_lock lock(&storage);
storage_type new_val = s;
new_val -= v;
s = new_val;
return new_val;
}
static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
static storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
scoped_lock lock(&storage);
storage_type new_val = s;
new_val &= v;
s = new_val;
return new_val;
}
static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
static storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
scoped_lock lock(&storage);
storage_type new_val = s;
new_val |= v;
s = new_val;
return new_val;
}
static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
static storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
scoped_lock lock(&storage);
storage_type new_val = s;
new_val ^= v;
s = new_val;
return new_val;
}
static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
static storage_type fetch_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
scoped_lock lock(&storage);
storage_type old_val = s;
s = static_cast< storage_type >(~old_val);
return old_val;
}
static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
static storage_type bitwise_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
scoped_lock lock(&storage);
storage_type new_val = static_cast< storage_type >(~s);
s = new_val;
return new_val;
@@ -131,99 +136,116 @@ struct emulated_extra_operations :
static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
Base::fetch_add(storage, v, order);
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
base_type::fetch_add(storage, v, order);
}
static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
Base::fetch_sub(storage, v, order);
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
base_type::fetch_sub(storage, v, order);
}
static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
fetch_negate(storage, order);
}
static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
Base::fetch_and(storage, v, order);
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
base_type::fetch_and(storage, v, order);
}
static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
Base::fetch_or(storage, v, order);
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
base_type::fetch_or(storage, v, order);
}
static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
Base::fetch_xor(storage, v, order);
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
base_type::fetch_xor(storage, v, order);
}
static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
fetch_complement(storage, order);
}
static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
return !!add(storage, v, order);
}
static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
return !!sub(storage, v, order);
}
static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
return !!negate(storage, order);
}
static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
return !!bitwise_and(storage, v, order);
}
static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
return !!bitwise_or(storage, v, order);
}
static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
return !!bitwise_xor(storage, v, order);
}
static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
return !!bitwise_complement(storage, order);
}
static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type mask = static_cast< storage_type >(static_cast< storage_type >(1u) << bit_number);
storage_type old_val = Base::fetch_or(storage, mask, order);
storage_type old_val = base_type::fetch_or(storage, mask, order);
return !!(old_val & mask);
}
static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type mask = static_cast< storage_type >(static_cast< storage_type >(1u) << bit_number);
storage_type old_val = Base::fetch_and(storage, ~mask, order);
storage_type old_val = base_type::fetch_and(storage, ~mask, order);
return !!(old_val & mask);
}
static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type mask = static_cast< storage_type >(static_cast< storage_type >(1u) << bit_number);
storage_type old_val = Base::fetch_xor(storage, mask, order);
storage_type old_val = base_type::fetch_xor(storage, mask, order);
return !!(old_val & mask);
}
};
template< typename Base, std::size_t Size, bool Signed >
struct extra_operations< Base, Size, Signed, false > :
public emulated_extra_operations< Base, Size, Signed >
public extra_operations_emulated< Base, Size, Signed >
{
};
@@ -231,8 +253,6 @@ struct extra_operations< Base, Size, Signed, false > :
} // namespace atomics
} // namespace boost
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_EMULATED_HPP_INCLUDED_

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -17,11 +17,13 @@
#include <cstddef>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#include <boost/atomic/detail/extra_operations_fwd.hpp>
#include <boost/atomic/detail/extra_ops_generic.hpp>
#include <boost/atomic/detail/ops_gcc_ppc_common.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/gcc_ppc_asm_common.hpp>
#include <boost/atomic/detail/capabilities.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -32,7 +34,7 @@ namespace atomics {
namespace detail {
template< typename Base >
struct gcc_ppc_extra_operations_common :
struct extra_operations_gcc_ppc_common :
public Base
{
typedef Base base_type;
@@ -85,192 +87,192 @@ struct gcc_ppc_extra_operations_common :
};
template< typename Base, std::size_t Size, bool Signed >
struct gcc_ppc_extra_operations;
struct extra_operations_gcc_ppc;
#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX)
template< typename Base, bool Signed >
struct gcc_ppc_extra_operations< Base, 1u, Signed > :
public generic_extra_operations< Base, 1u, Signed >
struct extra_operations_gcc_ppc< Base, 1u, Signed > :
public extra_operations_generic< Base, 1u, Signed >
{
typedef generic_extra_operations< Base, 1u, Signed > base_type;
typedef extra_operations_generic< Base, 1u, Signed > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
storage_type original, result;
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lbarx %0,%y2\n\t"
"neg %1,%0\n\t"
"stbcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
storage_type original, result;
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lbarx %0,%y2\n\t"
"neg %1,%0\n\t"
"stbcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lbarx %0,%y2\n\t"
"add %1,%0,%3\n\t"
"stbcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lbarx %0,%y2\n\t"
"sub %1,%0,%3\n\t"
"stbcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lbarx %0,%y2\n\t"
"and %1,%0,%3\n\t"
"stbcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lbarx %0,%y2\n\t"
"or %1,%0,%3\n\t"
"stbcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lbarx %0,%y2\n\t"
"xor %1,%0,%3\n\t"
"stbcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
storage_type original, result;
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lbarx %0,%y2\n\t"
"nor %1,%0,%0\n\t"
"stbcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
storage_type original, result;
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lbarx %0,%y2\n\t"
"nor %1,%0,%0\n\t"
"stbcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
};
template< typename Base, bool Signed >
struct extra_operations< Base, 1u, Signed, true > :
public gcc_ppc_extra_operations_common< gcc_ppc_extra_operations< Base, 1u, Signed > >
public extra_operations_gcc_ppc_common< extra_operations_gcc_ppc< Base, 1u, Signed > >
{
};
@@ -279,180 +281,180 @@ struct extra_operations< Base, 1u, Signed, true > :
#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX)
template< typename Base, bool Signed >
struct gcc_ppc_extra_operations< Base, 2u, Signed > :
public generic_extra_operations< Base, 2u, Signed >
struct extra_operations_gcc_ppc< Base, 2u, Signed > :
public extra_operations_generic< Base, 2u, Signed >
{
typedef generic_extra_operations< Base, 2u, Signed > base_type;
typedef extra_operations_generic< Base, 2u, Signed > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
storage_type original, result;
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lharx %0,%y2\n\t"
"neg %1,%0\n\t"
"sthcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
storage_type original, result;
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lharx %0,%y2\n\t"
"neg %1,%0\n\t"
"sthcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lharx %0,%y2\n\t"
"add %1,%0,%3\n\t"
"sthcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lharx %0,%y2\n\t"
"sub %1,%0,%3\n\t"
"sthcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lharx %0,%y2\n\t"
"and %1,%0,%3\n\t"
"sthcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lharx %0,%y2\n\t"
"or %1,%0,%3\n\t"
"sthcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lharx %0,%y2\n\t"
"xor %1,%0,%3\n\t"
"sthcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
storage_type original, result;
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lharx %0,%y2\n\t"
"nor %1,%0,%0\n\t"
"sthcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
storage_type original, result;
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lharx %0,%y2\n\t"
"nor %1,%0,%0\n\t"
"sthcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
};
@@ -460,374 +462,374 @@ struct gcc_ppc_extra_operations< Base, 2u, Signed > :
#endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX)
template< typename Base, bool Signed >
struct gcc_ppc_extra_operations< Base, 4u, Signed > :
public generic_extra_operations< Base, 4u, Signed >
struct extra_operations_gcc_ppc< Base, 4u, Signed > :
public extra_operations_generic< Base, 4u, Signed >
{
typedef generic_extra_operations< Base, 4u, Signed > base_type;
typedef extra_operations_generic< Base, 4u, Signed > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
storage_type original, result;
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"neg %1,%0\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
storage_type original, result;
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"neg %1,%0\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"add %1,%0,%3\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"sub %1,%0,%3\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"and %1,%0,%3\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"or %1,%0,%3\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"xor %1,%0,%3\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
storage_type original, result;
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"nor %1,%0,%0\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
storage_type original, result;
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"lwarx %0,%y2\n\t"
"nor %1,%0,%0\n\t"
"stwcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
};
template< typename Base, bool Signed >
struct extra_operations< Base, 4u, Signed, true > :
public gcc_ppc_extra_operations_common< gcc_ppc_extra_operations< Base, 4u, Signed > >
public extra_operations_gcc_ppc_common< extra_operations_gcc_ppc< Base, 4u, Signed > >
{
};
#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX)
template< typename Base, bool Signed >
struct gcc_ppc_extra_operations< Base, 8u, Signed > :
public generic_extra_operations< Base, 8u, Signed >
struct extra_operations_gcc_ppc< Base, 8u, Signed > :
public extra_operations_generic< Base, 8u, Signed >
{
typedef generic_extra_operations< Base, 8u, Signed > base_type;
typedef extra_operations_generic< Base, 8u, Signed > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
storage_type original, result;
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"ldarx %0,%y2\n\t"
"neg %1,%0\n\t"
"stdcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
storage_type original, result;
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"ldarx %0,%y2\n\t"
"neg %1,%0\n\t"
"stdcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"ldarx %0,%y2\n\t"
"add %1,%0,%3\n\t"
"stdcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"ldarx %0,%y2\n\t"
"sub %1,%0,%3\n\t"
"stdcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"ldarx %0,%y2\n\t"
"and %1,%0,%3\n\t"
"stdcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"ldarx %0,%y2\n\t"
"or %1,%0,%3\n\t"
"stdcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
storage_type original, result;
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"ldarx %0,%y2\n\t"
"xor %1,%0,%3\n\t"
"stdcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
: "b" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
storage_type original, result;
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"ldarx %0,%y2\n\t"
"nor %1,%0,%0\n\t"
"stdcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return original;
}
static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
gcc_ppc_operations_base::fence_before(order);
core_arch_operations_gcc_ppc_base::fence_before(order);
storage_type original, result;
__asm__ __volatile__
(
"1:\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1")
"ldarx %0,%y2\n\t"
"nor %1,%0,%0\n\t"
"stdcx. %1,%y2\n\t"
"bne- 1b\n\t"
BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
: "=&b" (original), "=&b" (result), "+Z" (storage)
:
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
);
gcc_ppc_operations_base::fence_after(order);
core_arch_operations_gcc_ppc_base::fence_after(order);
return result;
}
};
template< typename Base, bool Signed >
struct extra_operations< Base, 8u, Signed, true > :
public gcc_ppc_extra_operations_common< gcc_ppc_extra_operations< Base, 8u, Signed > >
public extra_operations_gcc_ppc_common< extra_operations_gcc_ppc< Base, 8u, Signed > >
{
};
@@ -837,4 +839,6 @@ struct extra_operations< Base, 8u, Signed, true > :
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_ARM_PPC_INCLUDED_

View File

@@ -15,11 +15,13 @@
#define BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_X86_HPP_INCLUDED_
#include <cstddef>
#include <boost/cstdint.hpp>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#include <boost/atomic/detail/extra_operations_fwd.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/extra_ops_generic.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -29,103 +31,13 @@ namespace boost {
namespace atomics {
namespace detail {
template< typename Base >
struct gcc_x86_extra_operations_common :
public Base
{
typedef Base base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(Base::fetch_add(storage, v, order) + v);
}
static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
{
return static_cast< storage_type >(Base::fetch_sub(storage, v, order) - v);
}
static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT
{
bool res;
#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
__asm__ __volatile__
(
"lock; bts %[bit_number], %[storage]\n\t"
: [storage] "+m" (storage), [result] "=@ccc" (res)
: [bit_number] "Kq" (bit_number)
: "memory"
);
#else
__asm__ __volatile__
(
"lock; bts %[bit_number], %[storage]\n\t"
"setc %[result]\n\t"
: [storage] "+m" (storage), [result] "=q" (res)
: [bit_number] "Kq" (bit_number)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#endif
return res;
}
static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT
{
bool res;
#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
__asm__ __volatile__
(
"lock; btr %[bit_number], %[storage]\n\t"
: [storage] "+m" (storage), [result] "=@ccc" (res)
: [bit_number] "Kq" (bit_number)
: "memory"
);
#else
__asm__ __volatile__
(
"lock; btr %[bit_number], %[storage]\n\t"
"setc %[result]\n\t"
: [storage] "+m" (storage), [result] "=q" (res)
: [bit_number] "Kq" (bit_number)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#endif
return res;
}
static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT
{
bool res;
#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
__asm__ __volatile__
(
"lock; btc %[bit_number], %[storage]\n\t"
: [storage] "+m" (storage), [result] "=@ccc" (res)
: [bit_number] "Kq" (bit_number)
: "memory"
);
#else
__asm__ __volatile__
(
"lock; btc %[bit_number], %[storage]\n\t"
"setc %[result]\n\t"
: [storage] "+m" (storage), [result] "=q" (res)
: [bit_number] "Kq" (bit_number)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#endif
return res;
}
};
template< typename Base, bool Signed >
struct extra_operations< Base, 1u, Signed, true > :
public gcc_x86_extra_operations_common< Base >
public extra_operations_generic< Base, 1u, Signed >
{
typedef gcc_x86_extra_operations_common< Base > base_type;
typedef extra_operations_generic< Base, 1u, Signed > base_type;
typedef typename base_type::storage_type storage_type;
typedef typename make_storage_type< 4u >::type temp_storage_type;
typedef typename storage_traits< 4u >::type temp_storage_type;
#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, original, result)\
__asm__ __volatile__\
@@ -503,11 +415,11 @@ struct extra_operations< Base, 1u, Signed, true > :
template< typename Base, bool Signed >
struct extra_operations< Base, 2u, Signed, true > :
public gcc_x86_extra_operations_common< Base >
public extra_operations_generic< Base, 2u, Signed >
{
typedef gcc_x86_extra_operations_common< Base > base_type;
typedef extra_operations_generic< Base, 2u, Signed > base_type;
typedef typename base_type::storage_type storage_type;
typedef typename make_storage_type< 4u >::type temp_storage_type;
typedef typename storage_traits< 4u >::type temp_storage_type;
#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, original, result)\
__asm__ __volatile__\
@@ -878,6 +790,78 @@ struct extra_operations< Base, 2u, Signed, true > :
: [argument] "iq" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#endif
return res;
}
static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT
{
bool res;
#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
__asm__ __volatile__
(
"lock; btsw %[bit_number], %[storage]\n\t"
: [storage] "+m" (storage), [result] "=@ccc" (res)
: [bit_number] "Kq" ((uint16_t)bit_number)
: "memory"
);
#else
__asm__ __volatile__
(
"lock; btsw %[bit_number], %[storage]\n\t"
"setc %[result]\n\t"
: [storage] "+m" (storage), [result] "=q" (res)
: [bit_number] "Kq" ((uint16_t)bit_number)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#endif
return res;
}
static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT
{
bool res;
#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
__asm__ __volatile__
(
"lock; btrw %[bit_number], %[storage]\n\t"
: [storage] "+m" (storage), [result] "=@ccc" (res)
: [bit_number] "Kq" ((uint16_t)bit_number)
: "memory"
);
#else
__asm__ __volatile__
(
"lock; btrw %[bit_number], %[storage]\n\t"
"setc %[result]\n\t"
: [storage] "+m" (storage), [result] "=q" (res)
: [bit_number] "Kq" ((uint16_t)bit_number)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#endif
return res;
}
static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT
{
bool res;
#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
__asm__ __volatile__
(
"lock; btcw %[bit_number], %[storage]\n\t"
: [storage] "+m" (storage), [result] "=@ccc" (res)
: [bit_number] "Kq" ((uint16_t)bit_number)
: "memory"
);
#else
__asm__ __volatile__
(
"lock; btcw %[bit_number], %[storage]\n\t"
"setc %[result]\n\t"
: [storage] "+m" (storage), [result] "=q" (res)
: [bit_number] "Kq" ((uint16_t)bit_number)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#endif
return res;
}
@@ -885,9 +869,9 @@ struct extra_operations< Base, 2u, Signed, true > :
template< typename Base, bool Signed >
struct extra_operations< Base, 4u, Signed, true > :
public gcc_x86_extra_operations_common< Base >
public extra_operations_generic< Base, 4u, Signed >
{
typedef gcc_x86_extra_operations_common< Base > base_type;
typedef extra_operations_generic< Base, 4u, Signed > base_type;
typedef typename base_type::storage_type storage_type;
#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, original, result)\
@@ -1259,6 +1243,78 @@ struct extra_operations< Base, 4u, Signed, true > :
: [argument] "ir" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#endif
return res;
}
static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT
{
bool res;
#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
__asm__ __volatile__
(
"lock; btsl %[bit_number], %[storage]\n\t"
: [storage] "+m" (storage), [result] "=@ccc" (res)
: [bit_number] "Kr" ((uint32_t)bit_number)
: "memory"
);
#else
__asm__ __volatile__
(
"lock; btsl %[bit_number], %[storage]\n\t"
"setc %[result]\n\t"
: [storage] "+m" (storage), [result] "=q" (res)
: [bit_number] "Kr" ((uint32_t)bit_number)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#endif
return res;
}
static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT
{
bool res;
#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
__asm__ __volatile__
(
"lock; btrl %[bit_number], %[storage]\n\t"
: [storage] "+m" (storage), [result] "=@ccc" (res)
: [bit_number] "Kr" ((uint32_t)bit_number)
: "memory"
);
#else
__asm__ __volatile__
(
"lock; btrl %[bit_number], %[storage]\n\t"
"setc %[result]\n\t"
: [storage] "+m" (storage), [result] "=q" (res)
: [bit_number] "Kr" ((uint32_t)bit_number)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#endif
return res;
}
static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT
{
bool res;
#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
__asm__ __volatile__
(
"lock; btcl %[bit_number], %[storage]\n\t"
: [storage] "+m" (storage), [result] "=@ccc" (res)
: [bit_number] "Kr" ((uint32_t)bit_number)
: "memory"
);
#else
__asm__ __volatile__
(
"lock; btcl %[bit_number], %[storage]\n\t"
"setc %[result]\n\t"
: [storage] "+m" (storage), [result] "=q" (res)
: [bit_number] "Kr" ((uint32_t)bit_number)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#endif
return res;
}
@@ -1268,9 +1324,9 @@ struct extra_operations< Base, 4u, Signed, true > :
template< typename Base, bool Signed >
struct extra_operations< Base, 8u, Signed, true > :
public gcc_x86_extra_operations_common< Base >
public extra_operations_generic< Base, 8u, Signed >
{
typedef gcc_x86_extra_operations_common< Base > base_type;
typedef extra_operations_generic< Base, 8u, Signed > base_type;
typedef typename base_type::storage_type storage_type;
#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, original, result)\
@@ -1642,6 +1698,78 @@ struct extra_operations< Base, 8u, Signed, true > :
: [argument] "er" (v)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#endif
return res;
}
static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT
{
bool res;
#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
__asm__ __volatile__
(
"lock; btsq %[bit_number], %[storage]\n\t"
: [storage] "+m" (storage), [result] "=@ccc" (res)
: [bit_number] "Kr" ((uint64_t)bit_number)
: "memory"
);
#else
__asm__ __volatile__
(
"lock; btsq %[bit_number], %[storage]\n\t"
"setc %[result]\n\t"
: [storage] "+m" (storage), [result] "=q" (res)
: [bit_number] "Kr" ((uint64_t)bit_number)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#endif
return res;
}
static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT
{
bool res;
#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
__asm__ __volatile__
(
"lock; btrq %[bit_number], %[storage]\n\t"
: [storage] "+m" (storage), [result] "=@ccc" (res)
: [bit_number] "Kr" ((uint64_t)bit_number)
: "memory"
);
#else
__asm__ __volatile__
(
"lock; btrq %[bit_number], %[storage]\n\t"
"setc %[result]\n\t"
: [storage] "+m" (storage), [result] "=q" (res)
: [bit_number] "Kr" ((uint64_t)bit_number)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#endif
return res;
}
static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT
{
bool res;
#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS)
__asm__ __volatile__
(
"lock; btcq %[bit_number], %[storage]\n\t"
: [storage] "+m" (storage), [result] "=@ccc" (res)
: [bit_number] "Kr" ((uint64_t)bit_number)
: "memory"
);
#else
__asm__ __volatile__
(
"lock; btcq %[bit_number], %[storage]\n\t"
"setc %[result]\n\t"
: [storage] "+m" (storage), [result] "=q" (res)
: [bit_number] "Kr" ((uint64_t)bit_number)
: BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"
);
#endif
return res;
}
@@ -1653,4 +1781,6 @@ struct extra_operations< Base, 8u, Signed, true > :
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_X86_HPP_INCLUDED_

View File

@@ -17,33 +17,27 @@
#include <cstddef>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/integral_extend.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#include <boost/atomic/detail/integral_conversions.hpp>
#include <boost/atomic/detail/extra_operations_fwd.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(BOOST_MSVC)
#pragma warning(push)
// unary minus operator applied to unsigned type, result still unsigned
#pragma warning(disable: 4146)
#endif
namespace boost {
namespace atomics {
namespace detail {
//! Generic implementation of extra operations
template< typename Base, std::size_t Size, bool Signed, bool = Base::full_cas_based >
struct generic_extra_operations :
struct extra_operations_generic :
public Base
{
typedef Base base_type;
typedef typename base_type::storage_type storage_type;
typedef typename make_storage_type< Size >::type emulated_storage_type;
typedef typename storage_traits< Size >::type emulated_storage_type;
static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
@@ -195,12 +189,12 @@ struct generic_extra_operations :
//! Specialization for cases when the platform only natively supports CAS
template< typename Base, std::size_t Size, bool Signed >
struct generic_extra_operations< Base, Size, Signed, true > :
struct extra_operations_generic< Base, Size, Signed, true > :
public Base
{
typedef Base base_type;
typedef typename base_type::storage_type storage_type;
typedef typename make_storage_type< Size >::type emulated_storage_type;
typedef typename storage_traits< Size >::type emulated_storage_type;
static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
@@ -387,7 +381,7 @@ struct generic_extra_operations< Base, Size, Signed, true > :
// Default extra_operations template definition will be used unless specialized for a specific platform
template< typename Base, std::size_t Size, bool Signed >
struct extra_operations< Base, Size, Signed, true > :
public generic_extra_operations< Base, Size, Signed >
public extra_operations_generic< Base, Size, Signed >
{
};
@@ -395,8 +389,6 @@ struct extra_operations< Base, Size, Signed, true > :
} // namespace atomics
} // namespace boost
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_GENERIC_HPP_INCLUDED_

View File

@@ -18,10 +18,10 @@
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/interlocked.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#include <boost/atomic/detail/extra_operations_fwd.hpp>
#include <boost/atomic/detail/extra_ops_generic.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -35,9 +35,9 @@ namespace detail {
template< typename Base, std::size_t Size, bool Signed >
struct extra_operations< Base, 4u, Signed, true > :
public generic_extra_operations< Base, 4u, Signed >
public extra_operations_generic< Base, 4u, Signed >
{
typedef generic_extra_operations< Base, 4u, Signed > base_type;
typedef extra_operations_generic< Base, 4u, Signed > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
@@ -103,4 +103,6 @@ struct extra_operations< Base, 4u, Signed, true > :
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_MSVC_ARM_HPP_INCLUDED_

View File

@@ -18,104 +18,28 @@
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/interlocked.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#include <boost/atomic/detail/extra_operations_fwd.hpp>
#include <boost/atomic/detail/extra_ops_generic.hpp>
#include <boost/atomic/capabilities.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(BOOST_MSVC)
#pragma warning(push)
// frame pointer register 'ebx' modified by inline assembly code
#pragma warning(disable: 4731)
#endif
namespace boost {
namespace atomics {
namespace detail {
#if defined(_M_IX86) || (defined(BOOST_ATOMIC_INTERLOCKED_BTS) && defined(BOOST_ATOMIC_INTERLOCKED_BTR))
template< typename Base, std::size_t Size, bool Signed >
struct msvc_x86_extra_operations_common :
public generic_extra_operations< Base, Size, Signed >
{
typedef generic_extra_operations< Base, Size, Signed > base_type;
typedef typename base_type::storage_type storage_type;
#if defined(BOOST_ATOMIC_INTERLOCKED_BTS)
static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT
{
return !!BOOST_ATOMIC_INTERLOCKED_BTS(&storage, bit_number);
}
#else
static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
bool result;
__asm
{
mov edx, storage
mov eax, bit_number
lock bts [edx], eax
setc result
};
base_type::fence_after(order);
return result;
}
#endif
#if defined(BOOST_ATOMIC_INTERLOCKED_BTR)
static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT
{
return !!BOOST_ATOMIC_INTERLOCKED_BTR(&storage, bit_number);
}
#else
static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
bool result;
__asm
{
mov edx, storage
mov eax, bit_number
lock btr [edx], eax
setc result
};
base_type::fence_after(order);
return result;
}
#endif
#if defined(_M_IX86)
static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
bool result;
__asm
{
mov edx, storage
mov eax, bit_number
lock btc [edx], eax
setc result
};
base_type::fence_after(order);
return result;
}
#endif
};
template< typename Base, bool Signed >
struct extra_operations< Base, 1u, Signed, true > :
public msvc_x86_extra_operations_common< Base, 1u, Signed >
public extra_operations_generic< Base, 1u, Signed >
{
typedef msvc_x86_extra_operations_common< Base, 1u, Signed > base_type;
typedef extra_operations_generic< Base, 1u, Signed > base_type;
typedef typename base_type::storage_type storage_type;
#if defined(_M_IX86)
static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
@@ -491,17 +415,15 @@ struct extra_operations< Base, 1u, Signed, true > :
base_type::fence_after(order);
return result;
}
#endif // defined(_M_IX86)
};
template< typename Base, bool Signed >
struct extra_operations< Base, 2u, Signed, true > :
public msvc_x86_extra_operations_common< Base, 2u, Signed >
public extra_operations_generic< Base, 2u, Signed >
{
typedef msvc_x86_extra_operations_common< Base, 2u, Signed > base_type;
typedef extra_operations_generic< Base, 2u, Signed > base_type;
typedef typename base_type::storage_type storage_type;
#if defined(_M_IX86)
static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
@@ -877,14 +799,62 @@ struct extra_operations< Base, 2u, Signed, true > :
base_type::fence_after(order);
return result;
}
#endif // defined(_M_IX86)
static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
bool result;
__asm
{
mov edx, storage
mov eax, bit_number
lock bts word ptr [edx], ax
setc result
};
base_type::fence_after(order);
return result;
}
static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
bool result;
__asm
{
mov edx, storage
mov eax, bit_number
lock btr word ptr [edx], ax
setc result
};
base_type::fence_after(order);
return result;
}
static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
bool result;
__asm
{
mov edx, storage
mov eax, bit_number
lock btc word ptr [edx], ax
setc result
};
base_type::fence_after(order);
return result;
}
};
#endif // defined(_M_IX86)
#if defined(_M_IX86) || (defined(BOOST_ATOMIC_INTERLOCKED_BTS) && defined(BOOST_ATOMIC_INTERLOCKED_BTR))
template< typename Base, bool Signed >
struct extra_operations< Base, 4u, Signed, true > :
public msvc_x86_extra_operations_common< Base, 4u, Signed >
public extra_operations_generic< Base, 4u, Signed >
{
typedef msvc_x86_extra_operations_common< Base, 4u, Signed > base_type;
typedef extra_operations_generic< Base, 4u, Signed > base_type;
typedef typename base_type::storage_type storage_type;
#if defined(_M_IX86)
@@ -1263,7 +1233,66 @@ struct extra_operations< Base, 4u, Signed, true > :
base_type::fence_after(order);
return result;
}
static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
bool result;
__asm
{
mov edx, storage
mov eax, bit_number
lock btc dword ptr [edx], eax
setc result
};
base_type::fence_after(order);
return result;
}
#endif // defined(_M_IX86)
#if defined(BOOST_ATOMIC_INTERLOCKED_BTS)
static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT
{
return !!BOOST_ATOMIC_INTERLOCKED_BTS(&storage, bit_number);
}
#elif defined(_M_IX86)
static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
bool result;
__asm
{
mov edx, storage
mov eax, bit_number
lock bts dword ptr [edx], eax
setc result
};
base_type::fence_after(order);
return result;
}
#endif
#if defined(BOOST_ATOMIC_INTERLOCKED_BTR)
static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT
{
return !!BOOST_ATOMIC_INTERLOCKED_BTR(&storage, bit_number);
}
#elif defined(_M_IX86)
static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
{
base_type::fence_before(order);
bool result;
__asm
{
mov edx, storage
mov eax, bit_number
lock btr dword ptr [edx], eax
setc result
};
base_type::fence_after(order);
return result;
}
#endif
};
#endif // defined(_M_IX86) || (defined(BOOST_ATOMIC_INTERLOCKED_BTS) && defined(BOOST_ATOMIC_INTERLOCKED_BTR))
@@ -1272,9 +1301,9 @@ struct extra_operations< Base, 4u, Signed, true > :
template< typename Base, bool Signed >
struct extra_operations< Base, 8u, Signed, true > :
public generic_extra_operations< Base, 8u, Signed >
public extra_operations_generic< Base, 8u, Signed >
{
typedef generic_extra_operations< Base, 8u, Signed > base_type;
typedef extra_operations_generic< Base, 8u, Signed > base_type;
typedef typename base_type::storage_type storage_type;
static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
@@ -1294,8 +1323,6 @@ struct extra_operations< Base, 8u, Signed, true > :
} // namespace atomics
} // namespace boost
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_MSVC_X86_HPP_INCLUDED_

View File

@@ -0,0 +1,41 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/fence_arch_operations.hpp
*
* This header defines architecture-specific fence atomic operations.
*/
#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPERATIONS_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPERATIONS_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/platform.hpp>
#if defined(BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND_HEADER)
#include BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND_HEADER(boost/atomic/detail/fence_arch_ops_)
#else
#include <boost/atomic/detail/fence_operations_emulated.hpp>
namespace boost {
namespace atomics {
namespace detail {
typedef fence_operations_emulated fence_arch_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#endif
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPERATIONS_HPP_INCLUDED_

View File

@@ -0,0 +1,60 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/fence_arch_ops_gcc_aarch32.hpp
*
* This header contains implementation of the \c fence_arch_operations struct.
*/
#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_AARCH32_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_AARCH32_HPP_INCLUDED_
#include <boost/cstdint.hpp>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/capabilities.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
//! Fence operations for AArch32
struct fence_arch_operations_gcc_aarch32
{
static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
{
if (order == memory_order_consume || order == memory_order_acquire)
__asm__ __volatile__ ("dmb ishld\n\t" ::: "memory");
else
__asm__ __volatile__ ("dmb ish\n\t" ::: "memory");
}
}
static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("" ::: "memory");
}
};
typedef fence_arch_operations_gcc_aarch32 fence_arch_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_AARCH32_HPP_INCLUDED_

View File

@@ -0,0 +1,58 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/fence_arch_ops_gcc_aarch64.hpp
*
* This header contains implementation of the \c fence_arch_operations struct.
*/
#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_AARCH64_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_AARCH64_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
//! Fence operations for AArch64
struct fence_arch_operations_gcc_aarch64
{
static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
{
if (order == memory_order_consume || order == memory_order_acquire)
__asm__ __volatile__ ("dmb ishld\n\t" ::: "memory");
else
__asm__ __volatile__ ("dmb ish\n\t" ::: "memory");
}
}
static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("" ::: "memory");
}
};
typedef fence_arch_operations_gcc_aarch64 fence_arch_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_AARCH64_HPP_INCLUDED_

View File

@@ -0,0 +1,53 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/fence_arch_ops_gcc_alpha.hpp
*
* This header contains implementation of the \c fence_arch_operations struct.
*/
#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_ALPHA_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_ALPHA_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
//! Fence operations for Alpha
struct fence_arch_operations_gcc_alpha
{
static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("mb" ::: "memory");
}
static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("" ::: "memory");
}
};
typedef fence_arch_operations_gcc_alpha fence_arch_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_ALPHA_HPP_INCLUDED_

View File

@@ -0,0 +1,90 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/fence_arch_ops_gcc_arm.hpp
*
* This header contains implementation of the \c fence_arch_operations struct.
*/
#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_ARM_HPP_INCLUDED_
#include <boost/cstdint.hpp>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/capabilities.hpp>
#include <boost/atomic/detail/gcc_arm_asm_common.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
//! Fence operations for legacy ARM
struct fence_arch_operations_gcc_arm
{
static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
hardware_full_fence();
}
static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("" ::: "memory");
}
static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
{
// A memory barrier is effected using a "co-processor 15" instruction,
// though a separate assembler mnemonic is available for it in v7.
#if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_DMB)
// Older binutils (supposedly, older than 2.21.1) didn't support symbolic or numeric arguments of the "dmb" instruction such as "ish" or "#11".
// As a workaround we have to inject encoded bytes of the instruction. There are two encodings for the instruction: ARM and Thumb. See ARM Architecture Reference Manual, A8.8.43.
// Since we cannot detect binutils version at compile time, we'll have to always use this hack.
__asm__ __volatile__
(
#if defined(__thumb2__)
".short 0xF3BF, 0x8F5B\n\t" // dmb ish
#else
".word 0xF57FF05B\n\t" // dmb ish
#endif
:
:
: "memory"
);
#else
uint32_t tmp;
__asm__ __volatile__
(
BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0)
"mcr p15, 0, r0, c7, c10, 5\n\t"
BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0)
: "=&l" (tmp)
:
: "memory"
);
#endif
}
};
typedef fence_arch_operations_gcc_arm fence_arch_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_ARM_HPP_INCLUDED_

View File

@@ -0,0 +1,68 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/fence_arch_ops_gcc_ppc.hpp
*
* This header contains implementation of the \c fence_arch_operations struct.
*/
#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_PPC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_PPC_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
//! Fence operations for PowerPC
struct fence_arch_operations_gcc_ppc
{
static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
{
#if defined(__powerpc64__) || defined(__PPC64__)
if (order != memory_order_seq_cst)
__asm__ __volatile__ ("lwsync" ::: "memory");
else
__asm__ __volatile__ ("sync" ::: "memory");
#else
__asm__ __volatile__ ("sync" ::: "memory");
#endif
}
}
static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
{
#if defined(__ibmxl__) || defined(__IBMCPP__)
__fence();
#else
__asm__ __volatile__ ("" ::: "memory");
#endif
}
}
};
typedef fence_arch_operations_gcc_ppc fence_arch_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_PPC_HPP_INCLUDED_

View File

@@ -0,0 +1,70 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/fence_arch_ops_gcc_sparc.hpp
*
* This header contains implementation of the \c fence_arch_operations struct.
*/
#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_SPARC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_SPARC_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
//! Fence operations for SPARC
struct fence_arch_operations_gcc_sparc
{
static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
switch (order)
{
case memory_order_release:
__asm__ __volatile__ ("membar #StoreStore | #LoadStore" ::: "memory");
break;
case memory_order_consume:
case memory_order_acquire:
__asm__ __volatile__ ("membar #LoadLoad | #LoadStore" ::: "memory");
break;
case memory_order_acq_rel:
__asm__ __volatile__ ("membar #LoadLoad | #LoadStore | #StoreStore" ::: "memory");
break;
case memory_order_seq_cst:
__asm__ __volatile__ ("membar #Sync" ::: "memory");
break;
case memory_order_relaxed:
default:
break;
}
}
static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("" ::: "memory");
}
};
typedef fence_arch_operations_gcc_sparc fence_arch_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_SPARC_HPP_INCLUDED_

View File

@@ -0,0 +1,69 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/fence_arch_ops_gcc_x86.hpp
*
* This header contains implementation of the \c fence_arch_operations struct.
*/
#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_X86_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_X86_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
//! Fence operations for x86
struct fence_arch_operations_gcc_x86
{
static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
if (order == memory_order_seq_cst)
{
// We could generate mfence for a seq_cst fence here, but a dummy lock-prefixed instruction is enough
// and is faster than mfence on most modern x86 CPUs (as of 2020).
// Note that we want to apply the atomic operation on any location so that:
// - It is not shared with other threads. A variable on the stack suits this well.
// - It is likely in cache. Being close to the top of the stack fits this well.
// - It does not alias existing data on the stack, so that we don't introduce a false data dependency.
// See some performance data here: https://shipilev.net/blog/2014/on-the-fence-with-dependencies/
// Unfortunately, to make tools like valgrind happy, we have to initialize the dummy, which is
// otherwise not needed.
unsigned char dummy = 0u;
__asm__ __volatile__ ("lock; notb %0" : "+m" (dummy) : : "memory");
}
else if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_acquire) | static_cast< unsigned int >(memory_order_release))) != 0u)
{
__asm__ __volatile__ ("" ::: "memory");
}
}
static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("" ::: "memory");
}
};
typedef fence_arch_operations_gcc_x86 fence_arch_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_X86_HPP_INCLUDED_

View File

@@ -0,0 +1,66 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/fence_arch_ops_msvc_arm.hpp
*
* This header contains implementation of the \c fence_arch_operations struct.
*/
#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_MSVC_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_MSVC_ARM_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/ops_msvc_common.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
extern "C" void __dmb(unsigned int);
#if defined(BOOST_MSVC)
#pragma intrinsic(__dmb)
#endif
namespace boost {
namespace atomics {
namespace detail {
//! Fence operations for ARM
struct fence_arch_operations_msvc_arm
{
static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
if (order != memory_order_relaxed)
hardware_full_fence();
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
{
__dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later
}
};
typedef fence_arch_operations_msvc_arm fence_arch_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_MSVC_ARM_HPP_INCLUDED_

View File

@@ -0,0 +1,66 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/fence_arch_ops_msvc_x86.hpp
*
* This header contains implementation of the \c fence_arch_operations struct.
*/
#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_MSVC_X86_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_MSVC_X86_HPP_INCLUDED_
#include <boost/cstdint.hpp>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/interlocked.hpp>
#include <boost/atomic/detail/ops_msvc_common.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
//! Fence operations for x86
struct fence_arch_operations_msvc_x86
{
static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
if (order == memory_order_seq_cst)
{
// See the comment in fence_ops_gcc_x86.hpp as to why we're not using mfence here.
// We're not using __faststorefence() here because it generates an atomic operation
// on [rsp]/[esp] location, which may alias valid data and cause false data dependency.
boost::uint32_t dummy;
BOOST_ATOMIC_INTERLOCKED_INCREMENT(&dummy);
}
else if (order != memory_order_relaxed)
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
}
static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
};
typedef fence_arch_operations_msvc_x86 fence_arch_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_MSVC_X86_HPP_INCLUDED_

View File

@@ -0,0 +1,41 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/fence_operations.hpp
*
* This header defines fence atomic operations.
*/
#ifndef BOOST_ATOMIC_DETAIL_FENCE_OPERATIONS_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_FENCE_OPERATIONS_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/platform.hpp>
#if defined(BOOST_ATOMIC_DETAIL_CORE_BACKEND_HEADER)
#include BOOST_ATOMIC_DETAIL_CORE_BACKEND_HEADER(boost/atomic/detail/fence_ops_)
#else
#include <boost/atomic/detail/fence_arch_operations.hpp>
namespace boost {
namespace atomics {
namespace detail {
typedef fence_arch_operations fence_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#endif
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#endif // BOOST_ATOMIC_DETAIL_FENCE_OPERATIONS_HPP_INCLUDED_

View File

@@ -0,0 +1,50 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/fence_operations_emulated.hpp
*
* This header contains implementation of the \c fence_operations struct.
*/
#ifndef BOOST_ATOMIC_DETAIL_FENCE_OPERATIONS_EMULATED_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_FENCE_OPERATIONS_EMULATED_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/lock_pool.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
//! Fence operations based on lock pool
struct fence_operations_emulated
{
static BOOST_FORCEINLINE void thread_fence(memory_order) BOOST_NOEXCEPT
{
atomics::detail::lock_pool::thread_fence();
}
static BOOST_FORCEINLINE void signal_fence(memory_order) BOOST_NOEXCEPT
{
atomics::detail::lock_pool::signal_fence();
}
};
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_FENCE_OPERATIONS_EMULATED_HPP_INCLUDED_

View File

@@ -0,0 +1,75 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/fence_ops_gcc_atomic.hpp
*
* This header contains implementation of the \c fence_operations struct.
*/
#ifndef BOOST_ATOMIC_DETAIL_FENCE_OPS_GCC_ATOMIC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_FENCE_OPS_GCC_ATOMIC_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/fence_arch_operations.hpp>
#include <boost/atomic/detail/gcc_atomic_memory_order_utils.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(__INTEL_COMPILER)
// This is used to suppress warning #32013 described in gcc_atomic_memory_order_utils.hpp
// for Intel Compiler.
// In debug builds the compiler does not inline any functions, so basically
// every atomic function call results in this warning. I don't know any other
// way to selectively disable just this one warning.
#pragma system_header
#endif
namespace boost {
namespace atomics {
namespace detail {
//! Fence operations based on gcc __atomic* intrinsics
struct fence_operations_gcc_atomic
{
static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
#if defined(__x86_64__) || defined(__i386__)
if (order != memory_order_seq_cst)
{
__atomic_thread_fence(atomics::detail::convert_memory_order_to_gcc(order));
}
else
{
// gcc, clang, icc and probably other compilers generate mfence for a seq_cst fence,
// while a dummy lock-prefixed instruction would be enough and faster. See the comment in fence_ops_gcc_x86.hpp.
fence_arch_operations::thread_fence(order);
}
#else
__atomic_thread_fence(atomics::detail::convert_memory_order_to_gcc(order));
#endif
}
static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
__atomic_signal_fence(atomics::detail::convert_memory_order_to_gcc(order));
}
};
typedef fence_operations_gcc_atomic fence_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_FENCE_OPS_GCC_ATOMIC_HPP_INCLUDED_

View File

@@ -0,0 +1,53 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/fence_ops_gcc_sync.hpp
*
* This header contains implementation of the \c fence_operations struct.
*/
#ifndef BOOST_ATOMIC_DETAIL_FENCE_OPS_GCC_SYNC_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_FENCE_OPS_GCC_SYNC_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
//! Fence operations based on gcc __sync* intrinsics
struct fence_operations_gcc_sync
{
static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__sync_synchronize();
}
static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("" ::: "memory");
}
};
typedef fence_operations_gcc_sync fence_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_FENCE_OPS_GCC_SYNC_HPP_INCLUDED_

View File

@@ -0,0 +1,64 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009, 2011 Helge Bahmann
* Copyright (c) 2009 Phil Endecott
* Copyright (c) 2013 Tim Blechmann
* Linux-specific code by Phil Endecott
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/fence_ops_linux_arm.hpp
*
* This header contains implementation of the \c fence_operations struct.
*/
#ifndef BOOST_ATOMIC_DETAIL_FENCE_OPS_LINUX_ARM_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_FENCE_OPS_LINUX_ARM_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
//! Fence operations based on Linux-specific system routines
struct fence_operations_linux_arm
{
static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
hardware_full_fence();
}
static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
__asm__ __volatile__ ("" ::: "memory");
}
static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
{
// See the comment in core_ops_linux_arm.hpp regarding the function pointer below
typedef void (*kernel_dmb_t)(void);
((kernel_dmb_t)0xffff0fa0)();
}
};
typedef fence_operations_linux_arm fence_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_FENCE_OPS_LINUX_ARM_HPP_INCLUDED_

View File

@@ -0,0 +1,67 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/fence_ops_windows.hpp
*
* This header contains implementation of the \c fence_operations struct.
*/
#ifndef BOOST_ATOMIC_DETAIL_FENCE_OPS_WINDOWS_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_FENCE_OPS_WINDOWS_HPP_INCLUDED_
#include <boost/cstdint.hpp>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/interlocked.hpp>
#include <boost/atomic/detail/ops_msvc_common.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
//! Fence operations based on Windows-specific system calls or intrinsics
struct fence_operations_windows
{
static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
{
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
if (order == memory_order_seq_cst)
hardware_full_fence();
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
}
static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
{
if (order != memory_order_relaxed)
BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
}
static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
{
boost::uint32_t tmp;
BOOST_ATOMIC_INTERLOCKED_INCREMENT(&tmp);
}
};
typedef fence_operations_windows fence_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_FENCE_OPS_WINDOWS_HPP_INCLUDED_

View File

@@ -0,0 +1,24 @@
/*
* Copyright Andrey Semashev 2020.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#if !defined(BOOST_ATOMIC_ENABLE_WARNINGS)
#if defined(BOOST_MSVC)
#pragma warning(pop)
#elif defined(BOOST_GCC) && BOOST_GCC >= 40600
#pragma GCC diagnostic pop
#elif defined(BOOST_CLANG)
#pragma clang diagnostic pop
#endif
#endif // !defined(BOOST_ATOMIC_ENABLE_WARNINGS)

View File

@@ -16,6 +16,7 @@
#include <cstddef>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -25,11 +26,13 @@ namespace boost {
namespace atomics {
namespace detail {
template< typename Base, typename Value, std::size_t Size, bool = Base::is_always_lock_free >
template< typename Base, typename Value, std::size_t Size = sizeof(typename Base::storage_type), bool = Base::is_always_lock_free >
struct fp_operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_FP_OPERATIONS_FWD_HPP_INCLUDED_

View File

@@ -15,11 +15,12 @@
#define BOOST_ATOMIC_DETAIL_FP_OPS_EMULATED_HPP_INCLUDED_
#include <cstddef>
#include <boost/static_assert.hpp>
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/bitwise_fp_cast.hpp>
#include <boost/atomic/detail/fp_operations_fwd.hpp>
#include <boost/atomic/detail/lockpool.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -29,29 +30,32 @@ namespace boost {
namespace atomics {
namespace detail {
//! Generic implementation of floating point operations
//! Emulated implementation of floating point operations
template< typename Base, typename Value, std::size_t Size >
struct emulated_fp_operations :
struct fp_operations_emulated :
public Base
{
typedef Base base_type;
typedef typename base_type::storage_type storage_type;
typedef Value value_type;
typedef typename base_type::scoped_lock scoped_lock;
static BOOST_FORCEINLINE value_type fetch_add(storage_type volatile& storage, value_type v, memory_order) BOOST_NOEXCEPT
static value_type fetch_add(storage_type volatile& storage, value_type v, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
scoped_lock lock(&storage);
value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s);
value_type new_val = old_val + v;
s = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
return old_val;
}
static BOOST_FORCEINLINE value_type fetch_sub(storage_type volatile& storage, value_type v, memory_order) BOOST_NOEXCEPT
static value_type fetch_sub(storage_type volatile& storage, value_type v, memory_order) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object");
storage_type& s = const_cast< storage_type& >(storage);
lockpool::scoped_lock lock(&storage);
scoped_lock lock(&storage);
value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s);
value_type new_val = old_val - v;
s = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
@@ -61,7 +65,7 @@ struct emulated_fp_operations :
template< typename Base, typename Value, std::size_t Size >
struct fp_operations< Base, Value, Size, false > :
public emulated_fp_operations< Base, Value, Size >
public fp_operations_emulated< Base, Value, Size >
{
};
@@ -69,4 +73,6 @@ struct fp_operations< Base, Value, Size, false > :
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_FP_OPS_EMULATED_HPP_INCLUDED_

View File

@@ -18,8 +18,9 @@
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/bitwise_fp_cast.hpp>
#include <boost/atomic/detail/storage_type.hpp>
#include <boost/atomic/detail/storage_traits.hpp>
#include <boost/atomic/detail/fp_operations_fwd.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -31,7 +32,7 @@ namespace detail {
//! Generic implementation of floating point operations
template< typename Base, typename Value, std::size_t Size >
struct generic_fp_operations :
struct fp_operations_generic :
public Base
{
typedef Base base_type;
@@ -72,7 +73,7 @@ struct generic_fp_operations :
// Default fp_operations template definition will be used unless specialized for a specific platform
template< typename Base, typename Value, std::size_t Size >
struct fp_operations< Base, Value, Size, true > :
public generic_fp_operations< Base, Value, Size >
public fp_operations_generic< Base, Value, Size >
{
};
@@ -80,4 +81,6 @@ struct fp_operations< Base, Value, Size, true > :
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_FP_OPS_GENERIC_HPP_INCLUDED_

View File

@@ -0,0 +1,154 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/futex.hpp
*
* This header defines wrappers around futex syscall.
*
* http://man7.org/linux/man-pages/man2/futex.2.html
* https://man.openbsd.org/futex
*/
#ifndef BOOST_ATOMIC_DETAIL_FUTEX_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_FUTEX_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(__linux__) || defined(__OpenBSD__) || defined(__NETBSD__) || defined(__NetBSD__)
#include <sys/syscall.h>
#if defined(SYS_futex)
#define BOOST_ATOMIC_DETAIL_SYS_FUTEX SYS_futex
#elif defined(SYS_futex_time64)
// On some 32-bit targets (e.g. riscv32) SYS_futex is not defined and instead SYS_futex_time64 is implemented,
// which is equivalent to SYS_futex but uses 64-bit time_t.
#define BOOST_ATOMIC_DETAIL_SYS_FUTEX SYS_futex_time64
#elif defined(__NR_futex)
// Some Android NDKs (Google NDK and older Crystax.NET NDK versions) don't define SYS_futex.
#define BOOST_ATOMIC_DETAIL_SYS_FUTEX __NR_futex
#elif defined(SYS___futex)
// NetBSD defines SYS___futex, which has slightly different parameters. Basically, it has decoupled timeout and val2 parameters:
// int __futex(int *addr1, int op, int val1, const struct timespec *timeout, int *addr2, int val2, int val3);
// https://ftp.netbsd.org/pub/NetBSD/NetBSD-current/src/sys/sys/syscall.h
// http://bxr.su/NetBSD/sys/kern/sys_futex.c
#define BOOST_ATOMIC_DETAIL_SYS_FUTEX SYS___futex
#define BOOST_ATOMIC_DETAIL_NETBSD_FUTEX
#endif
#if defined(BOOST_ATOMIC_DETAIL_SYS_FUTEX)
#include <cstddef>
#if defined(__linux__)
#include <linux/futex.h>
#else
#include <sys/futex.h>
#endif
#include <boost/atomic/detail/intptr.hpp>
#include <boost/atomic/detail/header.hpp>
#define BOOST_ATOMIC_DETAIL_HAS_FUTEX
#if defined(FUTEX_PRIVATE_FLAG)
#define BOOST_ATOMIC_DETAIL_FUTEX_PRIVATE_FLAG FUTEX_PRIVATE_FLAG
#elif defined(__ANDROID__)
// On Android, futex.h is lacking many definitions, but the actual Linux kernel supports the API in full.
#define BOOST_ATOMIC_DETAIL_FUTEX_PRIVATE_FLAG 128
#else
#define BOOST_ATOMIC_DETAIL_FUTEX_PRIVATE_FLAG 0
#endif
namespace boost {
namespace atomics {
namespace detail {
//! Invokes an operation on the futex
BOOST_FORCEINLINE int futex_invoke(void* addr1, int op, unsigned int val1, const void* timeout = NULL, void* addr2 = NULL, unsigned int val3 = 0) BOOST_NOEXCEPT
{
#if !defined(BOOST_ATOMIC_DETAIL_NETBSD_FUTEX)
return ::syscall(BOOST_ATOMIC_DETAIL_SYS_FUTEX, addr1, op, val1, timeout, addr2, val3);
#else
// Pass 0 in val2.
return ::syscall(BOOST_ATOMIC_DETAIL_SYS_FUTEX, addr1, op, val1, timeout, addr2, 0u, val3);
#endif
}
//! Invokes an operation on the futex
BOOST_FORCEINLINE int futex_invoke(void* addr1, int op, unsigned int val1, unsigned int val2, void* addr2 = NULL, unsigned int val3 = 0) BOOST_NOEXCEPT
{
#if !defined(BOOST_ATOMIC_DETAIL_NETBSD_FUTEX)
return ::syscall(BOOST_ATOMIC_DETAIL_SYS_FUTEX, addr1, op, val1, static_cast< atomics::detail::uintptr_t >(val2), addr2, val3);
#else
// Pass NULL in timeout.
return ::syscall(BOOST_ATOMIC_DETAIL_SYS_FUTEX, addr1, op, val1, static_cast< void* >(NULL), addr2, val2, val3);
#endif
}
//! Checks that the value \c pval is \c expected and blocks
BOOST_FORCEINLINE int futex_wait(void* pval, unsigned int expected) BOOST_NOEXCEPT
{
return futex_invoke(pval, FUTEX_WAIT, expected);
}
//! Checks that the value \c pval is \c expected and blocks
BOOST_FORCEINLINE int futex_wait_private(void* pval, unsigned int expected) BOOST_NOEXCEPT
{
return futex_invoke(pval, FUTEX_WAIT | BOOST_ATOMIC_DETAIL_FUTEX_PRIVATE_FLAG, expected);
}
//! Wakes the specified number of threads waiting on the futex
BOOST_FORCEINLINE int futex_signal(void* pval, unsigned int count = 1u) BOOST_NOEXCEPT
{
return futex_invoke(pval, FUTEX_WAKE, count);
}
//! Wakes the specified number of threads waiting on the futex
BOOST_FORCEINLINE int futex_signal_private(void* pval, unsigned int count = 1u) BOOST_NOEXCEPT
{
return futex_invoke(pval, FUTEX_WAKE | BOOST_ATOMIC_DETAIL_FUTEX_PRIVATE_FLAG, count);
}
//! Wakes all threads waiting on the futex
BOOST_FORCEINLINE int futex_broadcast(void* pval) BOOST_NOEXCEPT
{
return futex_signal(pval, (~static_cast< unsigned int >(0u)) >> 1);
}
//! Wakes all threads waiting on the futex
BOOST_FORCEINLINE int futex_broadcast_private(void* pval) BOOST_NOEXCEPT
{
return futex_signal_private(pval, (~static_cast< unsigned int >(0u)) >> 1);
}
//! Wakes the wake_count threads waiting on the futex pval1 and requeues up to requeue_count of the blocked threads onto another futex pval2
BOOST_FORCEINLINE int futex_requeue(void* pval1, void* pval2, unsigned int wake_count = 1u, unsigned int requeue_count = (~static_cast< unsigned int >(0u)) >> 1) BOOST_NOEXCEPT
{
return futex_invoke(pval1, FUTEX_REQUEUE, wake_count, requeue_count, pval2);
}
//! Wakes the wake_count threads waiting on the futex pval1 and requeues up to requeue_count of the blocked threads onto another futex pval2
BOOST_FORCEINLINE int futex_requeue_private(void* pval1, void* pval2, unsigned int wake_count = 1u, unsigned int requeue_count = (~static_cast< unsigned int >(0u)) >> 1) BOOST_NOEXCEPT
{
return futex_invoke(pval1, FUTEX_REQUEUE | BOOST_ATOMIC_DETAIL_FUTEX_PRIVATE_FLAG, wake_count, requeue_count, pval2);
}
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // defined(BOOST_ATOMIC_DETAIL_SYS_FUTEX)
#endif // defined(__linux__) || defined(__OpenBSD__) || defined(__NETBSD__) || defined(__NetBSD__)
#endif // BOOST_ATOMIC_DETAIL_FUTEX_HPP_INCLUDED_

View File

@@ -0,0 +1,79 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2009 Helge Bahmann
* Copyright (c) 2013 Tim Blechmann
* Copyright (c) 2014, 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/gcc_arm_asm_common.hpp
*
* This header contains basic utilities for gcc asm-based ARM backend.
*/
#ifndef BOOST_ATOMIC_DETAIL_GCC_ARM_ASM_COMMON_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_GCC_ARM_ASM_COMMON_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/capabilities.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
// A memory barrier is effected using a "co-processor 15" instruction,
// though a separate assembler mnemonic is available for it in v7.
//
// "Thumb 1" is a subset of the ARM instruction set that uses a 16-bit encoding. It
// doesn't include all instructions and in particular it doesn't include the co-processor
// instruction used for the memory barrier or the load-locked/store-conditional
// instructions. So, if we're compiling in "Thumb 1" mode, we need to wrap all of our
// asm blocks with code to temporarily change to ARM mode.
//
// You can only change between ARM and Thumb modes when branching using the bx instruction.
// bx takes an address specified in a register. The least significant bit of the address
// indicates the mode, so 1 is added to indicate that the destination code is Thumb.
// A temporary register is needed for the address and is passed as an argument to these
// macros. It must be one of the "low" registers accessible to Thumb code, specified
// using the "l" attribute in the asm statement.
//
// Architecture v7 introduces "Thumb 2", which does include (almost?) all of the ARM
// instruction set. (Actually, there was an extension of v6 called v6T2 which supported
// "Thumb 2" mode, but its architecture manual is no longer available, referring to v7.)
// So in v7 we don't need to change to ARM mode; we can write "universal
// assembler" which will assemble to Thumb 2 or ARM code as appropriate. The only thing
// we need to do to make this "universal" assembler mode work is to insert "IT" instructions
// to annotate the conditional instructions. These are ignored in other modes (e.g. v6),
// so they can always be present.
// A note about memory_order_consume. Technically, this architecture allows to avoid
// unnecessary memory barrier after consume load since it supports data dependency ordering.
// However, some compiler optimizations may break a seemingly valid code relying on data
// dependency tracking by injecting bogus branches to aid out of order execution.
// This may happen not only in Boost.Atomic code but also in user's code, which we have no
// control of. See this thread: http://lists.boost.org/Archives/boost/2014/06/213890.php.
// For this reason we promote memory_order_consume to memory_order_acquire.
#if defined(__thumb__) && !defined(__thumb2__)
#define BOOST_ATOMIC_DETAIL_ARM_ASM_START(TMPREG) "adr " #TMPREG ", 8f\n\t" "bx " #TMPREG "\n\t" ".arm\n\t" ".align 4\n\t" "8:\n\t"
#define BOOST_ATOMIC_DETAIL_ARM_ASM_END(TMPREG) "adr " #TMPREG ", 9f + 1\n\t" "bx " #TMPREG "\n\t" ".thumb\n\t" ".align 2\n\t" "9:\n\t"
#define BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(var) "=&l" (var)
#else
// Indicate that start/end macros are empty and the tmpreg is not needed
#define BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED
#define BOOST_ATOMIC_DETAIL_ARM_ASM_START(TMPREG)
#define BOOST_ATOMIC_DETAIL_ARM_ASM_END(TMPREG)
#define BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(var) "=&l" (var)
#endif
#if defined(BOOST_ATOMIC_DETAIL_ARM_LITTLE_ENDIAN)
#define BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(arg) "%" BOOST_STRINGIZE(arg)
#define BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(arg) "%H" BOOST_STRINGIZE(arg)
#else
#define BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(arg) "%H" BOOST_STRINGIZE(arg)
#define BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(arg) "%" BOOST_STRINGIZE(arg)
#endif
#endif // BOOST_ATOMIC_DETAIL_GCC_ARM_ASM_COMMON_HPP_INCLUDED_

View File

@@ -0,0 +1,66 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/gcc_atomic_memory_order_utils.hpp
*
* This header contains utilities for working with gcc atomic memory order constants.
*/
#ifndef BOOST_ATOMIC_DETAIL_GCC_ATOMIC_MEMORY_ORDER_UTILS_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_MEMORY_ORDER_UTILS_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
/*!
* The function converts \c boost::memory_order values to the compiler-specific constants.
*
* NOTE: The intention is that the function is optimized away by the compiler, and the
* compiler-specific constants are passed to the intrinsics. Unfortunately, constexpr doesn't
* work in this case because the standard atomics interface require memory ordering
* constants to be passed as function arguments, at which point they stop being constexpr.
* However, it is crucial that the compiler sees constants and not runtime values,
* because otherwise it just ignores the ordering value and always uses seq_cst.
* This is the case with Intel C++ Compiler 14.0.3 (Composer XE 2013 SP1, update 3) and
* gcc 4.8.2. Intel Compiler issues a warning in this case:
*
* warning #32013: Invalid memory order specified. Defaulting to seq_cst memory order.
*
* while gcc acts silently.
*
* To mitigate the problem ALL functions, including the atomic<> members must be
* declared with BOOST_FORCEINLINE. In this case the compilers are able to see that
* all functions are called with constant orderings and call intrinstcts properly.
*
* Unfortunately, this still doesn't work in debug mode as the compiler doesn't
* propagate constants even when functions are marked with BOOST_FORCEINLINE. In this case
* all atomic operaions will be executed with seq_cst semantics.
*/
BOOST_FORCEINLINE BOOST_CONSTEXPR int convert_memory_order_to_gcc(memory_order order) BOOST_NOEXCEPT
{
return (order == memory_order_relaxed ? __ATOMIC_RELAXED : (order == memory_order_consume ? __ATOMIC_CONSUME :
(order == memory_order_acquire ? __ATOMIC_ACQUIRE : (order == memory_order_release ? __ATOMIC_RELEASE :
(order == memory_order_acq_rel ? __ATOMIC_ACQ_REL : __ATOMIC_SEQ_CST)))));
}
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_GCC_ATOMIC_MEMORY_ORDER_UTILS_HPP_INCLUDED_

View File

@@ -0,0 +1,33 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2021 Andrey Semashev
*/
/*!
* \file atomic/detail/gcc_ppc_asm_common.hpp
*
* This header contains basic utilities for gcc asm-based PowerPC backend.
*/
#ifndef BOOST_ATOMIC_DETAIL_GCC_PPC_ASM_COMMON_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_GCC_PPC_ASM_COMMON_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if !defined(_AIX)
#define BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL(label) label ":\n\t"
#define BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP(insn, label, offset) insn " " label "\n\t"
#else
// Standard assembler tool (as) on AIX does not support numeric jump labels, so we have to use offsets instead.
// https://github.com/boostorg/atomic/pull/50
#define BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL(label)
#define BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP(insn, label, offset) insn " $" offset "\n\t"
#endif
#endif // BOOST_ATOMIC_DETAIL_GCC_PPC_ASM_COMMON_HPP_INCLUDED_

View File

@@ -0,0 +1,72 @@
/*
* Copyright Andrey Semashev 2020.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if !defined(BOOST_ATOMIC_ENABLE_WARNINGS)
#if defined(BOOST_MSVC)
#pragma warning(push, 3)
// 'm_A' : class 'A' needs to have dll-interface to be used by clients of class 'B'
#pragma warning(disable: 4251)
// non dll-interface class 'A' used as base for dll-interface class 'B'
#pragma warning(disable: 4275)
// 'this' : used in base member initializer list
#pragma warning(disable: 4355)
// 'int' : forcing value to bool 'true' or 'false' (performance warning)
#pragma warning(disable: 4800)
// unreferenced formal parameter
#pragma warning(disable: 4100)
// conditional expression is constant
#pragma warning(disable: 4127)
// default constructor could not be generated
#pragma warning(disable: 4510)
// copy constructor could not be generated
#pragma warning(disable: 4511)
// assignment operator could not be generated
#pragma warning(disable: 4512)
// function marked as __forceinline not inlined
#pragma warning(disable: 4714)
// decorated name length exceeded, name was truncated
#pragma warning(disable: 4503)
// declaration of 'A' hides previous local declaration
#pragma warning(disable: 4456)
// declaration of 'A' hides global declaration
#pragma warning(disable: 4459)
// 'X': This function or variable may be unsafe. Consider using Y instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
#pragma warning(disable: 4996)
// 'A' : multiple assignment operators specified
#pragma warning(disable: 4522)
// unary minus operator applied to unsigned type, result still unsigned
#pragma warning(disable: 4146)
// frame pointer register 'ebx' modified by inline assembly code
#pragma warning(disable: 4731)
// alignment is sensitive to packing
#pragma warning(disable: 4121)
// 'struct_name' : structure was padded due to __declspec(align())
#pragma warning(disable: 4324)
#elif defined(BOOST_GCC) && BOOST_GCC >= 40600
#pragma GCC diagnostic push
// unused parameter 'arg'
#pragma GCC diagnostic ignored "-Wunused-parameter"
// missing initializer for member var
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#elif defined(BOOST_CLANG)
#pragma clang diagnostic push
// unused parameter 'arg'
#pragma clang diagnostic ignored "-Wunused-parameter"
// missing initializer for member var
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
#endif
#endif // !defined(BOOST_ATOMIC_ENABLE_WARNINGS)

View File

@@ -47,12 +47,19 @@
#endif
#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_SHORT) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_INT) ||\
!defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LLONG)
!defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LLONG) ||\
!defined(BOOST_ATOMIC_DETAIL_SIZEOF_POINTER)
// Try to deduce sizes from limits
#include <limits.h>
#if defined(__has_include)
#if __has_include(<stdint.h>)
#include <stdint.h>
#endif
#endif
#include <boost/cstdint.hpp>
#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_SHORT)
#if (USHRT_MAX + 0) == 0xff
#define BOOST_ATOMIC_DETAIL_SIZEOF_SHORT 1
#elif (USHRT_MAX + 0) == 0xffff
@@ -62,7 +69,9 @@
#elif (USHRT_MAX + 0) == UINT64_C(0xffffffffffffffff)
#define BOOST_ATOMIC_DETAIL_SIZEOF_SHORT 8
#endif
#endif // !defined(BOOST_ATOMIC_DETAIL_SIZEOF_SHORT)
#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_INT)
#if (UINT_MAX + 0) == 0xff
#define BOOST_ATOMIC_DETAIL_SIZEOF_INT 1
#elif (UINT_MAX + 0) == 0xffff
@@ -72,7 +81,9 @@
#elif (UINT_MAX + 0) == UINT64_C(0xffffffffffffffff)
#define BOOST_ATOMIC_DETAIL_SIZEOF_INT 8
#endif
#endif // !defined(BOOST_ATOMIC_DETAIL_SIZEOF_INT)
#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG)
#if (ULONG_MAX + 0) == 0xff
#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG 1
#elif (ULONG_MAX + 0) == 0xffff
@@ -82,7 +93,9 @@
#elif (ULONG_MAX + 0) == UINT64_C(0xffffffffffffffff)
#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG 8
#endif
#endif // !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG)
#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LLONG)
#if defined(__hpux) // HP-UX's value of ULONG_LONG_MAX is unusable in preprocessor expressions
#define BOOST_ATOMIC_DETAIL_SIZEOF_LLONG 8
#else
@@ -109,6 +122,17 @@
#endif
#endif // defined(__hpux)
#endif // !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LLONG)
#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_POINTER) && defined(UINTPTR_MAX)
#if (UINTPTR_MAX + 0) == 0xffff
#define BOOST_ATOMIC_DETAIL_SIZEOF_POINTER 2
#elif (UINTPTR_MAX + 0) == 0xffffffff
#define BOOST_ATOMIC_DETAIL_SIZEOF_POINTER 4
#elif (UINTPTR_MAX + 0) == UINT64_C(0xffffffffffffffff)
#define BOOST_ATOMIC_DETAIL_SIZEOF_POINTER 8
#endif
#endif // !defined(BOOST_ATOMIC_DETAIL_SIZEOF_POINTER) && defined(UINTPTR_MAX)
#endif

View File

@@ -6,13 +6,13 @@
* Copyright (c) 2018 Andrey Semashev
*/
/*!
* \file atomic/detail/integral_extend.hpp
* \file atomic/detail/integral_conversions.hpp
*
* This header defines sign/zero extension utilities for Boost.Atomic. The tools assume two's complement signed integer representation.
* This header defines sign/zero extension and truncation utilities for Boost.Atomic. The tools assume two's complement signed integer representation.
*/
#ifndef BOOST_ATOMIC_DETAIL_INTEGRAL_EXTEND_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_INTEGRAL_EXTEND_HPP_INCLUDED_
#ifndef BOOST_ATOMIC_DETAIL_INTEGRAL_CONVERSIONS_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_INTEGRAL_CONVERSIONS_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/bitwise_cast.hpp>
@@ -20,6 +20,7 @@
#include <boost/atomic/detail/type_traits/is_signed.hpp>
#include <boost/atomic/detail/type_traits/make_signed.hpp>
#include <boost/atomic/detail/type_traits/make_unsigned.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
@@ -102,4 +103,6 @@ BOOST_FORCEINLINE Output integral_extend(Input input) BOOST_NOEXCEPT
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_INTEGRAL_EXTEND_HPP_INCLUDED_
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_INTEGRAL_CONVERSIONS_HPP_INCLUDED_

View File

@@ -18,23 +18,31 @@
#if _WIN32_WCE >= 0x600
extern "C" long __cdecl _InterlockedCompareExchange( long volatile *, long, long );
extern "C" long __cdecl _InterlockedExchangeAdd( long volatile *, long );
extern "C" long __cdecl _InterlockedExchange( long volatile *, long );
extern "C" long __cdecl _InterlockedCompareExchange(long volatile*, long, long);
extern "C" long __cdecl _InterlockedExchangeAdd(long volatile*, long);
extern "C" long __cdecl _InterlockedExchange(long volatile*, long);
extern "C" long __cdecl _InterlockedIncrement(long volatile*);
extern "C" long __cdecl _InterlockedDecrement(long volatile*);
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) _InterlockedCompareExchange((long*)(dest), exchange, compare)
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) _InterlockedExchangeAdd((long*)(dest), (long)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) _InterlockedExchange((long*)(dest), (long)(newval))
#define BOOST_ATOMIC_INTERLOCKED_INCREMENT(dest) _InterlockedIncrement((long*)(dest))
#define BOOST_ATOMIC_INTERLOCKED_DECREMENT(dest) _InterlockedDecrement((long*)(dest))
#else // _WIN32_WCE >= 0x600
extern "C" long __cdecl InterlockedCompareExchange( long*, long, long );
extern "C" long __cdecl InterlockedExchangeAdd( long*, long );
extern "C" long __cdecl InterlockedExchange( long*, long );
extern "C" long __cdecl InterlockedCompareExchange(long*, long, long);
extern "C" long __cdecl InterlockedExchangeAdd(long*, long);
extern "C" long __cdecl InterlockedExchange(long*, long);
extern "C" long __cdecl InterlockedIncrement(long*);
extern "C" long __cdecl InterlockedDecrement(long*);
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) InterlockedCompareExchange((long*)(dest), exchange, compare)
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) InterlockedExchangeAdd((long*)(dest), (long)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) InterlockedExchange((long*)(dest), (long)(newval))
#define BOOST_ATOMIC_INTERLOCKED_INCREMENT(dest) InterlockedIncrement((long*)(dest))
#define BOOST_ATOMIC_INTERLOCKED_DECREMENT(dest) InterlockedDecrement((long*)(dest))
#endif // _WIN32_WCE >= 0x600
@@ -45,19 +53,25 @@ extern "C" long __cdecl InterlockedExchange( long*, long );
#if _MSC_VER < 1400
extern "C" long __cdecl _InterlockedCompareExchange( long volatile *, long, long );
extern "C" long __cdecl _InterlockedExchangeAdd( long volatile *, long );
extern "C" long __cdecl _InterlockedExchange( long volatile *, long );
extern "C" long __cdecl _InterlockedCompareExchange(long volatile*, long, long);
extern "C" long __cdecl _InterlockedExchangeAdd(long volatile*, long);
extern "C" long __cdecl _InterlockedExchange(long volatile*, long);
extern "C" long __cdecl _InterlockedIncrement(long volatile*);
extern "C" long __cdecl _InterlockedDecrement(long volatile*);
#if defined(BOOST_MSVC)
#pragma intrinsic(_InterlockedCompareExchange)
#pragma intrinsic(_InterlockedExchangeAdd)
#pragma intrinsic(_InterlockedExchange)
#pragma intrinsic(_InterlockedIncrement)
#pragma intrinsic(_InterlockedDecrement)
#endif
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) _InterlockedCompareExchange((long*)(dest), exchange, compare)
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) _InterlockedExchangeAdd((long*)(dest), (long)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) _InterlockedExchange((long*)(dest), (long)(newval))
#define BOOST_ATOMIC_INTERLOCKED_INCREMENT(dest) _InterlockedIncrement((long*)(dest))
#define BOOST_ATOMIC_INTERLOCKED_DECREMENT(dest) _InterlockedDecrement((long*)(dest))
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) ((void*)BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE((long*)(dest), (long)(exchange), (long)(compare)))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, exchange) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE((long*)(dest), (long)(exchange)))
@@ -70,6 +84,8 @@ extern "C" long __cdecl _InterlockedExchange( long volatile *, long );
#pragma intrinsic(_InterlockedCompareExchange)
#pragma intrinsic(_InterlockedExchangeAdd)
#pragma intrinsic(_InterlockedExchange)
#pragma intrinsic(_InterlockedIncrement)
#pragma intrinsic(_InterlockedDecrement)
#pragma intrinsic(_InterlockedAnd)
#pragma intrinsic(_InterlockedOr)
#pragma intrinsic(_InterlockedXor)
@@ -80,6 +96,8 @@ extern "C" long __cdecl _InterlockedExchange( long volatile *, long );
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) _InterlockedCompareExchange((long*)(dest), (long)(exchange), (long)(compare))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) _InterlockedExchangeAdd((long*)(dest), (long)(addend))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) _InterlockedExchange((long*)(dest), (long)(newval))
#define BOOST_ATOMIC_INTERLOCKED_INCREMENT(dest) _InterlockedIncrement((long*)(dest))
#define BOOST_ATOMIC_INTERLOCKED_DECREMENT(dest) _InterlockedDecrement((long*)(dest))
#define BOOST_ATOMIC_INTERLOCKED_AND(dest, arg) _InterlockedAnd((long*)(dest), (long)(arg))
#define BOOST_ATOMIC_INTERLOCKED_OR(dest, arg) _InterlockedOr((long*)(dest), (long)(arg))
#define BOOST_ATOMIC_INTERLOCKED_XOR(dest, arg) _InterlockedXor((long*)(dest), (long)(arg))
@@ -441,6 +459,8 @@ extern "C" long __cdecl _InterlockedExchange( long volatile *, long );
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) InterlockedCompareExchange((long*)(dest), (long)(exchange), (long)(compare))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) InterlockedExchange((long*)(dest), (long)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) InterlockedExchangeAdd((long*)(dest), (long)(addend))
#define BOOST_ATOMIC_INTERLOCKED_INCREMENT(dest) InterlockedIncrement((long*)(dest))
#define BOOST_ATOMIC_INTERLOCKED_DECREMENT(dest) InterlockedDecrement((long*)(dest))
#if defined(_WIN64)
@@ -477,10 +497,14 @@ extern "C" {
BOOST_ATOMIC_INTERLOCKED_IMPORT long __stdcall InterlockedCompareExchange(long volatile*, long, long);
BOOST_ATOMIC_INTERLOCKED_IMPORT long __stdcall InterlockedExchange(long volatile*, long);
BOOST_ATOMIC_INTERLOCKED_IMPORT long __stdcall InterlockedExchangeAdd(long volatile*, long);
BOOST_ATOMIC_INTERLOCKED_IMPORT long __stdcall InterlockedIncrement(long volatile*, long);
BOOST_ATOMIC_INTERLOCKED_IMPORT long __stdcall InterlockedDecrement(long volatile*, long);
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) boost::atomics::detail::InterlockedCompareExchange((long*)(dest), (long)(exchange), (long)(compare))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) boost::atomics::detail::InterlockedExchange((long*)(dest), (long)(newval))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) boost::atomics::detail::InterlockedExchangeAdd((long*)(dest), (long)(addend))
#define BOOST_ATOMIC_INTERLOCKED_INCREMENT(dest) boost::atomics::detail::InterlockedIncrement((long*)(dest))
#define BOOST_ATOMIC_INTERLOCKED_DECREMENT(dest) boost::atomics::detail::InterlockedDecrement((long*)(dest))
#if defined(_WIN64)
@@ -488,8 +512,8 @@ BOOST_ATOMIC_INTERLOCKED_IMPORT __int64 __stdcall InterlockedCompareExchange64(_
BOOST_ATOMIC_INTERLOCKED_IMPORT __int64 __stdcall InterlockedExchange64(__int64 volatile*, __int64);
BOOST_ATOMIC_INTERLOCKED_IMPORT __int64 __stdcall InterlockedExchangeAdd64(__int64 volatile*, __int64);
BOOST_ATOMIC_INTERLOCKED_IMPORT void* __stdcall InterlockedCompareExchangePointer(void* volatile *, void*, void*);
BOOST_ATOMIC_INTERLOCKED_IMPORT void* __stdcall InterlockedExchangePointer(void* volatile *, void*);
BOOST_ATOMIC_INTERLOCKED_IMPORT void* __stdcall InterlockedCompareExchangePointer(void* volatile*, void*, void*);
BOOST_ATOMIC_INTERLOCKED_IMPORT void* __stdcall InterlockedExchangePointer(void* volatile*, void*);
#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(dest, exchange, compare) boost::atomics::detail::InterlockedCompareExchange64((__int64*)(dest), (__int64)(exchange), (__int64)(compare))
#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(dest, newval) boost::atomics::detail::InterlockedExchange64((__int64*)(dest), (__int64)(newval))

View File

@@ -0,0 +1,46 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/intptr.hpp
*
* This header defines (u)intptr_t types.
*/
#ifndef BOOST_ATOMIC_DETAIL_INTPTR_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_INTPTR_HPP_INCLUDED_
#include <boost/cstdint.hpp>
#if defined(BOOST_HAS_INTPTR_T)
#include <cstddef>
#endif
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
#if !defined(BOOST_HAS_INTPTR_T)
using boost::uintptr_t;
using boost::intptr_t;
#else
typedef std::size_t uintptr_t;
typedef std::ptrdiff_t intptr_t;
#endif
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_INTPTR_HPP_INCLUDED_

View File

@@ -0,0 +1,151 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2011 Helge Bahmann
* Copyright (c) 2013-2014, 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/lock_pool.hpp
*
* This header contains declaration of the lock pool used to emulate atomic ops.
*/
#ifndef BOOST_ATOMIC_DETAIL_LOCK_POOL_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_LOCK_POOL_HPP_INCLUDED_
#include <cstddef>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/link.hpp>
#include <boost/atomic/detail/intptr.hpp>
#if defined(BOOST_WINDOWS)
#include <boost/winapi/thread.hpp>
#elif defined(BOOST_HAS_NANOSLEEP)
#include <time.h>
#else
#include <unistd.h>
#endif
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
BOOST_FORCEINLINE void wait_some() BOOST_NOEXCEPT
{
#if defined(BOOST_WINDOWS)
boost::winapi::SwitchToThread();
#elif defined(BOOST_HAS_NANOSLEEP)
// Do not use sched_yield or pthread_yield as at least on Linux it doesn't block the thread if there are no other
// pending threads on the current CPU. Proper sleeping is guaranteed to block the thread, which allows other threads
// to potentially migrate to this CPU and complete the tasks we're waiting for.
struct ::timespec ts = {};
ts.tv_sec = 0;
ts.tv_nsec = 1000;
::nanosleep(&ts, NULL);
#else
::usleep(1);
#endif
}
namespace lock_pool {
BOOST_ATOMIC_DECL void* short_lock(atomics::detail::uintptr_t h) BOOST_NOEXCEPT;
BOOST_ATOMIC_DECL void* long_lock(atomics::detail::uintptr_t h) BOOST_NOEXCEPT;
BOOST_ATOMIC_DECL void unlock(void* ls) BOOST_NOEXCEPT;
BOOST_ATOMIC_DECL void* allocate_wait_state(void* ls, const volatile void* addr) BOOST_NOEXCEPT;
BOOST_ATOMIC_DECL void free_wait_state(void* ls, void* ws) BOOST_NOEXCEPT;
BOOST_ATOMIC_DECL void wait(void* ls, void* ws) BOOST_NOEXCEPT;
BOOST_ATOMIC_DECL void notify_one(void* ls, const volatile void* addr) BOOST_NOEXCEPT;
BOOST_ATOMIC_DECL void notify_all(void* ls, const volatile void* addr) BOOST_NOEXCEPT;
BOOST_ATOMIC_DECL void thread_fence() BOOST_NOEXCEPT;
BOOST_ATOMIC_DECL void signal_fence() BOOST_NOEXCEPT;
template< std::size_t Alignment >
BOOST_FORCEINLINE atomics::detail::uintptr_t hash_ptr(const volatile void* addr) BOOST_NOEXCEPT
{
atomics::detail::uintptr_t ptr = (atomics::detail::uintptr_t)addr;
atomics::detail::uintptr_t h = ptr / Alignment;
// Since many malloc/new implementations return pointers with higher alignment
// than indicated by Alignment, it makes sense to mix higher bits
// into the lower ones. On 64-bit platforms, malloc typically aligns to 16 bytes,
// on 32-bit - to 8 bytes.
BOOST_CONSTEXPR_OR_CONST std::size_t malloc_alignment = sizeof(void*) >= 8u ? 16u : 8u;
BOOST_IF_CONSTEXPR (Alignment != malloc_alignment)
h ^= ptr / malloc_alignment;
return h;
}
template< std::size_t Alignment, bool LongLock = false >
class scoped_lock
{
private:
void* m_lock;
public:
explicit scoped_lock(const volatile void* addr) BOOST_NOEXCEPT
{
atomics::detail::uintptr_t h = lock_pool::hash_ptr< Alignment >(addr);
BOOST_IF_CONSTEXPR (!LongLock)
m_lock = lock_pool::short_lock(h);
else
m_lock = lock_pool::long_lock(h);
}
~scoped_lock() BOOST_NOEXCEPT
{
lock_pool::unlock(m_lock);
}
void* get_lock_state() const BOOST_NOEXCEPT
{
return m_lock;
}
BOOST_DELETED_FUNCTION(scoped_lock(scoped_lock const&))
BOOST_DELETED_FUNCTION(scoped_lock& operator=(scoped_lock const&))
};
template< std::size_t Alignment >
class scoped_wait_state :
public scoped_lock< Alignment, true >
{
private:
void* m_wait_state;
public:
explicit scoped_wait_state(const volatile void* addr) BOOST_NOEXCEPT :
scoped_lock< Alignment, true >(addr)
{
m_wait_state = lock_pool::allocate_wait_state(this->get_lock_state(), addr);
}
~scoped_wait_state() BOOST_NOEXCEPT
{
lock_pool::free_wait_state(this->get_lock_state(), m_wait_state);
}
void wait() BOOST_NOEXCEPT
{
lock_pool::wait(this->get_lock_state(), m_wait_state);
}
BOOST_DELETED_FUNCTION(scoped_wait_state(scoped_wait_state const&))
BOOST_DELETED_FUNCTION(scoped_wait_state& operator=(scoped_wait_state const&))
};
} // namespace lock_pool
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_LOCK_POOL_HPP_INCLUDED_

View File

@@ -1,51 +0,0 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2011 Helge Bahmann
* Copyright (c) 2013-2014 Andrey Semashev
*/
/*!
* \file atomic/detail/lockpool.hpp
*
* This header contains declaration of the lockpool used to emulate atomic ops.
*/
#ifndef BOOST_ATOMIC_DETAIL_LOCKPOOL_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_LOCKPOOL_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/link.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
struct lockpool
{
class scoped_lock
{
void* m_lock;
public:
explicit BOOST_ATOMIC_DECL scoped_lock(const volatile void* addr) BOOST_NOEXCEPT;
BOOST_ATOMIC_DECL ~scoped_lock() BOOST_NOEXCEPT;
BOOST_DELETED_FUNCTION(scoped_lock(scoped_lock const&))
BOOST_DELETED_FUNCTION(scoped_lock& operator=(scoped_lock const&))
};
static BOOST_ATOMIC_DECL void thread_fence() BOOST_NOEXCEPT;
static BOOST_ATOMIC_DECL void signal_fence() BOOST_NOEXCEPT;
};
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_LOCKPOOL_HPP_INCLUDED_

View File

@@ -0,0 +1,47 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/memory_order_utils.hpp
*
* This header contains utilities related to memory order constants.
*/
#ifndef BOOST_ATOMIC_DETAIL_MEMORY_ORDER_UTILS_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_MEMORY_ORDER_UTILS_HPP_INCLUDED_
#include <boost/memory_order.hpp>
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
BOOST_FORCEINLINE BOOST_CONSTEXPR memory_order deduce_failure_order(memory_order order) BOOST_NOEXCEPT
{
return order == memory_order_acq_rel ? memory_order_acquire : (order == memory_order_release ? memory_order_relaxed : order);
}
BOOST_FORCEINLINE BOOST_CONSTEXPR bool cas_failure_order_must_not_be_stronger_than_success_order(memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
{
// 15 == (memory_order_seq_cst | memory_order_consume), see memory_order.hpp
// Given the enum values we can test the strength of memory order requirements with this single condition.
return (static_cast< unsigned int >(failure_order) & 15u) <= (static_cast< unsigned int >(success_order) & 15u);
}
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_MEMORY_ORDER_UTILS_HPP_INCLUDED_

View File

@@ -0,0 +1,43 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2020 Andrey Semashev
*/
/*!
* \file atomic/detail/once_flag.hpp
*
* This header declares \c once_flag structure for controlling one time initialization
*/
#ifndef BOOST_ATOMIC_DETAIL_ONCE_FLAG_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_ONCE_FLAG_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/aligned_variable.hpp>
#include <boost/atomic/detail/core_operations.hpp>
#include <boost/atomic/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
typedef atomics::detail::core_operations< 1u, false, false > once_flag_operations;
struct once_flag
{
BOOST_ATOMIC_DETAIL_ALIGNED_VAR(once_flag_operations::storage_alignment, once_flag_operations::storage_type, m_flag);
};
} // namespace detail
} // namespace atomics
} // namespace boost
#include <boost/atomic/detail/footer.hpp>
#endif // BOOST_ATOMIC_DETAIL_ONCE_FLAG_HPP_INCLUDED_

View File

@@ -1,24 +0,0 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/operations.hpp
*
* This header defines atomic operations, including the emulated version.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPERATIONS_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPERATIONS_HPP_INCLUDED_
#include <boost/atomic/detail/operations_lockfree.hpp>
#include <boost/atomic/detail/ops_emulated.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#endif // BOOST_ATOMIC_DETAIL_OPERATIONS_HPP_INCLUDED_

View File

@@ -1,35 +0,0 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/operations_fwd.hpp
*
* This header contains forward declaration of the \c operations template.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPERATIONS_FWD_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPERATIONS_FWD_HPP_INCLUDED_
#include <cstddef>
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
template< std::size_t Size, bool Signed >
struct operations;
} // namespace detail
} // namespace atomics
} // namespace boost
#endif // BOOST_ATOMIC_DETAIL_OPERATIONS_FWD_HPP_INCLUDED_

View File

@@ -1,30 +0,0 @@
/*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Copyright (c) 2014 Andrey Semashev
*/
/*!
* \file atomic/detail/operations_lockfree.hpp
*
* This header defines lockfree atomic operations.
*/
#ifndef BOOST_ATOMIC_DETAIL_OPERATIONS_LOCKFREE_HPP_INCLUDED_
#define BOOST_ATOMIC_DETAIL_OPERATIONS_LOCKFREE_HPP_INCLUDED_
#include <boost/atomic/detail/config.hpp>
#include <boost/atomic/detail/platform.hpp>
#if !defined(BOOST_ATOMIC_EMULATED)
#include BOOST_ATOMIC_DETAIL_BACKEND_HEADER(boost/atomic/detail/ops_)
#else
#include <boost/atomic/detail/operations_fwd.hpp>
#endif
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#endif // BOOST_ATOMIC_DETAIL_OPERATIONS_LOCKFREE_HPP_INCLUDED_

Some files were not shown because too many files have changed in this diff Show More