blob: 7155fbec4aaf28b94356385b574ba7f9966e8449 [file] [log] [blame]
Jeff Thompsonf7d49942013-08-01 16:47:40 -07001#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
Jeff Thompson2277ce52013-08-01 17:34:11 -070012#include <ndnboost/smart_ptr/detail/yield_k.hpp>
Jeff Thompsonf7d49942013-08-01 16:47:40 -070013
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
30namespace ndnboost
31{
32
33namespace detail
34{
35
36class spinlock
37{
38public:
39
40 int v_;
41
42public:
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 ndnboost::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 }
86
87public:
88
89 class scoped_lock
90 {
91 private:
92
93 spinlock & sp_;
94
95 scoped_lock( scoped_lock const & );
96 scoped_lock & operator=( scoped_lock const & );
97
98 public:
99
100 explicit scoped_lock( spinlock & sp ): sp_( sp )
101 {
102 sp.lock();
103 }
104
105 ~scoped_lock()
106 {
107 sp_.unlock();
108 }
109 };
110};
111
112} // namespace detail
113} // namespace ndnboost
114
115#define BOOST_DETAIL_SPINLOCK_INIT {0}
116
117#undef BOOST_SP_ARM_BARRIER
118#undef BOOST_SP_ARM_HAS_LDREX
119
120#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED