Intel(R) Threading Building Blocks Doxygen Documentation version 4.2.3
Loading...
Searching...
No Matches
_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
31namespace tbb {
32namespace interface8 {
33namespace internal {
34
35enum 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
43static const unsigned long speculation_granularity = 64;
44
46// writer-preference
48class 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.
52public:
53#else
54private:
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;
59private:
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 }
94public:
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
105 ~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.
118private:
119#endif
121
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
210private:
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 */
#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
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:34
@ release
Release.
Definition: atomic.h:59
@ acquire
Acquire.
Definition: atomic.h:57
Base class for types that should not be copied or assigned.
Definition: tbb_stddef.h:330

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.