1/* Copyright (c) 2008, 2013, 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 as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software Foundation,
14 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
15
16#ifndef MYSQL_THREAD_H
17#define MYSQL_THREAD_H
18
19/**
20 @file mysql/psi/mysql_thread.h
21 Instrumentation helpers for mysys threads, mutexes,
22 read write locks and conditions.
23 This header file provides the necessary declarations
24 to use the mysys thread API with the performance schema instrumentation.
25 In some compilers (SunStudio), 'static inline' functions, when declared
26 but not used, are not optimized away (because they are unused) by default,
27 so that including a static inline function from a header file does
28 create unwanted dependencies, causing unresolved symbols at link time.
29 Other compilers, like gcc, optimize these dependencies by default.
30
31 Since the instrumented APIs declared here are wrapper on top
32 of my_pthread / safemutex / etc APIs,
33 including mysql/psi/mysql_thread.h assumes that
34 the dependency on my_pthread and safemutex already exists.
35*/
36/*
37 Note: there are several orthogonal dimensions here.
38
39 Dimension 1: Instrumentation
40 HAVE_PSI_INTERFACE is defined when the instrumentation is compiled in.
41 This may happen both in debug or production builds.
42
43 Dimension 2: Debug
44 SAFE_MUTEX is defined when debug is compiled in.
45 This may happen both with and without instrumentation.
46
47 Dimension 3: Platform
48 Mutexes are implemented with one of:
49 - the pthread library
50 - fast mutexes
51 - window apis
52 This is implemented by various macro definitions in my_pthread.h
53
54 This causes complexity with '#ifdef'-ery that can't be avoided.
55*/
56
57#include "mysql/psi/psi.h"
58
59/**
60 @defgroup Thread_instrumentation Thread Instrumentation
61 @ingroup Instrumentation_interface
62 @{
63*/
64
65#ifdef HAVE_PSI_THREAD_INTERFACE
66#define PSI_CALL_delete_current_thread PSI_THREAD_CALL(delete_current_thread)
67#define PSI_CALL_get_thread PSI_THREAD_CALL(get_thread)
68#define PSI_CALL_new_thread PSI_THREAD_CALL(new_thread)
69#define PSI_CALL_register_thread PSI_THREAD_CALL(register_thread)
70#define PSI_CALL_set_thread PSI_THREAD_CALL(set_thread)
71#define PSI_CALL_set_thread_connect_attrs PSI_THREAD_CALL(set_thread_connect_attrs)
72#define PSI_CALL_set_thread_db PSI_THREAD_CALL(set_thread_db)
73#define PSI_CALL_set_thread_id PSI_THREAD_CALL(set_thread_id)
74#define PSI_CALL_set_thread_info PSI_THREAD_CALL(set_thread_info)
75#define PSI_CALL_set_thread_start_time PSI_THREAD_CALL(set_thread_start_time)
76#define PSI_CALL_set_thread_user_host PSI_THREAD_CALL(set_thread_user_host)
77#define PSI_CALL_spawn_thread PSI_THREAD_CALL(spawn_thread)
78#else
79#define PSI_CALL_delete_current_thread() do { } while(0)
80#define PSI_CALL_get_thread() NULL
81#define PSI_CALL_new_thread(A1,A2,A3) NULL
82#define PSI_CALL_register_thread(A1,A2,A3) do { } while(0)
83#define PSI_CALL_set_thread(A1) do { } while(0)
84#define PSI_CALL_set_thread_connect_attrs(A1,A2,A3) 0
85#define PSI_CALL_set_thread_db(A1,A2) do { } while(0)
86#define PSI_CALL_set_thread_id(A1,A2) do { } while(0)
87#define PSI_CALL_set_thread_info(A1, A2) do { } while(0)
88#define PSI_CALL_set_thread_start_time(A1) do { } while(0)
89#define PSI_CALL_set_thread_user_host(A1, A2, A3, A4) do { } while(0)
90#define PSI_CALL_spawn_thread(A1, A2, A3, A4, A5) 0
91#endif
92
93
94/**
95 An instrumented mutex structure.
96 @sa mysql_mutex_t
97*/
98struct st_mysql_mutex
99{
100 /** The real mutex. */
101#ifdef SAFE_MUTEX
102 safe_mutex_t m_mutex;
103#else
104 pthread_mutex_t m_mutex;
105#endif
106 /**
107 The instrumentation hook.
108 Note that this hook is not conditionally defined,
109 for binary compatibility of the @c mysql_mutex_t interface.
110 */
111 struct PSI_mutex *m_psi;
112};
113
114/**
115 Type of an instrumented mutex.
116 @c mysql_mutex_t is a drop-in replacement for @c pthread_mutex_t.
117 @sa mysql_mutex_assert_owner
118 @sa mysql_mutex_assert_not_owner
119 @sa mysql_mutex_init
120 @sa mysql_mutex_lock
121 @sa mysql_mutex_unlock
122 @sa mysql_mutex_destroy
123*/
124typedef struct st_mysql_mutex mysql_mutex_t;
125
126/**
127 An instrumented rwlock structure.
128 @sa mysql_rwlock_t
129*/
130struct st_mysql_rwlock
131{
132 /** The real rwlock */
133 rw_lock_t m_rwlock;
134 /**
135 The instrumentation hook.
136 Note that this hook is not conditionally defined,
137 for binary compatibility of the @c mysql_rwlock_t interface.
138 */
139 struct PSI_rwlock *m_psi;
140};
141
142/**
143 An instrumented prlock structure.
144 @sa mysql_prlock_t
145*/
146struct st_mysql_prlock
147{
148 /** The real prlock */
149 rw_pr_lock_t m_prlock;
150 /**
151 The instrumentation hook.
152 Note that this hook is not conditionally defined,
153 for binary compatibility of the @c mysql_rwlock_t interface.
154 */
155 struct PSI_rwlock *m_psi;
156};
157
158/**
159 Type of an instrumented rwlock.
160 @c mysql_rwlock_t is a drop-in replacement for @c pthread_rwlock_t.
161 @sa mysql_rwlock_init
162 @sa mysql_rwlock_rdlock
163 @sa mysql_rwlock_tryrdlock
164 @sa mysql_rwlock_wrlock
165 @sa mysql_rwlock_trywrlock
166 @sa mysql_rwlock_unlock
167 @sa mysql_rwlock_destroy
168*/
169typedef struct st_mysql_rwlock mysql_rwlock_t;
170
171/**
172 Type of an instrumented prlock.
173 A prlock is a read write lock that 'prefers readers' (pr).
174 @c mysql_prlock_t is a drop-in replacement for @c rw_pr_lock_t.
175 @sa mysql_prlock_init
176 @sa mysql_prlock_rdlock
177 @sa mysql_prlock_wrlock
178 @sa mysql_prlock_unlock
179 @sa mysql_prlock_destroy
180*/
181typedef struct st_mysql_prlock mysql_prlock_t;
182
183/**
184 An instrumented cond structure.
185 @sa mysql_cond_t
186*/
187struct st_mysql_cond
188{
189 /** The real condition */
190 pthread_cond_t m_cond;
191 /**
192 The instrumentation hook.
193 Note that this hook is not conditionally defined,
194 for binary compatibility of the @c mysql_cond_t interface.
195 */
196 struct PSI_cond *m_psi;
197};
198
199/**
200 Type of an instrumented condition.
201 @c mysql_cond_t is a drop-in replacement for @c pthread_cond_t.
202 @sa mysql_cond_init
203 @sa mysql_cond_wait
204 @sa mysql_cond_timedwait
205 @sa mysql_cond_signal
206 @sa mysql_cond_broadcast
207 @sa mysql_cond_destroy
208*/
209typedef struct st_mysql_cond mysql_cond_t;
210
211/*
212 Consider the following code:
213 static inline void foo() { bar(); }
214 when foo() is never called.
215
216 With gcc, foo() is a local static function, so the dependencies
217 are optimized away at compile time, and there is no dependency on bar().
218 With other compilers (HP, Sun Studio), the function foo() implementation
219 is compiled, and bar() needs to be present to link.
220
221 Due to the existing header dependencies in MySQL code, this header file
222 is sometime used when it is not needed, which in turn cause link failures
223 on some platforms.
224 The proper fix would be to cut these extra dependencies in the calling code.
225 DISABLE_MYSQL_THREAD_H is a work around to limit dependencies.
226 DISABLE_MYSQL_PRLOCK_H is similar, and is used to disable specifically
227 the prlock wrappers.
228*/
229#ifndef DISABLE_MYSQL_THREAD_H
230
231/**
232 @def mysql_mutex_assert_owner(M)
233 Wrapper, to use safe_mutex_assert_owner with instrumented mutexes.
234 @c mysql_mutex_assert_owner is a drop-in replacement
235 for @c safe_mutex_assert_owner.
236*/
237#define mysql_mutex_assert_owner(M) \
238 safe_mutex_assert_owner(&(M)->m_mutex)
239
240/**
241 @def mysql_mutex_assert_not_owner(M)
242 Wrapper, to use safe_mutex_assert_not_owner with instrumented mutexes.
243 @c mysql_mutex_assert_not_owner is a drop-in replacement
244 for @c safe_mutex_assert_not_owner.
245*/
246#define mysql_mutex_assert_not_owner(M) \
247 safe_mutex_assert_not_owner(&(M)->m_mutex)
248
249#define mysql_mutex_setflags(M, F) \
250 safe_mutex_setflags(&(M)->m_mutex, (F))
251
252/** Wrappers for instrumented prlock objects. */
253
254#define mysql_prlock_assert_write_owner(M) \
255 rw_pr_lock_assert_write_owner(&(M)->m_prlock)
256
257#define mysql_prlock_assert_not_write_owner(M) \
258 rw_pr_lock_assert_not_write_owner(&(M)->m_prlock)
259
260/**
261 @def mysql_mutex_register(P1, P2, P3)
262 Mutex registration.
263*/
264#define mysql_mutex_register(P1, P2, P3) \
265 inline_mysql_mutex_register(P1, P2, P3)
266
267/**
268 @def mysql_mutex_init(K, M, A)
269 Instrumented mutex_init.
270 @c mysql_mutex_init is a replacement for @c pthread_mutex_init.
271 @param K The PSI_mutex_key for this instrumented mutex
272 @param M The mutex to initialize
273 @param A Mutex attributes
274*/
275
276#ifdef HAVE_PSI_MUTEX_INTERFACE
277 #ifdef SAFE_MUTEX
278 #define mysql_mutex_init(K, M, A) \
279 inline_mysql_mutex_init(K, M, A, #M, __FILE__, __LINE__)
280 #else
281 #define mysql_mutex_init(K, M, A) \
282 inline_mysql_mutex_init(K, M, A)
283 #endif
284#else
285 #ifdef SAFE_MUTEX
286 #define mysql_mutex_init(K, M, A) \
287 inline_mysql_mutex_init(M, A, #M, __FILE__, __LINE__)
288 #else
289 #define mysql_mutex_init(K, M, A) \
290 inline_mysql_mutex_init(M, A)
291 #endif
292#endif
293
294/**
295 @def mysql_mutex_destroy(M)
296 Instrumented mutex_destroy.
297 @c mysql_mutex_destroy is a drop-in replacement
298 for @c pthread_mutex_destroy.
299*/
300#ifdef SAFE_MUTEX
301 #define mysql_mutex_destroy(M) \
302 inline_mysql_mutex_destroy(M, __FILE__, __LINE__)
303#else
304 #define mysql_mutex_destroy(M) \
305 inline_mysql_mutex_destroy(M)
306#endif
307
308/**
309 @def mysql_mutex_lock(M)
310 Instrumented mutex_lock.
311 @c mysql_mutex_lock is a drop-in replacement for @c pthread_mutex_lock.
312 @param M The mutex to lock
313*/
314
315#if defined(SAFE_MUTEX) || defined (HAVE_PSI_MUTEX_INTERFACE)
316 #define mysql_mutex_lock(M) \
317 inline_mysql_mutex_lock(M, __FILE__, __LINE__)
318#else
319 #define mysql_mutex_lock(M) \
320 inline_mysql_mutex_lock(M)
321#endif
322
323/**
324 @def mysql_mutex_trylock(M)
325 Instrumented mutex_lock.
326 @c mysql_mutex_trylock is a drop-in replacement
327 for @c pthread_mutex_trylock.
328*/
329
330#if defined(SAFE_MUTEX) || defined (HAVE_PSI_MUTEX_INTERFACE)
331 #define mysql_mutex_trylock(M) \
332 inline_mysql_mutex_trylock(M, __FILE__, __LINE__)
333#else
334 #define mysql_mutex_trylock(M) \
335 inline_mysql_mutex_trylock(M)
336#endif
337
338/**
339 @def mysql_mutex_unlock(M)
340 Instrumented mutex_unlock.
341 @c mysql_mutex_unlock is a drop-in replacement for @c pthread_mutex_unlock.
342*/
343#ifdef SAFE_MUTEX
344 #define mysql_mutex_unlock(M) \
345 inline_mysql_mutex_unlock(M, __FILE__, __LINE__)
346#else
347 #define mysql_mutex_unlock(M) \
348 inline_mysql_mutex_unlock(M)
349#endif
350
351/**
352 @def mysql_rwlock_register(P1, P2, P3)
353 Rwlock registration.
354*/
355#define mysql_rwlock_register(P1, P2, P3) \
356 inline_mysql_rwlock_register(P1, P2, P3)
357
358/**
359 @def mysql_rwlock_init(K, RW)
360 Instrumented rwlock_init.
361 @c mysql_rwlock_init is a replacement for @c pthread_rwlock_init.
362 Note that pthread_rwlockattr_t is not supported in MySQL.
363 @param K The PSI_rwlock_key for this instrumented rwlock
364 @param RW The rwlock to initialize
365*/
366#ifdef HAVE_PSI_RWLOCK_INTERFACE
367 #define mysql_rwlock_init(K, RW) inline_mysql_rwlock_init(K, RW)
368#else
369 #define mysql_rwlock_init(K, RW) inline_mysql_rwlock_init(RW)
370#endif
371
372/**
373 @def mysql_prlock_init(K, RW)
374 Instrumented rw_pr_init.
375 @c mysql_prlock_init is a replacement for @c rw_pr_init.
376 @param K The PSI_rwlock_key for this instrumented prlock
377 @param RW The prlock to initialize
378*/
379#ifdef HAVE_PSI_RWLOCK_INTERFACE
380 #define mysql_prlock_init(K, RW) inline_mysql_prlock_init(K, RW)
381#else
382 #define mysql_prlock_init(K, RW) inline_mysql_prlock_init(RW)
383#endif
384
385/**
386 @def mysql_rwlock_destroy(RW)
387 Instrumented rwlock_destroy.
388 @c mysql_rwlock_destroy is a drop-in replacement
389 for @c pthread_rwlock_destroy.
390*/
391#define mysql_rwlock_destroy(RW) inline_mysql_rwlock_destroy(RW)
392
393/**
394 @def mysql_prlock_destroy(RW)
395 Instrumented rw_pr_destroy.
396 @c mysql_prlock_destroy is a drop-in replacement
397 for @c rw_pr_destroy.
398*/
399#define mysql_prlock_destroy(RW) inline_mysql_prlock_destroy(RW)
400
401/**
402 @def mysql_rwlock_rdlock(RW)
403 Instrumented rwlock_rdlock.
404 @c mysql_rwlock_rdlock is a drop-in replacement
405 for @c pthread_rwlock_rdlock.
406*/
407#ifdef HAVE_PSI_RWLOCK_INTERFACE
408 #define mysql_rwlock_rdlock(RW) \
409 inline_mysql_rwlock_rdlock(RW, __FILE__, __LINE__)
410#else
411 #define mysql_rwlock_rdlock(RW) \
412 inline_mysql_rwlock_rdlock(RW)
413#endif
414
415/**
416 @def mysql_prlock_rdlock(RW)
417 Instrumented rw_pr_rdlock.
418 @c mysql_prlock_rdlock is a drop-in replacement
419 for @c rw_pr_rdlock.
420*/
421#ifdef HAVE_PSI_RWLOCK_INTERFACE
422 #define mysql_prlock_rdlock(RW) \
423 inline_mysql_prlock_rdlock(RW, __FILE__, __LINE__)
424#else
425 #define mysql_prlock_rdlock(RW) \
426 inline_mysql_prlock_rdlock(RW)
427#endif
428
429/**
430 @def mysql_rwlock_wrlock(RW)
431 Instrumented rwlock_wrlock.
432 @c mysql_rwlock_wrlock is a drop-in replacement
433 for @c pthread_rwlock_wrlock.
434*/
435#ifdef HAVE_PSI_RWLOCK_INTERFACE
436 #define mysql_rwlock_wrlock(RW) \
437 inline_mysql_rwlock_wrlock(RW, __FILE__, __LINE__)
438#else
439 #define mysql_rwlock_wrlock(RW) \
440 inline_mysql_rwlock_wrlock(RW)
441#endif
442
443/**
444 @def mysql_prlock_wrlock(RW)
445 Instrumented rw_pr_wrlock.
446 @c mysql_prlock_wrlock is a drop-in replacement
447 for @c rw_pr_wrlock.
448*/
449#ifdef HAVE_PSI_RWLOCK_INTERFACE
450 #define mysql_prlock_wrlock(RW) \
451 inline_mysql_prlock_wrlock(RW, __FILE__, __LINE__)
452#else
453 #define mysql_prlock_wrlock(RW) \
454 inline_mysql_prlock_wrlock(RW)
455#endif
456
457/**
458 @def mysql_rwlock_tryrdlock(RW)
459 Instrumented rwlock_tryrdlock.
460 @c mysql_rwlock_tryrdlock is a drop-in replacement
461 for @c pthread_rwlock_tryrdlock.
462*/
463#ifdef HAVE_PSI_RWLOCK_INTERFACE
464 #define mysql_rwlock_tryrdlock(RW) \
465 inline_mysql_rwlock_tryrdlock(RW, __FILE__, __LINE__)
466#else
467 #define mysql_rwlock_tryrdlock(RW) \
468 inline_mysql_rwlock_tryrdlock(RW)
469#endif
470
471/**
472 @def mysql_rwlock_trywrlock(RW)
473 Instrumented rwlock_trywrlock.
474 @c mysql_rwlock_trywrlock is a drop-in replacement
475 for @c pthread_rwlock_trywrlock.
476*/
477#ifdef HAVE_PSI_RWLOCK_INTERFACE
478 #define mysql_rwlock_trywrlock(RW) \
479 inline_mysql_rwlock_trywrlock(RW, __FILE__, __LINE__)
480#else
481 #define mysql_rwlock_trywrlock(RW) \
482 inline_mysql_rwlock_trywrlock(RW)
483#endif
484
485/**
486 @def mysql_rwlock_unlock(RW)
487 Instrumented rwlock_unlock.
488 @c mysql_rwlock_unlock is a drop-in replacement
489 for @c pthread_rwlock_unlock.
490*/
491#define mysql_rwlock_unlock(RW) inline_mysql_rwlock_unlock(RW)
492
493/**
494 @def mysql_prlock_unlock(RW)
495 Instrumented rw_pr_unlock.
496 @c mysql_prlock_unlock is a drop-in replacement
497 for @c rw_pr_unlock.
498*/
499#define mysql_prlock_unlock(RW) inline_mysql_prlock_unlock(RW)
500
501/**
502 @def mysql_cond_register(P1, P2, P3)
503 Cond registration.
504*/
505#define mysql_cond_register(P1, P2, P3) \
506 inline_mysql_cond_register(P1, P2, P3)
507
508/**
509 @def mysql_cond_init(K, C, A)
510 Instrumented cond_init.
511 @c mysql_cond_init is a replacement for @c pthread_cond_init.
512 @param C The cond to initialize
513 @param K The PSI_cond_key for this instrumented cond
514 @param A Condition attributes
515*/
516#ifdef HAVE_PSI_COND_INTERFACE
517 #define mysql_cond_init(K, C, A) inline_mysql_cond_init(K, C, A)
518#else
519 #define mysql_cond_init(K, C, A) inline_mysql_cond_init(C, A)
520#endif
521
522/**
523 @def mysql_cond_destroy(C)
524 Instrumented cond_destroy.
525 @c mysql_cond_destroy is a drop-in replacement for @c pthread_cond_destroy.
526*/
527#define mysql_cond_destroy(C) inline_mysql_cond_destroy(C)
528
529/**
530 @def mysql_cond_wait(C)
531 Instrumented cond_wait.
532 @c mysql_cond_wait is a drop-in replacement for @c pthread_cond_wait.
533*/
534#ifdef HAVE_PSI_COND_INTERFACE
535 #define mysql_cond_wait(C, M) \
536 inline_mysql_cond_wait(C, M, __FILE__, __LINE__)
537#else
538 #define mysql_cond_wait(C, M) \
539 inline_mysql_cond_wait(C, M)
540#endif
541
542/**
543 @def mysql_cond_timedwait(C, M, W)
544 Instrumented cond_timedwait.
545 @c mysql_cond_timedwait is a drop-in replacement
546 for @c pthread_cond_timedwait.
547*/
548#ifdef HAVE_PSI_COND_INTERFACE
549 #define mysql_cond_timedwait(C, M, W) \
550 inline_mysql_cond_timedwait(C, M, W, __FILE__, __LINE__)
551#else
552 #define mysql_cond_timedwait(C, M, W) \
553 inline_mysql_cond_timedwait(C, M, W)
554#endif
555
556/**
557 @def mysql_cond_signal(C)
558 Instrumented cond_signal.
559 @c mysql_cond_signal is a drop-in replacement for @c pthread_cond_signal.
560*/
561#define mysql_cond_signal(C) inline_mysql_cond_signal(C)
562
563/**
564 @def mysql_cond_broadcast(C)
565 Instrumented cond_broadcast.
566 @c mysql_cond_broadcast is a drop-in replacement
567 for @c pthread_cond_broadcast.
568*/
569#define mysql_cond_broadcast(C) inline_mysql_cond_broadcast(C)
570
571/**
572 @def mysql_thread_register(P1, P2, P3)
573 Thread registration.
574*/
575#define mysql_thread_register(P1, P2, P3) \
576 inline_mysql_thread_register(P1, P2, P3)
577
578/**
579 @def mysql_thread_create(K, P1, P2, P3, P4)
580 Instrumented pthread_create.
581 This function creates both the thread instrumentation and a thread.
582 @c mysql_thread_create is a replacement for @c pthread_create.
583 The parameter P4 (or, if it is NULL, P1) will be used as the
584 instrumented thread "indentity".
585 Providing a P1 / P4 parameter with a different value for each call
586 will on average improve performances, since this thread identity value
587 is used internally to randomize access to data and prevent contention.
588 This is optional, and the improvement is not guaranteed, only statistical.
589 @param K The PSI_thread_key for this instrumented thread
590 @param P1 pthread_create parameter 1
591 @param P2 pthread_create parameter 2
592 @param P3 pthread_create parameter 3
593 @param P4 pthread_create parameter 4
594*/
595#ifdef HAVE_PSI_THREAD_INTERFACE
596 #define mysql_thread_create(K, P1, P2, P3, P4) \
597 inline_mysql_thread_create(K, P1, P2, P3, P4)
598#else
599 #define mysql_thread_create(K, P1, P2, P3, P4) \
600 pthread_create(P1, P2, P3, P4)
601#endif
602
603/**
604 @def mysql_thread_set_psi_id(I)
605 Set the thread identifier for the instrumentation.
606 @param I The thread identifier
607*/
608#ifdef HAVE_PSI_THREAD_INTERFACE
609 #define mysql_thread_set_psi_id(I) inline_mysql_thread_set_psi_id(I)
610#else
611 #define mysql_thread_set_psi_id(I) do {} while (0)
612#endif
613
614static inline void inline_mysql_mutex_register(
615#ifdef HAVE_PSI_MUTEX_INTERFACE
616 const char *category,
617 PSI_mutex_info *info,
618 int count
619#else
620 const char *category __attribute__ ((unused)),
621 void *info __attribute__ ((unused)),
622 int count __attribute__ ((unused))
623#endif
624)
625{
626#ifdef HAVE_PSI_MUTEX_INTERFACE
627 PSI_MUTEX_CALL(register_mutex)(category, info, count);
628#endif
629}
630
631static inline int inline_mysql_mutex_init(
632#ifdef HAVE_PSI_MUTEX_INTERFACE
633 PSI_mutex_key key,
634#endif
635 mysql_mutex_t *that,
636 const pthread_mutexattr_t *attr
637#ifdef SAFE_MUTEX
638 , const char *src_name, const char *src_file, uint src_line
639#endif
640 )
641{
642#ifdef HAVE_PSI_MUTEX_INTERFACE
643 that->m_psi= PSI_MUTEX_CALL(init_mutex)(key, &that->m_mutex);
644#else
645 that->m_psi= NULL;
646#endif
647#ifdef SAFE_MUTEX
648 return safe_mutex_init(&that->m_mutex, attr, src_name, src_file, src_line);
649#else
650 return pthread_mutex_init(&that->m_mutex, attr);
651#endif
652}
653
654static inline int inline_mysql_mutex_destroy(
655 mysql_mutex_t *that
656#ifdef SAFE_MUTEX
657 , const char *src_file, uint src_line
658#endif
659 )
660{
661#ifdef HAVE_PSI_MUTEX_INTERFACE
662 if (that->m_psi != NULL)
663 {
664 PSI_MUTEX_CALL(destroy_mutex)(that->m_psi);
665 that->m_psi= NULL;
666 }
667#endif
668#ifdef SAFE_MUTEX
669 return safe_mutex_destroy(&that->m_mutex, src_file, src_line);
670#else
671 return pthread_mutex_destroy(&that->m_mutex);
672#endif
673}
674
675static inline int inline_mysql_mutex_lock(
676 mysql_mutex_t *that
677#if defined(SAFE_MUTEX) || defined (HAVE_PSI_MUTEX_INTERFACE)
678 , const char *src_file, uint src_line
679#endif
680 )
681{
682 int result;
683
684#ifdef HAVE_PSI_MUTEX_INTERFACE
685 if (psi_likely(that->m_psi != NULL))
686 {
687 /* Instrumentation start */
688 PSI_mutex_locker *locker;
689 PSI_mutex_locker_state state;
690 locker= PSI_MUTEX_CALL(start_mutex_wait)(&state, that->m_psi,
691 PSI_MUTEX_LOCK, src_file, src_line);
692
693 /* Instrumented code */
694#ifdef SAFE_MUTEX
695 result= safe_mutex_lock(&that->m_mutex, FALSE, src_file, src_line);
696#else
697 result= pthread_mutex_lock(&that->m_mutex);
698#endif
699
700 /* Instrumentation end */
701 if (locker != NULL)
702 PSI_MUTEX_CALL(end_mutex_wait)(locker, result);
703
704 return result;
705 }
706#endif
707
708 /* Non instrumented code */
709#ifdef SAFE_MUTEX
710 result= safe_mutex_lock(&that->m_mutex, FALSE, src_file, src_line);
711#else
712 result= pthread_mutex_lock(&that->m_mutex);
713#endif
714
715 return result;
716}
717
718static inline int inline_mysql_mutex_trylock(
719 mysql_mutex_t *that
720#if defined(SAFE_MUTEX) || defined (HAVE_PSI_MUTEX_INTERFACE)
721 , const char *src_file, uint src_line
722#endif
723 )
724{
725 int result;
726
727#ifdef HAVE_PSI_MUTEX_INTERFACE
728 if (psi_likely(that->m_psi != NULL))
729 {
730 /* Instrumentation start */
731 PSI_mutex_locker *locker;
732 PSI_mutex_locker_state state;
733 locker= PSI_MUTEX_CALL(start_mutex_wait)(&state, that->m_psi,
734 PSI_MUTEX_TRYLOCK, src_file, src_line);
735
736 /* Instrumented code */
737#ifdef SAFE_MUTEX
738 result= safe_mutex_lock(&that->m_mutex, TRUE, src_file, src_line);
739#else
740 result= pthread_mutex_trylock(&that->m_mutex);
741#endif
742
743 /* Instrumentation end */
744 if (locker != NULL)
745 PSI_MUTEX_CALL(end_mutex_wait)(locker, result);
746
747 return result;
748 }
749#endif
750
751 /* Non instrumented code */
752#ifdef SAFE_MUTEX
753 result= safe_mutex_lock(&that->m_mutex, TRUE, src_file, src_line);
754#else
755 result= pthread_mutex_trylock(&that->m_mutex);
756#endif
757
758 return result;
759}
760
761static inline int inline_mysql_mutex_unlock(
762 mysql_mutex_t *that
763#ifdef SAFE_MUTEX
764 , const char *src_file, uint src_line
765#endif
766 )
767{
768 int result;
769
770#ifdef HAVE_PSI_MUTEX_INTERFACE
771 if (psi_likely(that->m_psi != NULL))
772 PSI_MUTEX_CALL(unlock_mutex)(that->m_psi);
773#endif
774
775#ifdef SAFE_MUTEX
776 result= safe_mutex_unlock(&that->m_mutex, src_file, src_line);
777#else
778 result= pthread_mutex_unlock(&that->m_mutex);
779#endif
780
781 return result;
782}
783
784static inline void inline_mysql_rwlock_register(
785#ifdef HAVE_PSI_RWLOCK_INTERFACE
786 const char *category,
787 PSI_rwlock_info *info,
788 int count
789#else
790 const char *category __attribute__ ((unused)),
791 void *info __attribute__ ((unused)),
792 int count __attribute__ ((unused))
793#endif
794)
795{
796#ifdef HAVE_PSI_RWLOCK_INTERFACE
797 PSI_RWLOCK_CALL(register_rwlock)(category, info, count);
798#endif
799}
800
801static inline int inline_mysql_rwlock_init(
802#ifdef HAVE_PSI_RWLOCK_INTERFACE
803 PSI_rwlock_key key,
804#endif
805 mysql_rwlock_t *that)
806{
807#ifdef HAVE_PSI_RWLOCK_INTERFACE
808 that->m_psi= PSI_RWLOCK_CALL(init_rwlock)(key, &that->m_rwlock);
809#else
810 that->m_psi= NULL;
811#endif
812 /*
813 pthread_rwlockattr_t is not used in MySQL.
814 */
815 return my_rwlock_init(&that->m_rwlock, NULL);
816}
817
818#ifndef DISABLE_MYSQL_PRLOCK_H
819static inline int inline_mysql_prlock_init(
820#ifdef HAVE_PSI_RWLOCK_INTERFACE
821 PSI_rwlock_key key,
822#endif
823 mysql_prlock_t *that)
824{
825#ifdef HAVE_PSI_RWLOCK_INTERFACE
826 that->m_psi= PSI_RWLOCK_CALL(init_rwlock)(key, &that->m_prlock);
827#else
828 that->m_psi= NULL;
829#endif
830 return rw_pr_init(&that->m_prlock);
831}
832#endif
833
834static inline int inline_mysql_rwlock_destroy(
835 mysql_rwlock_t *that)
836{
837#ifdef HAVE_PSI_RWLOCK_INTERFACE
838 if (psi_likely(that->m_psi != NULL))
839 {
840 PSI_RWLOCK_CALL(destroy_rwlock)(that->m_psi);
841 that->m_psi= NULL;
842 }
843#endif
844 return rwlock_destroy(&that->m_rwlock);
845}
846
847#ifndef DISABLE_MYSQL_PRLOCK_H
848static inline int inline_mysql_prlock_destroy(
849 mysql_prlock_t *that)
850{
851#ifdef HAVE_PSI_RWLOCK_INTERFACE
852 if (psi_likely(that->m_psi != NULL))
853 {
854 PSI_RWLOCK_CALL(destroy_rwlock)(that->m_psi);
855 that->m_psi= NULL;
856 }
857#endif
858 return rw_pr_destroy(&that->m_prlock);
859}
860#endif
861
862static inline int inline_mysql_rwlock_rdlock(
863 mysql_rwlock_t *that
864#ifdef HAVE_PSI_RWLOCK_INTERFACE
865 , const char *src_file, uint src_line
866#endif
867 )
868{
869 int result;
870
871#ifdef HAVE_PSI_RWLOCK_INTERFACE
872 if (psi_likely(that->m_psi != NULL))
873 {
874 /* Instrumentation start */
875 PSI_rwlock_locker *locker;
876 PSI_rwlock_locker_state state;
877 locker= PSI_RWLOCK_CALL(start_rwlock_rdwait)(&state, that->m_psi,
878 PSI_RWLOCK_READLOCK, src_file, src_line);
879
880 /* Instrumented code */
881 result= rw_rdlock(&that->m_rwlock);
882
883 /* Instrumentation end */
884 if (locker != NULL)
885 PSI_RWLOCK_CALL(end_rwlock_rdwait)(locker, result);
886
887 return result;
888 }
889#endif
890
891 /* Non instrumented code */
892 result= rw_rdlock(&that->m_rwlock);
893
894 return result;
895}
896
897#ifndef DISABLE_MYSQL_PRLOCK_H
898static inline int inline_mysql_prlock_rdlock(
899 mysql_prlock_t *that
900#ifdef HAVE_PSI_RWLOCK_INTERFACE
901 , const char *src_file, uint src_line
902#endif
903 )
904{
905 int result;
906
907#ifdef HAVE_PSI_RWLOCK_INTERFACE
908 if (psi_likely(that->m_psi != NULL))
909 {
910 /* Instrumentation start */
911 PSI_rwlock_locker *locker;
912 PSI_rwlock_locker_state state;
913 locker= PSI_RWLOCK_CALL(start_rwlock_rdwait)(&state, that->m_psi,
914 PSI_RWLOCK_READLOCK, src_file, src_line);
915
916 /* Instrumented code */
917 result= rw_pr_rdlock(&that->m_prlock);
918
919 /* Instrumentation end */
920 if (locker != NULL)
921 PSI_RWLOCK_CALL(end_rwlock_rdwait)(locker, result);
922
923 return result;
924 }
925#endif
926
927 /* Non instrumented code */
928 result= rw_pr_rdlock(&that->m_prlock);
929
930 return result;
931}
932#endif
933
934static inline int inline_mysql_rwlock_wrlock(
935 mysql_rwlock_t *that
936#ifdef HAVE_PSI_RWLOCK_INTERFACE
937 , const char *src_file, uint src_line
938#endif
939 )
940{
941 int result;
942
943#ifdef HAVE_PSI_RWLOCK_INTERFACE
944 if (psi_likely(that->m_psi != NULL))
945 {
946 /* Instrumentation start */
947 PSI_rwlock_locker *locker;
948 PSI_rwlock_locker_state state;
949 locker= PSI_RWLOCK_CALL(start_rwlock_wrwait)(&state, that->m_psi,
950 PSI_RWLOCK_WRITELOCK, src_file, src_line);
951
952 /* Instrumented code */
953 result= rw_wrlock(&that->m_rwlock);
954
955 /* Instrumentation end */
956 if (locker != NULL)
957 PSI_RWLOCK_CALL(end_rwlock_wrwait)(locker, result);
958
959 return result;
960 }
961#endif
962
963 /* Non instrumented code */
964 result= rw_wrlock(&that->m_rwlock);
965
966 return result;
967}
968
969#ifndef DISABLE_MYSQL_PRLOCK_H
970static inline int inline_mysql_prlock_wrlock(
971 mysql_prlock_t *that
972#ifdef HAVE_PSI_RWLOCK_INTERFACE
973 , const char *src_file, uint src_line
974#endif
975 )
976{
977 int result;
978
979#ifdef HAVE_PSI_RWLOCK_INTERFACE
980 if (psi_likely(that->m_psi != NULL))
981 {
982 /* Instrumentation start */
983 PSI_rwlock_locker *locker;
984 PSI_rwlock_locker_state state;
985 locker= PSI_RWLOCK_CALL(start_rwlock_wrwait)(&state, that->m_psi,
986 PSI_RWLOCK_WRITELOCK, src_file, src_line);
987
988 /* Instrumented code */
989 result= rw_pr_wrlock(&that->m_prlock);
990
991 /* Instrumentation end */
992 if (locker != NULL)
993 PSI_RWLOCK_CALL(end_rwlock_wrwait)(locker, result);
994
995 return result;
996 }
997#endif
998
999 /* Non instrumented code */
1000 result= rw_pr_wrlock(&that->m_prlock);
1001
1002 return result;
1003}
1004#endif
1005
1006static inline int inline_mysql_rwlock_tryrdlock(
1007 mysql_rwlock_t *that
1008#ifdef HAVE_PSI_RWLOCK_INTERFACE
1009 , const char *src_file, uint src_line
1010#endif
1011 )
1012{
1013 int result;
1014
1015#ifdef HAVE_PSI_RWLOCK_INTERFACE
1016 if (psi_likely(that->m_psi != NULL))
1017 {
1018 /* Instrumentation start */
1019 PSI_rwlock_locker *locker;
1020 PSI_rwlock_locker_state state;
1021 locker= PSI_RWLOCK_CALL(start_rwlock_rdwait)(&state, that->m_psi,
1022 PSI_RWLOCK_TRYREADLOCK, src_file, src_line);
1023
1024 /* Instrumented code */
1025 result= rw_tryrdlock(&that->m_rwlock);
1026
1027 /* Instrumentation end */
1028 if (locker != NULL)
1029 PSI_RWLOCK_CALL(end_rwlock_rdwait)(locker, result);
1030
1031 return result;
1032 }
1033#endif
1034
1035 /* Non instrumented code */
1036 result= rw_tryrdlock(&that->m_rwlock);
1037
1038 return result;
1039}
1040
1041static inline int inline_mysql_rwlock_trywrlock(
1042 mysql_rwlock_t *that
1043#ifdef HAVE_PSI_RWLOCK_INTERFACE
1044 , const char *src_file, uint src_line
1045#endif
1046 )
1047{
1048 int result;
1049
1050#ifdef HAVE_PSI_RWLOCK_INTERFACE
1051 if (psi_likely(that->m_psi != NULL))
1052 {
1053 /* Instrumentation start */
1054 PSI_rwlock_locker *locker;
1055 PSI_rwlock_locker_state state;
1056 locker= PSI_RWLOCK_CALL(start_rwlock_wrwait)(&state, that->m_psi,
1057 PSI_RWLOCK_TRYWRITELOCK, src_file, src_line);
1058
1059 /* Instrumented code */
1060 result= rw_trywrlock(&that->m_rwlock);
1061
1062 /* Instrumentation end */
1063 if (locker != NULL)
1064 PSI_RWLOCK_CALL(end_rwlock_wrwait)(locker, result);
1065
1066 return result;
1067 }
1068#endif
1069
1070 /* Non instrumented code */
1071 result= rw_trywrlock(&that->m_rwlock);
1072
1073 return result;
1074}
1075
1076static inline int inline_mysql_rwlock_unlock(
1077 mysql_rwlock_t *that)
1078{
1079 int result;
1080#ifdef HAVE_PSI_RWLOCK_INTERFACE
1081 if (psi_likely(that->m_psi != NULL))
1082 PSI_RWLOCK_CALL(unlock_rwlock)(that->m_psi);
1083#endif
1084 result= rw_unlock(&that->m_rwlock);
1085 return result;
1086}
1087
1088#ifndef DISABLE_MYSQL_PRLOCK_H
1089static inline int inline_mysql_prlock_unlock(
1090 mysql_prlock_t *that)
1091{
1092 int result;
1093#ifdef HAVE_PSI_RWLOCK_INTERFACE
1094 if (psi_likely(that->m_psi != NULL))
1095 PSI_RWLOCK_CALL(unlock_rwlock)(that->m_psi);
1096#endif
1097 result= rw_pr_unlock(&that->m_prlock);
1098 return result;
1099}
1100#endif
1101
1102static inline void inline_mysql_cond_register(
1103#ifdef HAVE_PSI_COND_INTERFACE
1104 const char *category,
1105 PSI_cond_info *info,
1106 int count
1107#else
1108 const char *category __attribute__ ((unused)),
1109 void *info __attribute__ ((unused)),
1110 int count __attribute__ ((unused))
1111#endif
1112)
1113{
1114#ifdef HAVE_PSI_COND_INTERFACE
1115 PSI_COND_CALL(register_cond)(category, info, count);
1116#endif
1117}
1118
1119static inline int inline_mysql_cond_init(
1120#ifdef HAVE_PSI_COND_INTERFACE
1121 PSI_cond_key key,
1122#endif
1123 mysql_cond_t *that,
1124 const pthread_condattr_t *attr)
1125{
1126#ifdef HAVE_PSI_COND_INTERFACE
1127 that->m_psi= PSI_COND_CALL(init_cond)(key, &that->m_cond);
1128#else
1129 that->m_psi= NULL;
1130#endif
1131 return pthread_cond_init(&that->m_cond, attr);
1132}
1133
1134static inline int inline_mysql_cond_destroy(
1135 mysql_cond_t *that)
1136{
1137#ifdef HAVE_PSI_COND_INTERFACE
1138 if (psi_likely(that->m_psi != NULL))
1139 {
1140 PSI_COND_CALL(destroy_cond)(that->m_psi);
1141 that->m_psi= NULL;
1142 }
1143#endif
1144 return pthread_cond_destroy(&that->m_cond);
1145}
1146
1147static inline int inline_mysql_cond_wait(
1148 mysql_cond_t *that,
1149 mysql_mutex_t *mutex
1150#ifdef HAVE_PSI_COND_INTERFACE
1151 , const char *src_file, uint src_line
1152#endif
1153 )
1154{
1155 int result;
1156
1157#ifdef HAVE_PSI_COND_INTERFACE
1158 if (psi_likely(that->m_psi != NULL))
1159 {
1160 /* Instrumentation start */
1161 PSI_cond_locker *locker;
1162 PSI_cond_locker_state state;
1163 locker= PSI_COND_CALL(start_cond_wait)(&state, that->m_psi, mutex->m_psi,
1164 PSI_COND_WAIT, src_file, src_line);
1165
1166 /* Instrumented code */
1167 result= my_cond_wait(&that->m_cond, &mutex->m_mutex);
1168
1169 /* Instrumentation end */
1170 if (locker != NULL)
1171 PSI_COND_CALL(end_cond_wait)(locker, result);
1172
1173 return result;
1174 }
1175#endif
1176
1177 /* Non instrumented code */
1178 result= my_cond_wait(&that->m_cond, &mutex->m_mutex);
1179
1180 return result;
1181}
1182
1183static inline int inline_mysql_cond_timedwait(
1184 mysql_cond_t *that,
1185 mysql_mutex_t *mutex,
1186 const struct timespec *abstime
1187#ifdef HAVE_PSI_COND_INTERFACE
1188 , const char *src_file, uint src_line
1189#endif
1190 )
1191{
1192 int result;
1193
1194#ifdef HAVE_PSI_COND_INTERFACE
1195 if (psi_likely(that->m_psi != NULL))
1196 {
1197 /* Instrumentation start */
1198 PSI_cond_locker *locker;
1199 PSI_cond_locker_state state;
1200 locker= PSI_COND_CALL(start_cond_wait)(&state, that->m_psi, mutex->m_psi,
1201 PSI_COND_TIMEDWAIT, src_file, src_line);
1202
1203 /* Instrumented code */
1204 result= my_cond_timedwait(&that->m_cond, &mutex->m_mutex, abstime);
1205
1206 /* Instrumentation end */
1207 if (psi_likely(locker != NULL))
1208 PSI_COND_CALL(end_cond_wait)(locker, result);
1209
1210 return result;
1211 }
1212#endif
1213
1214 /* Non instrumented code */
1215 result= my_cond_timedwait(&that->m_cond, &mutex->m_mutex, abstime);
1216
1217 return result;
1218}
1219
1220static inline int inline_mysql_cond_signal(
1221 mysql_cond_t *that)
1222{
1223 int result;
1224#ifdef HAVE_PSI_COND_INTERFACE
1225 if (psi_likely(that->m_psi != NULL))
1226 PSI_COND_CALL(signal_cond)(that->m_psi);
1227#endif
1228 result= pthread_cond_signal(&that->m_cond);
1229 return result;
1230}
1231
1232static inline int inline_mysql_cond_broadcast(
1233 mysql_cond_t *that)
1234{
1235 int result;
1236#ifdef HAVE_PSI_COND_INTERFACE
1237 if (psi_likely(that->m_psi != NULL))
1238 PSI_COND_CALL(broadcast_cond)(that->m_psi);
1239#endif
1240 result= pthread_cond_broadcast(&that->m_cond);
1241 return result;
1242}
1243
1244static inline void inline_mysql_thread_register(
1245#ifdef HAVE_PSI_THREAD_INTERFACE
1246 const char *category,
1247 PSI_thread_info *info,
1248 int count
1249#else
1250 const char *category __attribute__ ((unused)),
1251 void *info __attribute__ ((unused)),
1252 int count __attribute__ ((unused))
1253#endif
1254)
1255{
1256#ifdef HAVE_PSI_THREAD_INTERFACE
1257 PSI_THREAD_CALL(register_thread)(category, info, count);
1258#endif
1259}
1260
1261#ifdef HAVE_PSI_THREAD_INTERFACE
1262static inline int inline_mysql_thread_create(
1263 PSI_thread_key key,
1264 pthread_t *thread, const pthread_attr_t *attr,
1265 void *(*start_routine)(void*), void *arg)
1266{
1267 int result;
1268 result= PSI_THREAD_CALL(spawn_thread)(key, thread, attr, start_routine, arg);
1269 return result;
1270}
1271
1272static inline void inline_mysql_thread_set_psi_id(my_thread_id id)
1273{
1274 struct PSI_thread *psi= PSI_THREAD_CALL(get_thread)();
1275 PSI_THREAD_CALL(set_thread_id)(psi, id);
1276}
1277#endif
1278
1279#endif /* DISABLE_MYSQL_THREAD_H */
1280
1281/** @} (end of group Thread_instrumentation) */
1282
1283#endif
1284
1285