1 #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED 2 #define BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED 3 4 // 5 // Copyright (c) 2008, 2011 Peter Dimov 6 // 7 // Distributed under the Boost Software License, Version 1.0. 8 // See accompanying file LICENSE_1_0.txt or copy at 9 // http://www.boost.org/LICENSE_1_0.txt) 10 // 11 12 #include <boost/smart_ptr/detail/yield_k.hpp> 13 14 #if defined(BOOST_SP_REPORT_IMPLEMENTATION) 15 16 #include <boost/config/pragma_message.hpp> 17 BOOST_PRAGMA_MESSAGE("Using g++/ARM spinlock") 18 19 #endif 20 21 #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__) 22 23 # define BOOST_SP_ARM_BARRIER "dmb" 24 # define BOOST_SP_ARM_HAS_LDREX 25 26 #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__) 27 28 # define BOOST_SP_ARM_BARRIER "mcr p15, 0, r0, c7, c10, 5" 29 # define BOOST_SP_ARM_HAS_LDREX 30 31 #else 32 33 # define BOOST_SP_ARM_BARRIER "" 34 35 #endif 36 37 namespace boost 38 { 39 40 namespace detail 41 { 42 43 class spinlock 44 { 45 public: 46 47 int v_; 48 49 public: 50 try_lock()51 bool try_lock() 52 { 53 int r; 54 55 #ifdef BOOST_SP_ARM_HAS_LDREX 56 57 __asm__ __volatile__( 58 "ldrex %0, [%2]; \n" 59 "cmp %0, %1; \n" 60 "strexne %0, %1, [%2]; \n" 61 BOOST_SP_ARM_BARRIER : 62 "=&r"( r ): // outputs 63 "r"( 1 ), "r"( &v_ ): // inputs 64 "memory", "cc" ); 65 66 #else 67 68 __asm__ __volatile__( 69 "swp %0, %1, [%2];\n" 70 BOOST_SP_ARM_BARRIER : 71 "=&r"( r ): // outputs 72 "r"( 1 ), "r"( &v_ ): // inputs 73 "memory", "cc" ); 74 75 #endif 76 77 return r == 0; 78 } 79 lock()80 void lock() 81 { 82 for( unsigned k = 0; !try_lock(); ++k ) 83 { 84 boost::detail::yield( k ); 85 } 86 } 87 unlock()88 void unlock() 89 { 90 __asm__ __volatile__( BOOST_SP_ARM_BARRIER ::: "memory" ); 91 *const_cast< int volatile* >( &v_ ) = 0; 92 __asm__ __volatile__( BOOST_SP_ARM_BARRIER ::: "memory" ); 93 } 94 95 public: 96 97 class scoped_lock 98 { 99 private: 100 101 spinlock & sp_; 102 103 scoped_lock( scoped_lock const & ); 104 scoped_lock & operator=( scoped_lock const & ); 105 106 public: 107 scoped_lock(spinlock & sp)108 explicit scoped_lock( spinlock & sp ): sp_( sp ) 109 { 110 sp.lock(); 111 } 112 ~scoped_lock()113 ~scoped_lock() 114 { 115 sp_.unlock(); 116 } 117 }; 118 }; 119 120 } // namespace detail 121 } // namespace boost 122 123 #define BOOST_DETAIL_SPINLOCK_INIT {0} 124 125 #undef BOOST_SP_ARM_BARRIER 126 #undef BOOST_SP_ARM_HAS_LDREX 127 128 #endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED 129