1 | /***************************************************************************** |
2 | |
3 | Copyright (c) 2012, 2015, Oracle and/or its affiliates. All Rights Reserved. |
4 | Copyright (c) 2017, MariaDB Corporation. |
5 | |
6 | This program is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU General Public License as published by the Free Software |
8 | Foundation; version 2 of the License. |
9 | |
10 | This program is distributed in the hope that it will be useful, but WITHOUT |
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
12 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU General Public License along with |
15 | this program; if not, write to the Free Software Foundation, Inc., |
16 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA |
17 | |
18 | *****************************************************************************/ |
19 | |
20 | /******************************************************************//** |
21 | @file include/ut0mutex.h |
22 | Policy based mutexes. |
23 | |
24 | Created 2012-03-24 Sunny Bains. |
25 | ***********************************************************************/ |
26 | |
27 | #ifndef UNIV_INNOCHECKSUM |
28 | |
29 | #ifndef ut0mutex_h |
30 | #define ut0mutex_h |
31 | |
32 | extern uint srv_spin_wait_delay; |
33 | extern ulong srv_n_spin_wait_rounds; |
34 | |
35 | #include "sync0policy.h" |
36 | #include "ib0mutex.h" |
37 | #include <set> |
38 | |
39 | /** Create a typedef using the MutexType<PolicyType> |
40 | @param[in] M Mutex type |
41 | @param[in[ P Policy type |
42 | @param[in] T The resulting typedef alias */ |
43 | #define UT_MUTEX_TYPE(M, P, T) typedef PolicyMutex<M<P> > T; |
44 | |
45 | typedef OSMutex EventMutex; |
46 | |
47 | # ifdef HAVE_IB_LINUX_FUTEX |
48 | UT_MUTEX_TYPE(TTASFutexMutex, GenericPolicy, FutexMutex); |
49 | UT_MUTEX_TYPE(TTASFutexMutex, BlockMutexPolicy, BlockFutexMutex); |
50 | # endif /* HAVE_IB_LINUX_FUTEX */ |
51 | |
52 | UT_MUTEX_TYPE(TTASMutex, GenericPolicy, SpinMutex); |
53 | UT_MUTEX_TYPE(TTASMutex, BlockMutexPolicy, BlockSpinMutex); |
54 | |
55 | UT_MUTEX_TYPE(OSTrackMutex, GenericPolicy, SysMutex); |
56 | UT_MUTEX_TYPE(OSTrackMutex, BlockMutexPolicy, BlockSysMutex); |
57 | |
58 | UT_MUTEX_TYPE(TTASEventMutex, GenericPolicy, SyncArrayMutex); |
59 | UT_MUTEX_TYPE(TTASEventMutex, BlockMutexPolicy, BlockSyncArrayMutex); |
60 | |
61 | #ifdef MUTEX_FUTEX |
62 | /** The default mutex type. */ |
63 | typedef FutexMutex ib_mutex_t; |
64 | typedef BlockFutexMutex ib_bpmutex_t; |
65 | #define MUTEX_TYPE "Uses futexes" |
66 | #elif defined(MUTEX_SYS) |
67 | typedef SysMutex ib_mutex_t; |
68 | typedef BlockSysMutex ib_bpmutex_t; |
69 | #define MUTEX_TYPE "Uses system mutexes" |
70 | #elif defined(MUTEX_EVENT) |
71 | typedef SyncArrayMutex ib_mutex_t; |
72 | typedef BlockSyncArrayMutex ib_bpmutex_t; |
73 | #define MUTEX_TYPE "Uses event mutexes" |
74 | #else |
75 | #error "ib_mutex_t type is unknown" |
76 | #endif /* MUTEX_FUTEX */ |
77 | |
78 | extern uint srv_spin_wait_delay; |
79 | extern ulong srv_n_spin_wait_rounds; |
80 | |
81 | #define mutex_create(I, M) mutex_init((M), (I), \ |
82 | __FILE__, __LINE__) |
83 | |
84 | #define mutex_enter_loc(M,file,line) (M)->enter( \ |
85 | uint32_t(srv_n_spin_wait_rounds), \ |
86 | uint32_t(srv_spin_wait_delay), \ |
87 | file, line) |
88 | #define mutex_enter(M) mutex_enter_loc(M, __FILE__, __LINE__) |
89 | |
90 | #define mutex_enter_nospin(M) (M)->enter( \ |
91 | 0, \ |
92 | 0, \ |
93 | __FILE__, uint32_t(__LINE__)) |
94 | |
95 | #define mutex_enter_nowait(M) (M)->trylock(__FILE__, \ |
96 | uint32_t(__LINE__)) |
97 | |
98 | #define mutex_exit(M) (M)->exit() |
99 | |
100 | #define mutex_free(M) mutex_destroy(M) |
101 | |
102 | #ifdef UNIV_DEBUG |
103 | /** |
104 | Checks that the mutex has been initialized. */ |
105 | #define mutex_validate(M) (M)->validate() |
106 | |
107 | /** |
108 | Checks that the current thread owns the mutex. Works only |
109 | in the debug version. */ |
110 | #define mutex_own(M) (M)->is_owned() |
111 | #else |
112 | #define mutex_own(M) /* No op */ |
113 | #define mutex_validate(M) /* No op */ |
114 | #endif /* UNIV_DEBUG */ |
115 | |
116 | /** Iterate over the mutex meta data */ |
117 | class MutexMonitor { |
118 | public: |
119 | /** Constructor */ |
120 | MutexMonitor() { } |
121 | |
122 | /** Destructor */ |
123 | ~MutexMonitor() { } |
124 | |
125 | /** Enable the mutex monitoring */ |
126 | void enable(); |
127 | |
128 | /** Disable the mutex monitoring */ |
129 | void disable(); |
130 | |
131 | /** Reset the mutex monitoring values */ |
132 | void reset(); |
133 | |
134 | /** Invoke the callback for each active mutex collection |
135 | @param[in,out] callback Functor to call |
136 | @return false if callback returned false */ |
137 | template<typename Callback> |
138 | bool iterate(Callback& callback) const |
139 | UNIV_NOTHROW |
140 | { |
141 | LatchMetaData::iterator end = latch_meta.end(); |
142 | |
143 | for (LatchMetaData::iterator it = latch_meta.begin(); |
144 | it != end; |
145 | ++it) { |
146 | |
147 | /* Some of the slots will be null in non-debug mode */ |
148 | |
149 | if (*it == NULL) { |
150 | continue; |
151 | } |
152 | |
153 | latch_meta_t* latch_meta = *it; |
154 | |
155 | bool ret = callback(*latch_meta); |
156 | |
157 | if (!ret) { |
158 | return(ret); |
159 | } |
160 | } |
161 | |
162 | return(true); |
163 | } |
164 | }; |
165 | |
166 | /** Defined in sync0sync.cc */ |
167 | extern MutexMonitor mutex_monitor; |
168 | |
169 | /** |
170 | Creates, or rather, initializes a mutex object in a specified memory |
171 | location (which must be appropriately aligned). The mutex is initialized |
172 | in the reset state. Explicit freeing of the mutex with mutex_free is |
173 | necessary only if the memory block containing it is freed. |
174 | Add the mutex instance to the global mutex list. |
175 | @param[in,out] mutex mutex to initialise |
176 | @param[in] id The mutex ID (Latch ID) |
177 | @param[in] filename Filename from where it was called |
178 | @param[in] line Line number in filename from where called */ |
179 | template <typename Mutex> |
180 | void mutex_init( |
181 | Mutex* mutex, |
182 | latch_id_t id, |
183 | const char* file_name, |
184 | uint32_t line) |
185 | { |
186 | new(mutex) Mutex(); |
187 | |
188 | mutex->init(id, file_name, line); |
189 | } |
190 | |
191 | /** |
192 | Removes a mutex instance from the mutex list. The mutex is checked to |
193 | be in the reset state. |
194 | @param[in,out] mutex mutex instance to destroy */ |
195 | template <typename Mutex> |
196 | void mutex_destroy( |
197 | Mutex* mutex) |
198 | { |
199 | mutex->destroy(); |
200 | } |
201 | |
202 | #endif /* ut0mutex_h */ |
203 | |
204 | #endif /* UNIV_INNOCHECKSUM */ |
205 | |