MySQL  8.0.27
Source Code Documentation
mysql_mutex.h
Go to the documentation of this file.
1 /* Copyright (c) 2008, 2021, Oracle and/or its affiliates.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License, version 2.0,
5  as published by the Free Software Foundation.
6 
7  This program is also distributed with certain software (including
8  but not limited to OpenSSL) that is licensed under separate terms,
9  as designated in a particular file or component or in included license
10  documentation. The authors of MySQL hereby grant you an additional
11  permission to link the program and your derivative works with the
12  separately licensed software that they have included with MySQL.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License, version 2.0, for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22 
23 #ifndef MYSQL_MUTEX_H
24 #define MYSQL_MUTEX_H
25 
26 /**
27  @file include/mysql/psi/mysql_mutex.h
28  Instrumentation helpers for mutexes.
29  This header file provides the necessary declarations
30  to use the mutex API with the performance schema instrumentation.
31  In some compilers (SunStudio), 'static inline' functions, when declared
32  but not used, are not optimized away (because they are unused) by default,
33  so that including a static inline function from a header file does
34  create unwanted dependencies, causing unresolved symbols at link time.
35  Other compilers, like gcc, optimize these dependencies by default.
36 */
37 /*
38  Note: there are several orthogonal dimensions here.
39 
40  Dimension 1: Instrumentation
41  HAVE_PSI_MUTEX_INTERFACE is defined when the instrumentation is compiled in.
42  This may happen both in debug or production builds.
43 
44  Dimension 2: Debug
45  SAFE_MUTEX is defined when debug is compiled in.
46  This may happen both with and without instrumentation.
47 
48  Dimension 3: Platform
49  Mutexes are implemented with one of:
50  - the pthread library
51  - fast mutexes
52  - window apis
53  This is implemented by various macro definitions in my_thread.h
54 
55  This causes complexity with '#ifdef'-ery that can't be avoided.
56 */
57 
58 /* HAVE_PSI_*_INTERFACE */
59 #include "my_psi_config.h" // IWYU pragma: keep
60 
63 #include "mysql/psi/psi_mutex.h"
64 #include "thr_mutex.h"
65 
66 #if defined(MYSQL_SERVER) || defined(PFS_DIRECT_CALL)
67 /* PSI_MUTEX_CALL() as direct call. */
68 #include "pfs_mutex_provider.h" // IWYU pragma: keep
69 #endif
70 
71 #ifndef PSI_MUTEX_CALL
72 #define PSI_MUTEX_CALL(M) psi_mutex_service->M
73 #endif
74 
75 /**
76  @defgroup psi_api_mutex Mutex Instrumentation (API)
77  @ingroup psi_api
78  @{
79 */
80 
81 /*
82  Consider the following code:
83  static inline void foo() { bar(); }
84  when foo() is never called.
85 
86  With gcc, foo() is a local static function, so the dependencies
87  are optimized away at compile time, and there is no dependency on bar().
88  With other compilers (HP, Sun Studio), the function foo() implementation
89  is compiled, and bar() needs to be present to link.
90 
91  Due to the existing header dependencies in MySQL code, this header file
92  is sometime used when it is not needed, which in turn cause link failures
93  on some platforms.
94  The proper fix would be to cut these extra dependencies in the calling code.
95  DISABLE_MYSQL_THREAD_H is a work around to limit dependencies.
96  DISABLE_MYSQL_PRLOCK_H is similar, and is used to disable specifically
97  the prlock wrappers.
98 */
99 #ifndef DISABLE_MYSQL_THREAD_H
100 
101 /**
102  @def mysql_mutex_assert_owner(M)
103  Wrapper, to use safe_mutex_assert_owner with instrumented mutexes.
104  @c mysql_mutex_assert_owner is a drop-in replacement
105  for @c safe_mutex_assert_owner.
106 */
107 #ifdef SAFE_MUTEX
108 #define mysql_mutex_assert_owner(M) \
109  safe_mutex_assert_owner((M)->m_mutex.m_u.m_safe_ptr);
110 #else
111 #define mysql_mutex_assert_owner(M) \
112  {}
113 #endif
114 
115 /**
116  @def mysql_mutex_assert_not_owner(M)
117  Wrapper, to use safe_mutex_assert_not_owner with instrumented mutexes.
118  @c mysql_mutex_assert_not_owner is a drop-in replacement
119  for @c safe_mutex_assert_not_owner.
120 */
121 #ifdef SAFE_MUTEX
122 #define mysql_mutex_assert_not_owner(M) \
123  safe_mutex_assert_not_owner((M)->m_mutex.m_u.m_safe_ptr);
124 #else
125 #define mysql_mutex_assert_not_owner(M) \
126  {}
127 #endif
128 
129 /**
130  @def mysql_mutex_register(P1, P2, P3)
131  Mutex registration.
132 */
133 #define mysql_mutex_register(P1, P2, P3) inline_mysql_mutex_register(P1, P2, P3)
134 
135 /**
136  @def mysql_mutex_init(K, M, A)
137  Instrumented mutex_init.
138  @c mysql_mutex_init is a replacement for @c pthread_mutex_init.
139  @param K The PSI_mutex_key for this instrumented mutex
140  @param M The mutex to initialize
141  @param A Mutex attributes
142 */
143 
144 #define mysql_mutex_init(K, M, A) \
145  mysql_mutex_init_with_src(K, M, A, __FILE__, __LINE__)
146 
147 #define mysql_mutex_init_with_src(K, M, A, F, L) \
148  inline_mysql_mutex_init(K, M, A, F, L)
149 
150 /**
151  @def mysql_mutex_destroy(M)
152  Instrumented mutex_destroy.
153  @c mysql_mutex_destroy is a drop-in replacement
154  for @c pthread_mutex_destroy.
155 */
156 #define mysql_mutex_destroy(M) \
157  mysql_mutex_destroy_with_src(M, __FILE__, __LINE__)
158 
159 #define mysql_mutex_destroy_with_src(M, F, L) \
160  inline_mysql_mutex_destroy(M, F, L)
161 
162 /**
163  @def mysql_mutex_lock(M)
164  Instrumented mutex_lock.
165  @c mysql_mutex_lock is a drop-in replacement for @c pthread_mutex_lock.
166  @param M The mutex to lock
167 */
168 
169 #define mysql_mutex_lock(M) mysql_mutex_lock_with_src(M, __FILE__, __LINE__)
170 
171 #define mysql_mutex_lock_with_src(M, F, L) inline_mysql_mutex_lock(M, F, L)
172 
173 /**
174  @def mysql_mutex_trylock(M)
175  Instrumented mutex_lock.
176  @c mysql_mutex_trylock is a drop-in replacement
177  for @c my_mutex_trylock.
178 */
179 
180 #define mysql_mutex_trylock(M) \
181  mysql_mutex_trylock_with_src(M, __FILE__, __LINE__)
182 
183 #define mysql_mutex_trylock_with_src(M, F, L) \
184  inline_mysql_mutex_trylock(M, F, L)
185 
186 /**
187  @def mysql_mutex_unlock(M)
188  Instrumented mutex_unlock.
189  @c mysql_mutex_unlock is a drop-in replacement for @c pthread_mutex_unlock.
190 */
191 #define mysql_mutex_unlock(M) mysql_mutex_unlock_with_src(M, __FILE__, __LINE__)
192 
193 #define mysql_mutex_unlock_with_src(M, F, L) inline_mysql_mutex_unlock(M, F, L)
194 
195 static inline void inline_mysql_mutex_register(const char *category
196  [[maybe_unused]],
198  [[maybe_unused]],
199  int count [[maybe_unused]]) {
200 #ifdef HAVE_PSI_MUTEX_INTERFACE
201  PSI_MUTEX_CALL(register_mutex)(category, info, count);
202 #endif
203 }
204 
205 static inline int inline_mysql_mutex_init(PSI_mutex_key key [[maybe_unused]],
206  mysql_mutex_t *that,
207  const native_mutexattr_t *attr,
208  const char *src_file [[maybe_unused]],
209  uint src_line [[maybe_unused]]) {
210 #ifdef HAVE_PSI_MUTEX_INTERFACE
211  that->m_psi = PSI_MUTEX_CALL(init_mutex)(key, &that->m_mutex);
212 #else
213  that->m_psi = nullptr;
214 #endif
215  return my_mutex_init(&that->m_mutex, attr
216 #ifdef SAFE_MUTEX
217  ,
218  src_file, src_line
219 #endif
220  );
221 }
222 
224  const char *src_file
225  [[maybe_unused]],
226  uint src_line [[maybe_unused]]) {
227 #ifdef HAVE_PSI_MUTEX_INTERFACE
228  if (that->m_psi != nullptr) {
230  that->m_psi = nullptr;
231  }
232 #endif
233  return my_mutex_destroy(&that->m_mutex
234 #ifdef SAFE_MUTEX
235  ,
236  src_file, src_line
237 #endif
238  );
239 }
240 
241 static inline int inline_mysql_mutex_lock(mysql_mutex_t *that,
242  const char *src_file [[maybe_unused]],
243  uint src_line [[maybe_unused]]) {
244  int result;
245 
246 #ifdef HAVE_PSI_MUTEX_INTERFACE
247  if (that->m_psi != nullptr) {
248  if (that->m_psi->m_enabled) {
249  /* Instrumentation start */
250  PSI_mutex_locker *locker;
252  locker = PSI_MUTEX_CALL(start_mutex_wait)(
253  &state, that->m_psi, PSI_MUTEX_LOCK, src_file, src_line);
254 
255  /* Instrumented code */
256  result = my_mutex_lock(&that->m_mutex
257 #ifdef SAFE_MUTEX
258  ,
259  src_file, src_line
260 #endif
261  );
262 
263  /* Instrumentation end */
264  if (locker != nullptr) {
265  PSI_MUTEX_CALL(end_mutex_wait)(locker, result);
266  }
267 
268  return result;
269  }
270  }
271 #endif
272 
273  /* Non instrumented code */
274  result = my_mutex_lock(&that->m_mutex
275 #ifdef SAFE_MUTEX
276  ,
277  src_file, src_line
278 #endif
279  );
280 
281  return result;
282 }
283 
285  const char *src_file
286  [[maybe_unused]],
287  uint src_line [[maybe_unused]]) {
288  int result;
289 
290 #ifdef HAVE_PSI_MUTEX_INTERFACE
291  if (that->m_psi != nullptr) {
292  if (that->m_psi->m_enabled) {
293  /* Instrumentation start */
294  PSI_mutex_locker *locker;
296  locker = PSI_MUTEX_CALL(start_mutex_wait)(
297  &state, that->m_psi, PSI_MUTEX_TRYLOCK, src_file, src_line);
298 
299  /* Instrumented code */
301 #ifdef SAFE_MUTEX
302  ,
303  src_file, src_line
304 #endif
305  );
306 
307  /* Instrumentation end */
308  if (locker != nullptr) {
309  PSI_MUTEX_CALL(end_mutex_wait)(locker, result);
310  }
311 
312  return result;
313  }
314  }
315 #endif
316 
317  /* Non instrumented code */
319 #ifdef SAFE_MUTEX
320  ,
321  src_file, src_line
322 #endif
323  );
324 
325  return result;
326 }
327 
328 static inline int inline_mysql_mutex_unlock(mysql_mutex_t *that,
329  const char *src_file
330  [[maybe_unused]],
331  uint src_line [[maybe_unused]]) {
332  int result;
333 
334 #ifdef HAVE_PSI_MUTEX_INTERFACE
335  if (that->m_psi != nullptr) {
336  PSI_MUTEX_CALL(unlock_mutex)(that->m_psi);
337  }
338 #endif
339 
341 #ifdef SAFE_MUTEX
342  ,
343  src_file, src_line
344 #endif
345  );
346 
347  return result;
348 }
349 
350 #endif /* DISABLE_MYSQL_THREAD_H */
351 
352 /** @} (end of group psi_api_mutex) */
353 
354 #endif
#define PSI_MUTEX_CALL(M)
Definition: psi_mutex.h:35
void destroy_mutex(PFS_mutex *pfs)
Destroy instrumentation for a mutex instance.
Definition: pfs_instr.cc:341
struct PSI_mutex_locker PSI_mutex_locker
Definition: psi_mutex_bits.h:104
unsigned int PSI_mutex_key
Instrumented mutex key.
Definition: psi_mutex_bits.h:51
@ PSI_MUTEX_TRYLOCK
Lock attempt.
Definition: psi_mutex_bits.h:111
@ PSI_MUTEX_LOCK
Lock.
Definition: psi_mutex_bits.h:109
static void inline_mysql_mutex_register(const char *category[[maybe_unused]], PSI_mutex_info *info[[maybe_unused]], int count[[maybe_unused]])
Definition: mysql_mutex.h:195
static int inline_mysql_mutex_destroy(mysql_mutex_t *that, const char *src_file[[maybe_unused]], uint src_line[[maybe_unused]])
Definition: mysql_mutex.h:223
static int inline_mysql_mutex_unlock(mysql_mutex_t *that, const char *src_file[[maybe_unused]], uint src_line[[maybe_unused]])
Definition: mysql_mutex.h:328
static int inline_mysql_mutex_lock(mysql_mutex_t *that, const char *src_file[[maybe_unused]], uint src_line[[maybe_unused]])
Definition: mysql_mutex.h:241
static int inline_mysql_mutex_trylock(mysql_mutex_t *that, const char *src_file[[maybe_unused]], uint src_line[[maybe_unused]])
Definition: mysql_mutex.h:284
static int inline_mysql_mutex_init(PSI_mutex_key key[[maybe_unused]], mysql_mutex_t *that, const native_mutexattr_t *attr, const char *src_file[[maybe_unused]], uint src_line[[maybe_unused]])
Definition: mysql_mutex.h:205
Defines various enable/disable and HAVE_ macros related to the performance schema instrumentation sys...
static int count
Definition: myisam_ftdump.cc:42
ABI for instrumented mutexes.
Log info(cout, "NOTE")
native_mutex_t init_mutex
Definition: mysqlimport.cc:54
static const char * category
Definition: sha2_password.cc:168
Performance schema instrumentation (declarations).
struct result result
Definition: result.h:33
Performance schema instrumentation interface.
Instrumentation helpers for mutexes.
required string key
Definition: replication_asynchronous_connection_failover.proto:59
bool m_enabled
Instrumentation is enabled.
Definition: psi_bits.h:175
Mutex information.
Definition: psi_mutex_bits.h:72
State data storage for start_mutex_wait_v1_t.
Definition: psi_mutex_bits.h:124
An instrumented mutex structure.
Definition: mysql_mutex_bits.h:49
struct PSI_mutex * m_psi
The instrumentation hook.
Definition: mysql_mutex_bits.h:57
my_mutex_t m_mutex
The real mutex.
Definition: mysql_mutex_bits.h:51
Definition: result.h:29
MySQL mutex implementation.
static int my_mutex_init(my_mutex_t *mp, const native_mutexattr_t *attr)
Definition: thr_mutex.h:164
static int my_mutex_destroy(my_mutex_t *mp)
Definition: thr_mutex.h:224
static int my_mutex_lock(my_mutex_t *mp)
Definition: thr_mutex.h:179
static int my_mutex_trylock(my_mutex_t *mp)
Definition: thr_mutex.h:194
static int my_mutex_unlock(my_mutex_t *mp)
Definition: thr_mutex.h:209
pthread_mutexattr_t native_mutexattr_t
Definition: thr_mutex_bits.h:55
unsigned int uint
Definition: uca-dump.cc:29