Home ⌂Doc Index ◂Up ▴
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-2020 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 #ifndef __TBB__x86_rtm_rw_mutex_impl_H
18 #define __TBB__x86_rtm_rw_mutex_impl_H
19 
20 #ifndef __TBB_spin_rw_mutex_H
21 #error Do not #include this internal file directly; use public TBB headers instead.
22 #endif
23 
24 #if __TBB_TSX_AVAILABLE
25 
26 #include "../tbb_stddef.h"
27 #include "../tbb_machine.h"
28 #include "../tbb_profiling.h"
29 #include "../spin_rw_mutex.h"
30 
31 namespace tbb {
32 namespace interface8 {
33 namespace internal {
34 
35 enum RTM_type {
36  RTM_not_in_mutex,
37  RTM_transacting_reader,
38  RTM_transacting_writer,
39  RTM_real_reader,
40  RTM_real_writer
41 };
42 
43 static const unsigned long speculation_granularity = 64;
44 
46 // writer-preference
48 class x86_rtm_rw_mutex: private spin_rw_mutex {
49 #if __TBB_USE_X86_RTM_RW_MUTEX || __TBB_GCC_VERSION < 40000
50 // bug in gcc 3.x.x causes syntax error in spite of the friend declaration below.
51 // Make the scoped_lock public in that case.
52 public:
53 #else
54 private:
55 #endif
56  friend class interface7::internal::padded_mutex<x86_rtm_rw_mutex,true>;
57  class scoped_lock; // should be private
58  friend class scoped_lock;
59 private:
61 
63  void __TBB_EXPORTED_METHOD internal_construct();
64 
66  // only_speculate == true if we're doing a try_lock, else false.
67  void __TBB_EXPORTED_METHOD internal_acquire_writer(x86_rtm_rw_mutex::scoped_lock&, bool only_speculate=false);
68 
70  // only_speculate == true if we're doing a try_lock, else false.
71  void __TBB_EXPORTED_METHOD internal_acquire_reader(x86_rtm_rw_mutex::scoped_lock&, bool only_speculate=false);
72 
74  bool __TBB_EXPORTED_METHOD internal_upgrade( x86_rtm_rw_mutex::scoped_lock& );
75 
77  bool __TBB_EXPORTED_METHOD internal_downgrade( x86_rtm_rw_mutex::scoped_lock& );
78 
80  bool __TBB_EXPORTED_METHOD internal_try_acquire_writer( x86_rtm_rw_mutex::scoped_lock& );
81 
83  void __TBB_EXPORTED_METHOD internal_release( x86_rtm_rw_mutex::scoped_lock& );
84 
85  static x86_rtm_rw_mutex* internal_get_mutex( const spin_rw_mutex::scoped_lock& lock )
86  {
87  return static_cast<x86_rtm_rw_mutex*>( lock.mutex );
88  }
89  static void internal_set_mutex( spin_rw_mutex::scoped_lock& lock, spin_rw_mutex* mtx )
90  {
91  lock.mutex = mtx;
92  }
94 public:
96  x86_rtm_rw_mutex() {
97  w_flag = false;
98 #if TBB_USE_THREADING_TOOLS
99  internal_construct();
100 #endif
101  }
102 
103 #if TBB_USE_ASSERT
104  ~x86_rtm_rw_mutex() {}
106 #endif /* TBB_USE_ASSERT */
107 
108  // Mutex traits
109  static const bool is_rw_mutex = true;
110  static const bool is_recursive_mutex = false;
111  static const bool is_fair_mutex = false;
112 
113 #if __TBB_USE_X86_RTM_RW_MUTEX || __TBB_GCC_VERSION < 40000
114 #else
115  // by default we will not provide the scoped_lock interface. The user
116  // should use the padded version of the mutex. scoped_lock is used in
117  // padded_mutex template.
118 private:
119 #endif
120 
123  // Speculation-enabled scoped lock for spin_rw_mutex
124  // The idea is to be able to reuse the acquire/release methods of spin_rw_mutex
125  // and its scoped lock wherever possible. The only way to use a speculative lock is to use
126  // a scoped_lock. (because transaction_state must be local)
127 
128  class scoped_lock : tbb::internal::no_copy {
129  friend class x86_rtm_rw_mutex;
130  spin_rw_mutex::scoped_lock my_scoped_lock;
131 
132  RTM_type transaction_state;
133 
134  public:
136 
137  scoped_lock() : my_scoped_lock(), transaction_state(RTM_not_in_mutex) {
138  }
139 
141  scoped_lock( x86_rtm_rw_mutex& m, bool write = true ) : my_scoped_lock(),
142  transaction_state(RTM_not_in_mutex) {
143  acquire(m, write);
144  }
145 
147  ~scoped_lock() {
148  if(transaction_state != RTM_not_in_mutex) release();
149  }
150 
152  void acquire( x86_rtm_rw_mutex& m, bool write = true ) {
153  if( write ) m.internal_acquire_writer(*this);
154  else m.internal_acquire_reader(*this);
155  }
156 
158  void release() {
159  x86_rtm_rw_mutex* mutex = x86_rtm_rw_mutex::internal_get_mutex(my_scoped_lock);
160  __TBB_ASSERT( mutex, "lock is not acquired" );
161  __TBB_ASSERT( transaction_state!=RTM_not_in_mutex, "lock is not acquired" );
162  return mutex->internal_release(*this);
163  }
164 
166 
167  bool upgrade_to_writer() {
168  x86_rtm_rw_mutex* mutex = x86_rtm_rw_mutex::internal_get_mutex(my_scoped_lock);
169  __TBB_ASSERT( mutex, "lock is not acquired" );
170  if (transaction_state == RTM_transacting_writer || transaction_state == RTM_real_writer)
171  return true; // Already a writer
172  return mutex->internal_upgrade(*this);
173  }
174 
176 
177  bool downgrade_to_reader() {
178  x86_rtm_rw_mutex* mutex = x86_rtm_rw_mutex::internal_get_mutex(my_scoped_lock);
179  __TBB_ASSERT( mutex, "lock is not acquired" );
180  if (transaction_state == RTM_transacting_reader || transaction_state == RTM_real_reader)
181  return true; // Already a reader
182  return mutex->internal_downgrade(*this);
183  }
184 
186 
187  bool try_acquire( x86_rtm_rw_mutex& m, bool write = true ) {
188 #if TBB_USE_ASSERT
189  x86_rtm_rw_mutex* mutex = x86_rtm_rw_mutex::internal_get_mutex(my_scoped_lock);
190  __TBB_ASSERT( !mutex, "lock is already acquired" );
191 #endif
192  // have to assign m to our mutex.
193  // cannot set the mutex, because try_acquire in spin_rw_mutex depends on it being NULL.
194  if(write) return m.internal_try_acquire_writer(*this);
195  // speculatively acquire the lock. If this fails, do try_acquire on the spin_rw_mutex.
196  m.internal_acquire_reader(*this, /*only_speculate=*/true);
197  if(transaction_state == RTM_transacting_reader) return true;
198  if( my_scoped_lock.try_acquire(m, false)) {
199  transaction_state = RTM_real_reader;
200  return true;
201  }
202  return false;
203  }
204 
205  }; // class x86_rtm_rw_mutex::scoped_lock
206 
207  // ISO C++0x compatibility methods not provided because we cannot maintain
208  // state about whether a thread is in a transaction.
209 
210 private:
211  char pad[speculation_granularity-sizeof(spin_rw_mutex)]; // padding
212 
213  // If true, writer holds the spin_rw_mutex.
214  tbb::atomic<bool> w_flag; // want this on a separate cache line
215 
216 }; // x86_rtm_rw_mutex
217 
218 } // namespace internal
219 } // namespace interface8
220 } // namespace tbb
221 
222 #endif /* __TBB_TSX_AVAILABLE */
223 #endif /* __TBB__x86_rtm_rw_mutex_impl_H */
spin_rw_mutex_v3 spin_rw_mutex
Definition: spin_rw_mutex.h:33
Release.
Definition: atomic.h:59
Base class for types that should not be copied or assigned.
Definition: tbb_stddef.h:330
#define __TBB_EXPORTED_METHOD
Definition: tbb_stddef.h:98
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:165
Acquire.
Definition: atomic.h:57
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.

Copyright © 2005-2020 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.