spinlock_gcc_arm.hpp 2.6 KB

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