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