]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7S__) | |
15 | ||
16 | # define BOOST_SP_ARM_BARRIER "dmb" | |
17 | # define BOOST_SP_ARM_HAS_LDREX | |
18 | ||
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__) | |
20 | ||
21 | # define BOOST_SP_ARM_BARRIER "mcr p15, 0, r0, c7, c10, 5" | |
22 | # define BOOST_SP_ARM_HAS_LDREX | |
23 | ||
24 | #else | |
25 | ||
26 | # define BOOST_SP_ARM_BARRIER "" | |
27 | ||
28 | #endif | |
29 | ||
30 | namespace boost | |
31 | { | |
32 | ||
33 | namespace detail | |
34 | { | |
35 | ||
36 | class spinlock | |
37 | { | |
38 | public: | |
39 | ||
40 | int v_; | |
41 | ||
42 | public: | |
43 | ||
44 | bool try_lock() | |
45 | { | |
46 | int r; | |
47 | ||
48 | #ifdef BOOST_SP_ARM_HAS_LDREX | |
49 | ||
50 | __asm__ __volatile__( | |
51 | "ldrex %0, [%2]; \n" | |
52 | "cmp %0, %1; \n" | |
53 | "strexne %0, %1, [%2]; \n" | |
54 | BOOST_SP_ARM_BARRIER : | |
55 | "=&r"( r ): // outputs | |
56 | "r"( 1 ), "r"( &v_ ): // inputs | |
57 | "memory", "cc" ); | |
58 | ||
59 | #else | |
60 | ||
61 | __asm__ __volatile__( | |
62 | "swp %0, %1, [%2];\n" | |
63 | BOOST_SP_ARM_BARRIER : | |
64 | "=&r"( r ): // outputs | |
65 | "r"( 1 ), "r"( &v_ ): // inputs | |
66 | "memory", "cc" ); | |
67 | ||
68 | #endif | |
69 | ||
70 | return r == 0; | |
71 | } | |
72 | ||
73 | void lock() | |
74 | { | |
75 | for( unsigned k = 0; !try_lock(); ++k ) | |
76 | { | |
77 | boost::detail::yield( k ); | |
78 | } | |
79 | } | |
80 | ||
81 | void unlock() | |
82 | { | |
83 | __asm__ __volatile__( BOOST_SP_ARM_BARRIER ::: "memory" ); | |
84 | *const_cast< int volatile* >( &v_ ) = 0; | |
85 | __asm__ __volatile__( BOOST_SP_ARM_BARRIER ::: "memory" ); | |
86 | } | |
87 | ||
88 | public: | |
89 | ||
90 | class scoped_lock | |
91 | { | |
92 | private: | |
93 | ||
94 | spinlock & sp_; | |
95 | ||
96 | scoped_lock( scoped_lock const & ); | |
97 | scoped_lock & operator=( scoped_lock const & ); | |
98 | ||
99 | public: | |
100 | ||
101 | explicit scoped_lock( spinlock & sp ): sp_( sp ) | |
102 | { | |
103 | sp.lock(); | |
104 | } | |
105 | ||
106 | ~scoped_lock() | |
107 | { | |
108 | sp_.unlock(); | |
109 | } | |
110 | }; | |
111 | }; | |
112 | ||
113 | } // namespace detail | |
114 | } // namespace boost | |
115 | ||
116 | #define BOOST_DETAIL_SPINLOCK_INIT {0} | |
117 | ||
118 | #undef BOOST_SP_ARM_BARRIER | |
119 | #undef BOOST_SP_ARM_HAS_LDREX | |
120 | ||
121 | #endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED |