diff --git a/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp b/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp new file mode 100644 index 0000000..e618f6e --- /dev/null +++ b/include/boost/smart_ptr/detail/spinlock_gcc_arm.hpp @@ -0,0 +1,128 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED + +// +// Copyright (c) 2008, 2011 Peter Dimov +// +// 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 + +#if defined(BOOST_SP_REPORT_IMPLEMENTATION) + +#include +BOOST_PRAGMA_MESSAGE("Using g++/ARM spinlock") + +#endif + +#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7S__) + +# define BOOST_SP_ARM_BARRIER "dmb" +# define BOOST_SP_ARM_HAS_LDREX + +#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) + +# define BOOST_SP_ARM_BARRIER "mcr p15, 0, r0, c7, c10, 5" +# define BOOST_SP_ARM_HAS_LDREX + +#else + +# define BOOST_SP_ARM_BARRIER "" + +#endif + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + int v_; + +public: + + bool try_lock() + { + int r; + +#ifdef BOOST_SP_ARM_HAS_LDREX + + __asm__ __volatile__( + "ldrex %0, [%2]; \n" + "cmp %0, %1; \n" + "strexne %0, %1, [%2]; \n" + BOOST_SP_ARM_BARRIER : + "=&r"( r ): // outputs + "r"( 1 ), "r"( &v_ ): // inputs + "memory", "cc" ); + +#else + + __asm__ __volatile__( + "swp %0, %1, [%2];\n" + BOOST_SP_ARM_BARRIER : + "=&r"( r ): // outputs + "r"( 1 ), "r"( &v_ ): // inputs + "memory", "cc" ); + +#endif + + return r == 0; + } + + void lock() + { + for( unsigned k = 0; !try_lock(); ++k ) + { + boost::detail::yield( k ); + } + } + + void unlock() + { + __asm__ __volatile__( BOOST_SP_ARM_BARRIER ::: "memory" ); + *const_cast< int volatile* >( &v_ ) = 0; + __asm__ __volatile__( BOOST_SP_ARM_BARRIER ::: "memory" ); + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT {0} + +#undef BOOST_SP_ARM_BARRIER +#undef BOOST_SP_ARM_HAS_LDREX + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/spinlock_gcc_atomic.hpp b/include/boost/smart_ptr/detail/spinlock_gcc_atomic.hpp new file mode 100644 index 0000000..d87b844 --- /dev/null +++ b/include/boost/smart_ptr/detail/spinlock_gcc_atomic.hpp @@ -0,0 +1,94 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ATOMIC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ATOMIC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// Copyright 2008, 2020 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +#if defined(BOOST_SP_REPORT_IMPLEMENTATION) + +#include +BOOST_PRAGMA_MESSAGE("Using __atomic spinlock") + +#endif + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + // `bool` alignment is required for Apple PPC32 + // https://github.com/boostorg/smart_ptr/issues/105 + // https://github.com/PurpleI2P/i2pd/issues/1726 + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107590 + + union + { + unsigned char v_; + bool align_; + }; + +public: + + bool try_lock() + { + return __atomic_test_and_set( &v_, __ATOMIC_ACQUIRE ) == 0; + } + + void lock() + { + for( unsigned k = 0; !try_lock(); ++k ) + { + boost::detail::yield( k ); + } + } + + void unlock() + { + __atomic_clear( &v_, __ATOMIC_RELEASE ); + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT {{0}} + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ATOMIC_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/spinlock_nt.hpp b/include/boost/smart_ptr/detail/spinlock_nt.hpp new file mode 100644 index 0000000..ce23761 --- /dev/null +++ b/include/boost/smart_ptr/detail/spinlock_nt.hpp @@ -0,0 +1,96 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// Copyright (c) 2008 Peter Dimov +// +// 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 + +#if defined(BOOST_SP_REPORT_IMPLEMENTATION) + +#include +BOOST_PRAGMA_MESSAGE("Using single-threaded spinlock emulation") + +#endif + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + bool locked_; + +public: + + inline bool try_lock() + { + if( locked_ ) + { + return false; + } + else + { + locked_ = true; + return true; + } + } + + inline void lock() + { + BOOST_ASSERT( !locked_ ); + locked_ = true; + } + + inline void unlock() + { + BOOST_ASSERT( locked_ ); + locked_ = false; + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT { false } + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/spinlock_pt.hpp b/include/boost/smart_ptr/detail/spinlock_pt.hpp new file mode 100644 index 0000000..a7f8a81 --- /dev/null +++ b/include/boost/smart_ptr/detail/spinlock_pt.hpp @@ -0,0 +1,86 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// Copyright (c) 2008 Peter Dimov +// +// 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 + +#if defined(BOOST_SP_REPORT_IMPLEMENTATION) + +#include +BOOST_PRAGMA_MESSAGE("Using pthread_mutex spinlock emulation") + +#endif + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + pthread_mutex_t v_; + +public: + + bool try_lock() + { + return pthread_mutex_trylock( &v_ ) == 0; + } + + void lock() + { + pthread_mutex_lock( &v_ ); + } + + void unlock() + { + pthread_mutex_unlock( &v_ ); + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT { PTHREAD_MUTEX_INITIALIZER } + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/spinlock_sync.hpp b/include/boost/smart_ptr/detail/spinlock_sync.hpp new file mode 100644 index 0000000..cbfdd94 --- /dev/null +++ b/include/boost/smart_ptr/detail/spinlock_sync.hpp @@ -0,0 +1,94 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// Copyright (c) 2008 Peter Dimov +// +// 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 + +#if defined( __ia64__ ) && defined( __INTEL_COMPILER ) +# include +#endif + +#if defined(BOOST_SP_REPORT_IMPLEMENTATION) + +#include +BOOST_PRAGMA_MESSAGE("Using __sync spinlock") + +#endif + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + unsigned char v_; + +public: + + bool try_lock() + { + int r = __sync_lock_test_and_set( &v_, 1 ); + return r == 0; + } + + void lock() + { + for( unsigned k = 0; !try_lock(); ++k ) + { + boost::detail::yield( k ); + } + } + + void unlock() + { + __sync_lock_release( &v_ ); + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT {0} + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/spinlock_w32.hpp b/include/boost/smart_ptr/detail/spinlock_w32.hpp new file mode 100644 index 0000000..39092ce --- /dev/null +++ b/include/boost/smart_ptr/detail/spinlock_w32.hpp @@ -0,0 +1,120 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// Copyright (c) 2008 Peter Dimov +// +// 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 +#include + +#if defined(BOOST_SP_REPORT_IMPLEMENTATION) + +#include +BOOST_PRAGMA_MESSAGE("Using Win32 spinlock") + +#endif + +// BOOST_COMPILER_FENCE + +#if defined(__INTEL_COMPILER) + +#define BOOST_COMPILER_FENCE __memory_barrier(); + +#elif defined( _MSC_VER ) && _MSC_VER >= 1310 + +extern "C" void _ReadWriteBarrier(); +#pragma intrinsic( _ReadWriteBarrier ) + +#define BOOST_COMPILER_FENCE _ReadWriteBarrier(); + +#elif defined(__GNUC__) + +#define BOOST_COMPILER_FENCE __asm__ __volatile__( "" : : : "memory" ); + +#else + +#define BOOST_COMPILER_FENCE + +#endif + +// + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + long v_; + +public: + + bool try_lock() + { + long r = BOOST_SP_INTERLOCKED_EXCHANGE( &v_, 1 ); + + BOOST_COMPILER_FENCE + + return r == 0; + } + + void lock() + { + for( unsigned k = 0; !try_lock(); ++k ) + { + boost::detail::yield( k ); + } + } + + void unlock() + { + BOOST_COMPILER_FENCE + *const_cast< long volatile* >( &v_ ) = 0; + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT {0} + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED