1 ////////////////////////////////////////////////////////////////////////////////
2 //  Copyright (c) 2011 Bryce Lelbach
3 //  Copyright (c) 2011-2012 Hartmut Kaiser
4 //  Copyright (c) 2008 Peter Dimov
5 //
6 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
7 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 ////////////////////////////////////////////////////////////////////////////////
9 
10 #if !defined(HPX_LCOS_LOCAL_SPINLOCK_NO_BACKOFF)
11 #define HPX_LCOS_LOCAL_SPINLOCK_NO_BACKOFF
12 
13 #include <hpx/config.hpp>
14 #include <hpx/runtime/threads/thread_helpers.hpp>
15 #include <hpx/util/itt_notify.hpp>
16 #include <hpx/util/register_locks.hpp>
17 
18 #if defined(HPX_WINDOWS)
19 #  include <boost/smart_ptr/detail/spinlock.hpp>
20 #  if !defined( BOOST_SP_HAS_SYNC )
21 #    include <hpx/config/compiler_fence.hpp>
22 #    include <boost/detail/interlocked.hpp>
23 #  endif
24 #else
25 #  if !defined(__ANDROID__) && !defined(ANDROID) && !defined(__arm__)
26 #    include <boost/smart_ptr/detail/spinlock.hpp>
27 #    if defined( __ia64__ ) && defined( __INTEL_COMPILER )
28 #      include <ia64intrin.h>
29 #    endif
30 #  endif
31 #endif
32 
33 #include <cstddef>
34 #include <cstdint>
35 
36 ///////////////////////////////////////////////////////////////////////////////
37 namespace hpx { namespace lcos { namespace local
38 {
39     /// boost::mutex-compatible spinlock class
40     struct spinlock_no_backoff
41     {
42     public:
43         HPX_NON_COPYABLE(spinlock_no_backoff);
44 
45     private:
46         std::uint64_t v_;
47 
48     public:
spinlock_no_backoffhpx::lcos::local::spinlock_no_backoff49         spinlock_no_backoff() : v_(0)
50         {
51             HPX_ITT_SYNC_CREATE(this, "hpx::lcos::local::spinlock_no_backoff", "");
52         }
53 
~spinlock_no_backoffhpx::lcos::local::spinlock_no_backoff54         ~spinlock_no_backoff()
55         {
56             HPX_ITT_SYNC_DESTROY(this);
57         }
58 
lockhpx::lcos::local::spinlock_no_backoff59         void lock()
60         {
61             HPX_ITT_SYNC_PREPARE(this);
62 
63             for (std::size_t k = 0; !try_lock(); ++k)
64             {
65             }
66 
67             HPX_ITT_SYNC_ACQUIRED(this);
68             util::register_lock(this);
69         }
70 
try_lockhpx::lcos::local::spinlock_no_backoff71         bool try_lock()
72         {
73             HPX_ITT_SYNC_PREPARE(this);
74 
75 #if !defined( BOOST_SP_HAS_SYNC )
76             std::uint64_t r = BOOST_INTERLOCKED_EXCHANGE(&v_, 1);
77             HPX_COMPILER_FENCE;
78 #else
79             std::uint64_t r = __sync_lock_test_and_set(&v_, 1);
80 #endif
81 
82             if (r == 0) {
83                 HPX_ITT_SYNC_ACQUIRED(this);
84                 util::register_lock(this);
85                 return true;
86             }
87 
88             HPX_ITT_SYNC_CANCEL(this);
89             return false;
90         }
91 
unlockhpx::lcos::local::spinlock_no_backoff92         void unlock()
93         {
94             HPX_ITT_SYNC_RELEASING(this);
95 
96 #if !defined( BOOST_SP_HAS_SYNC )
97             HPX_COMPILER_FENCE;
98             *const_cast<std::uint64_t volatile*>(&v_) = 0;
99 #else
100             __sync_lock_release(&v_);
101 #endif
102 
103             HPX_ITT_SYNC_RELEASED(this);
104             util::unregister_lock(this);
105         }
106     };
107 }}}
108 
109 #endif // HPX_B3A83B49_92E0_4150_A551_488F9F5E1113
110