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 #ifndef UNIV_DEBUG
55
56 # ifdef HAVE_IB_LINUX_FUTEX
57 UT_MUTEX_TYPE(TTASFutexMutex, GenericPolicy, FutexMutex);
58 UT_MUTEX_TYPE(TTASFutexMutex, AggregateMutexStatsPolicy, BlockFutexMutex);
59 # endif /* HAVE_IB_LINUX_FUTEX */
60
61 UT_MUTEX_TYPE(TTASMutex, GenericPolicy, SpinMutex);
62 UT_MUTEX_TYPE(TTASMutex, AggregateMutexStatsPolicy, BlockSpinMutex);
63
64
65 UT_MUTEX_TYPE(OSTrackMutex, GenericPolicy, SysMutex);
66 UT_MUTEX_TYPE(OSTrackMutex, AggregateMutexStatsPolicy, BlockSysMutex);
67
68 UT_MUTEX_TYPE(TTASEventMutex, GenericPolicy, SyncArrayMutex);
69 UT_MUTEX_TYPE(TTASEventMutex, AggregateMutexStatsPolicy, BlockSyncArrayMutex);
70
71 #else /* !UNIV_DEBUG */
72
73 # ifdef HAVE_IB_LINUX_FUTEX
74 UT_MUTEX_TYPE(TTASFutexMutex, GenericPolicy, FutexMutex);
75 UT_MUTEX_TYPE(TTASFutexMutex, AggregateMutexStatsPolicy, BlockFutexMutex);
76 # endif /* HAVE_IB_LINUX_FUTEX */
77
78 UT_MUTEX_TYPE(TTASMutex, GenericPolicy, SpinMutex);
79 UT_MUTEX_TYPE(TTASMutex, AggregateMutexStatsPolicy, BlockSpinMutex);
80
81 UT_MUTEX_TYPE(OSTrackMutex, GenericPolicy, SysMutex);
82 UT_MUTEX_TYPE(OSTrackMutex, AggregateMutexStatsPolicy, BlockSysMutex);
83
84 UT_MUTEX_TYPE(TTASEventMutex, GenericPolicy, SyncArrayMutex);
85 UT_MUTEX_TYPE(TTASEventMutex, AggregateMutexStatsPolicy, BlockSyncArrayMutex);
86
87 #endif /* !UNIV_DEBUG */
88
89 #ifdef MUTEX_FUTEX
90 /** The default mutex type. */
91 typedef FutexMutex ib_mutex_t;
92 typedef BlockFutexMutex ib_bpmutex_t;
93 #define MUTEX_TYPE "Uses futexes"
94 #elif defined(MUTEX_SYS)
95 typedef SysMutex ib_mutex_t;
96 typedef BlockSysMutex ib_bpmutex_t;
97 #define MUTEX_TYPE "Uses system mutexes"
98 #elif defined(MUTEX_EVENT)
99 typedef SyncArrayMutex ib_mutex_t;
100 typedef BlockSyncArrayMutex ib_bpmutex_t;
101 #define MUTEX_TYPE "Uses event mutexes"
102 #else
103 #error "ib_mutex_t type is unknown"
104 #endif /* MUTEX_FUTEX */
105
106 #include "ut0mutex.ic"
107
108 extern ulong srv_spin_wait_delay;
109 extern ulong srv_n_spin_wait_rounds;
110
111 #define mutex_create(I, M) mutex_init((M), (I), __FILE__, __LINE__)
112
113 #define mutex_enter(M) (M)->enter( \
114 srv_n_spin_wait_rounds, \
115 srv_spin_wait_delay, \
116 __FILE__, __LINE__)
117
118 #define mutex_enter_nospin(M) (M)->enter( \
119 0, \
120 0, \
121 __FILE__, __LINE__)
122
123 #define mutex_enter_nowait(M) (M)->trylock(__FILE__, __LINE__)
124
125 #define mutex_exit(M) (M)->exit()
126
127 #define mutex_free(M) mutex_destroy(M)
128
129 #ifdef UNIV_DEBUG
130 /**
131 Checks that the mutex has been initialized. */
132 #define mutex_validate(M) (M)->validate()
133
134 /**
135 Checks that the current thread owns the mutex. Works only
136 in the debug version. */
137 #define mutex_own(M) (M)->is_owned()
138 #else
139 #define mutex_own(M) /* No op */
140 #define mutex_validate(M) /* No op */
141 #endif /* UNIV_DEBUG */
142
143 /** Iterate over the mutex meta data */
144 class MutexMonitor {
145 public:
146 /** Constructor */
MutexMonitor()147 MutexMonitor() { }
148
149 /** Destructor */
~MutexMonitor()150 ~MutexMonitor() { }
151
152 /** Enable the mutex monitoring */
153 void enable();
154
155 /** Disable the mutex monitoring */
156 void disable();
157
158 /** Reset the mutex monitoring values */
159 void reset();
160
161 /** Invoke the callback for each active mutex collection
162 @param[in,out] callback Functor to call
163 @return false if callback returned false */
164 template<typename Callback>
iterate(Callback & callback)165 bool iterate(Callback& callback) const
166 UNIV_NOTHROW
167 {
168 LatchMetaData::iterator end = latch_meta.end();
169
170 for (LatchMetaData::iterator it = latch_meta.begin();
171 it != end;
172 ++it) {
173
174 /* Some of the slots will be null in non-debug mode */
175
176 if (*it == NULL) {
177 continue;
178 }
179
180 latch_meta_t* latch_meta = *it;
181
182 bool ret = callback(*latch_meta);
183
184 if (!ret) {
185 return(ret);
186 }
187 }
188
189 return(true);
190 }
191 };
192
193 /** Defined in sync0sync.cc */
194 extern MutexMonitor* mutex_monitor;
195
196 /**
197 Creates, or rather, initializes a mutex object in a specified memory
198 location (which must be appropriately aligned). The mutex is initialized
199 in the reset state. Explicit freeing of the mutex with mutex_free is
200 necessary only if the memory block containing it is freed.
201 Add the mutex instance to the global mutex list.
202 @param[in,out] mutex mutex to initialise
203 @param[in] id The mutex ID (Latch ID)
204 @param[in] filename Filename from where it was called
205 @param[in] line Line number in filename from where called */
206 template <typename Mutex>
mutex_init(Mutex * mutex,latch_id_t id,const char * file_name,uint32_t line)207 void mutex_init(
208 Mutex* mutex,
209 latch_id_t id,
210 const char* file_name,
211 uint32_t line)
212 {
213 new(mutex) Mutex();
214
215 mutex->init(id, file_name, line);
216 }
217
218 /**
219 Removes a mutex instance from the mutex list. The mutex is checked to
220 be in the reset state.
221 @param[in,out] mutex mutex instance to destroy */
222 template <typename Mutex>
mutex_destroy(Mutex * mutex)223 void mutex_destroy(
224 Mutex* mutex)
225 {
226 mutex->destroy();
227 }
228
229 #endif /* ut0mutex_h */
230
231 #endif /* UNIV_INNOCHECKSUM */
232