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