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