Intel(R) Threading Building Blocks Doxygen Documentation  version 4.2.3
_x86_rtm_rw_mutex_impl.h
Go to the documentation of this file.
1 /*
2  Copyright (c) 2005-2019 Intel Corporation
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 
16 
17 
18 
19 */
20 
21 #ifndef __TBB__x86_rtm_rw_mutex_impl_H
22 #define __TBB__x86_rtm_rw_mutex_impl_H
23 
24 #ifndef __TBB_spin_rw_mutex_H
25 #error Do not #include this internal file directly; use public TBB headers instead.
26 #endif
27 
28 #if __TBB_TSX_AVAILABLE
29 
30 #include "../tbb_stddef.h"
31 #include "../tbb_machine.h"
32 #include "../tbb_profiling.h"
33 #include "../spin_rw_mutex.h"
34 
35 namespace tbb {
36 namespace interface8 {
37 namespace internal {
38 
39 enum RTM_type {
40  RTM_not_in_mutex,
41  RTM_transacting_reader,
42  RTM_transacting_writer,
43  RTM_real_reader,
44  RTM_real_writer
45 };
46 
47 static const unsigned long speculation_granularity = 64;
48 
50 // writer-preference
52 class x86_rtm_rw_mutex: private spin_rw_mutex {
53 #if __TBB_USE_X86_RTM_RW_MUTEX || __TBB_GCC_VERSION < 40000
54 // bug in gcc 3.x.x causes syntax error in spite of the friend declaration below.
55 // Make the scoped_lock public in that case.
56 public:
57 #else
58 private:
59 #endif
60  friend class interface7::internal::padded_mutex<x86_rtm_rw_mutex,true>;
61  class scoped_lock; // should be private
62  friend class scoped_lock;
63 private:
65 
67  void __TBB_EXPORTED_METHOD internal_construct();
68 
70  // only_speculate == true if we're doing a try_lock, else false.
71  void __TBB_EXPORTED_METHOD internal_acquire_writer(x86_rtm_rw_mutex::scoped_lock&, bool only_speculate=false);
72 
74  // only_speculate == true if we're doing a try_lock, else false.
75  void __TBB_EXPORTED_METHOD internal_acquire_reader(x86_rtm_rw_mutex::scoped_lock&, bool only_speculate=false);
76 
78  bool __TBB_EXPORTED_METHOD internal_upgrade( x86_rtm_rw_mutex::scoped_lock& );
79 
81  bool __TBB_EXPORTED_METHOD internal_downgrade( x86_rtm_rw_mutex::scoped_lock& );
82 
84  bool __TBB_EXPORTED_METHOD internal_try_acquire_writer( x86_rtm_rw_mutex::scoped_lock& );
85 
87  void __TBB_EXPORTED_METHOD internal_release( x86_rtm_rw_mutex::scoped_lock& );
88 
89  static x86_rtm_rw_mutex* internal_get_mutex( const spin_rw_mutex::scoped_lock& lock )
90  {
91  return static_cast<x86_rtm_rw_mutex*>( lock.mutex );
92  }
93  static void internal_set_mutex( spin_rw_mutex::scoped_lock& lock, spin_rw_mutex* mtx )
94  {
95  lock.mutex = mtx;
96  }
98 public:
100  x86_rtm_rw_mutex() {
101  w_flag = false;
102 #if TBB_USE_THREADING_TOOLS
103  internal_construct();
104 #endif
105  }
106 
107 #if TBB_USE_ASSERT
108  ~x86_rtm_rw_mutex() {}
110 #endif /* TBB_USE_ASSERT */
111 
112  // Mutex traits
113  static const bool is_rw_mutex = true;
114  static const bool is_recursive_mutex = false;
115  static const bool is_fair_mutex = false;
116 
117 #if __TBB_USE_X86_RTM_RW_MUTEX || __TBB_GCC_VERSION < 40000
118 #else
119  // by default we will not provide the scoped_lock interface. The user
120  // should use the padded version of the mutex. scoped_lock is used in
121  // padded_mutex template.
122 private:
123 #endif
124 
127  // Speculation-enabled scoped lock for spin_rw_mutex
128  // The idea is to be able to reuse the acquire/release methods of spin_rw_mutex
129  // and its scoped lock wherever possible. The only way to use a speculative lock is to use
130  // a scoped_lock. (because transaction_state must be local)
131 
132  class scoped_lock : tbb::internal::no_copy {
133  friend class x86_rtm_rw_mutex;
134  spin_rw_mutex::scoped_lock my_scoped_lock;
135 
136  RTM_type transaction_state;
137 
138  public:
140 
141  scoped_lock() : my_scoped_lock(), transaction_state(RTM_not_in_mutex) {
142  }
143 
145  scoped_lock( x86_rtm_rw_mutex& m, bool write = true ) : my_scoped_lock(),
146  transaction_state(RTM_not_in_mutex) {
147  acquire(m, write);
148  }
149 
151  ~scoped_lock() {
152  if(transaction_state != RTM_not_in_mutex) release();
153  }
154 
156  void acquire( x86_rtm_rw_mutex& m, bool write = true ) {
157  if( write ) m.internal_acquire_writer(*this);
158  else m.internal_acquire_reader(*this);
159  }
160 
162  void release() {
163  x86_rtm_rw_mutex* mutex = x86_rtm_rw_mutex::internal_get_mutex(my_scoped_lock);
164  __TBB_ASSERT( mutex, "lock is not acquired" );
165  __TBB_ASSERT( transaction_state!=RTM_not_in_mutex, "lock is not acquired" );
166  return mutex->internal_release(*this);
167  }
168 
170 
171  bool upgrade_to_writer() {
172  x86_rtm_rw_mutex* mutex = x86_rtm_rw_mutex::internal_get_mutex(my_scoped_lock);
173  __TBB_ASSERT( mutex, "lock is not acquired" );
174  if (transaction_state == RTM_transacting_writer || transaction_state == RTM_real_writer)
175  return true; // Already a writer
176  return mutex->internal_upgrade(*this);
177  }
178 
180 
181  bool downgrade_to_reader() {
182  x86_rtm_rw_mutex* mutex = x86_rtm_rw_mutex::internal_get_mutex(my_scoped_lock);
183  __TBB_ASSERT( mutex, "lock is not acquired" );
184  if (transaction_state == RTM_transacting_reader || transaction_state == RTM_real_reader)
185  return true; // Already a reader
186  return mutex->internal_downgrade(*this);
187  }
188 
190 
191  bool try_acquire( x86_rtm_rw_mutex& m, bool write = true ) {
192 #if TBB_USE_ASSERT
193  x86_rtm_rw_mutex* mutex = x86_rtm_rw_mutex::internal_get_mutex(my_scoped_lock);
194  __TBB_ASSERT( !mutex, "lock is already acquired" );
195 #endif
196  // have to assign m to our mutex.
197  // cannot set the mutex, because try_acquire in spin_rw_mutex depends on it being NULL.
198  if(write) return m.internal_try_acquire_writer(*this);
199  // speculatively acquire the lock. If this fails, do try_acquire on the spin_rw_mutex.
200  m.internal_acquire_reader(*this, /*only_speculate=*/true);
201  if(transaction_state == RTM_transacting_reader) return true;
202  if( my_scoped_lock.try_acquire(m, false)) {
203  transaction_state = RTM_real_reader;
204  return true;
205  }
206  return false;
207  }
208 
209  }; // class x86_rtm_rw_mutex::scoped_lock
210 
211  // ISO C++0x compatibility methods not provided because we cannot maintain
212  // state about whether a thread is in a transaction.
213 
214 private:
215  char pad[speculation_granularity-sizeof(spin_rw_mutex)]; // padding
216 
217  // If true, writer holds the spin_rw_mutex.
218  tbb::atomic<bool> w_flag; // want this on a separate cache line
219 
220 }; // x86_rtm_rw_mutex
221 
222 } // namespace internal
223 } // namespace interface8
224 } // namespace tbb
225 
226 #endif /* __TBB_TSX_AVAILABLE */
227 #endif /* __TBB__x86_rtm_rw_mutex_impl_H */
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
Base class for types that should not be copied or assigned.
Definition: tbb_stddef.h:335
Acquire.
Definition: atomic.h:47
#define __TBB_EXPORTED_METHOD
Definition: tbb_stddef.h:102
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void * lock
The graph class.
spin_rw_mutex_v3 spin_rw_mutex
Definition: spin_rw_mutex.h:37
Release.
Definition: atomic.h:49

Copyright © 2005-2019 Intel Corporation. All Rights Reserved.

Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are registered trademarks or trademarks of Intel Corporation or its subsidiaries in the United States and other countries.

* Other names and brands may be claimed as the property of others.