InnoDB Plugin  1.0
sync0rw.h
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
4 Copyright (c) 2008, Google Inc.
5 
6 Portions of this file contain modifications contributed and copyrighted by
7 Google, Inc. Those modifications are gratefully acknowledged and are described
8 briefly in the InnoDB documentation. The contributions by Google are
9 incorporated with their permission, and subject to the conditions contained in
10 the file COPYING.Google.
11 
12 This program is free software; you can redistribute it and/or modify it under
13 the terms of the GNU General Public License as published by the Free Software
14 Foundation; version 2 of the License.
15 
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc.,
22 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
23 
24 *****************************************************************************/
25 
26 /**************************************************/
33 #ifndef sync0rw_h
34 #define sync0rw_h
35 
36 #include "univ.i"
37 #ifndef UNIV_HOTBACKUP
38 #include "ut0lst.h"
39 #include "ut0counter.h"
40 #include "sync0sync.h"
41 #include "os0sync.h"
42 
43 /* The following undef is to prevent a name conflict with a macro
44 in MySQL: */
45 #undef rw_lock_t
46 #endif /* !UNIV_HOTBACKUP */
47 
51 
55 
59 
63 
67 
71 
75 
79 
83 };
84 
85 /* Latch types; these are used also in btr0btr.h: keep the numerical values
86 smaller than 30 and the order of the numerical values like below! */
87 #define RW_S_LATCH 1
88 #define RW_X_LATCH 2
89 #define RW_NO_LATCH 3
90 
91 #ifndef UNIV_HOTBACKUP
92 /* We decrement lock_word by this amount for each x_lock. It is also the
93 start value for the lock_word, meaning that it limits the maximum number
94 of concurrent read locks before the rw_lock breaks. The current value of
95 0x00100000 allows 1,048,575 concurrent readers and 2047 recursive writers.*/
96 #define X_LOCK_DECR 0x00100000
97 
98 struct rw_lock_t;
99 #ifdef UNIV_SYNC_DEBUG
100 struct rw_lock_debug_t;
101 #endif /* UNIV_SYNC_DEBUG */
102 
103 typedef UT_LIST_BASE_NODE_T(rw_lock_t) rw_lock_list_t;
104 
105 extern rw_lock_list_t rw_lock_list;
106 extern ib_mutex_t rw_lock_list_mutex;
107 
108 #ifdef UNIV_SYNC_DEBUG
109 /* The global mutex which protects debug info lists of all rw-locks.
110 To modify the debug info list of an rw-lock, this mutex has to be
111 
112 acquired in addition to the mutex protecting the lock. */
113 extern ib_mutex_t rw_lock_debug_mutex;
119 #endif /* UNIV_SYNC_DEBUG */
120 
123 
124 #ifdef UNIV_PFS_RWLOCK
125 /* Following are rwlock keys used to register with MySQL
126 performance schema */
127 # ifdef UNIV_LOG_ARCHIVE
128 extern mysql_pfs_key_t archive_lock_key;
129 # endif /* UNIV_LOG_ARCHIVE */
130 extern mysql_pfs_key_t btr_search_latch_key;
131 extern mysql_pfs_key_t buf_block_lock_key;
132 # ifdef UNIV_SYNC_DEBUG
133 extern mysql_pfs_key_t buf_block_debug_latch_key;
134 # endif /* UNIV_SYNC_DEBUG */
135 extern mysql_pfs_key_t dict_operation_lock_key;
136 extern mysql_pfs_key_t checkpoint_lock_key;
137 extern mysql_pfs_key_t fil_space_latch_key;
138 extern mysql_pfs_key_t fts_cache_rw_lock_key;
139 extern mysql_pfs_key_t fts_cache_init_rw_lock_key;
140 extern mysql_pfs_key_t trx_i_s_cache_lock_key;
141 extern mysql_pfs_key_t trx_purge_latch_key;
142 extern mysql_pfs_key_t index_tree_rw_lock_key;
143 extern mysql_pfs_key_t index_online_log_key;
144 extern mysql_pfs_key_t dict_table_stats_key;
145 extern mysql_pfs_key_t trx_sys_rw_lock_key;
146 extern mysql_pfs_key_t hash_table_rw_lock_key;
147 #endif /* UNIV_PFS_RWLOCK */
148 
149 
150 #ifndef UNIV_PFS_RWLOCK
151 /******************************************************************/
158 # ifdef UNIV_DEBUG
159 # ifdef UNIV_SYNC_DEBUG
160 # define rw_lock_create(K, L, level) \
161  rw_lock_create_func((L), (level), #L, __FILE__, __LINE__)
162 # else /* UNIV_SYNC_DEBUG */
163 # define rw_lock_create(K, L, level) \
164  rw_lock_create_func((L), #L, __FILE__, __LINE__)
165 # endif/* UNIV_SYNC_DEBUG */
166 # else /* UNIV_DEBUG */
167 # define rw_lock_create(K, L, level) \
168  rw_lock_create_func((L), __FILE__, __LINE__)
169 # endif /* UNIV_DEBUG */
170 
171 /**************************************************************/
175 # define rw_lock_s_lock(M) \
176  rw_lock_s_lock_func((M), 0, __FILE__, __LINE__)
177 
178 # define rw_lock_s_lock_inline(M, P, F, L) \
179  rw_lock_s_lock_func((M), (P), (F), (L))
180 
181 # define rw_lock_s_lock_gen(M, P) \
182  rw_lock_s_lock_func((M), (P), __FILE__, __LINE__)
183 
184 # define rw_lock_s_lock_gen_nowait(M, P) \
185  rw_lock_s_lock_low((M), (P), __FILE__, __LINE__)
186 
187 # define rw_lock_s_lock_nowait(M, F, L) \
188  rw_lock_s_lock_low((M), 0, (F), (L))
189 
190 # ifdef UNIV_SYNC_DEBUG
191 # define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(P, L)
192 # else
193 # define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(L)
194 # endif
195 
196 
197 # define rw_lock_x_lock(M) \
198  rw_lock_x_lock_func((M), 0, __FILE__, __LINE__)
199 
200 # define rw_lock_x_lock_inline(M, P, F, L) \
201  rw_lock_x_lock_func((M), (P), (F), (L))
202 
203 # define rw_lock_x_lock_gen(M, P) \
204  rw_lock_x_lock_func((M), (P), __FILE__, __LINE__)
205 
206 # define rw_lock_x_lock_nowait(M) \
207  rw_lock_x_lock_func_nowait((M), __FILE__, __LINE__)
208 
209 # define rw_lock_x_lock_func_nowait_inline(M, F, L) \
210  rw_lock_x_lock_func_nowait((M), (F), (L))
211 
212 # ifdef UNIV_SYNC_DEBUG
213 # define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(P, L)
214 # else
215 # define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(L)
216 # endif
217 
218 # define rw_lock_free(M) rw_lock_free_func(M)
219 
220 #else /* !UNIV_PFS_RWLOCK */
221 
222 /* Following macros point to Performance Schema instrumented functions. */
223 # ifdef UNIV_DEBUG
224 # ifdef UNIV_SYNC_DEBUG
225 # define rw_lock_create(K, L, level) \
226  pfs_rw_lock_create_func((K), (L), (level), #L, __FILE__, __LINE__)
227 # else /* UNIV_SYNC_DEBUG */
228 # define rw_lock_create(K, L, level) \
229  pfs_rw_lock_create_func((K), (L), #L, __FILE__, __LINE__)
230 # endif/* UNIV_SYNC_DEBUG */
231 # else /* UNIV_DEBUG */
232 # define rw_lock_create(K, L, level) \
233  pfs_rw_lock_create_func((K), (L), __FILE__, __LINE__)
234 # endif /* UNIV_DEBUG */
235 
236 /******************************************************************
237 NOTE! The following macros should be used in rw locking and
238 unlocking, not the corresponding function. */
239 
240 # define rw_lock_s_lock(M) \
241  pfs_rw_lock_s_lock_func((M), 0, __FILE__, __LINE__)
242 
243 # define rw_lock_s_lock_inline(M, P, F, L) \
244  pfs_rw_lock_s_lock_func((M), (P), (F), (L))
245 
246 # define rw_lock_s_lock_gen(M, P) \
247  pfs_rw_lock_s_lock_func((M), (P), __FILE__, __LINE__)
248 
249 # define rw_lock_s_lock_gen_nowait(M, P) \
250  pfs_rw_lock_s_lock_low((M), (P), __FILE__, __LINE__)
251 
252 # define rw_lock_s_lock_nowait(M, F, L) \
253  pfs_rw_lock_s_lock_low((M), 0, (F), (L))
254 
255 # ifdef UNIV_SYNC_DEBUG
256 # define rw_lock_s_unlock_gen(L, P) pfs_rw_lock_s_unlock_func(P, L)
257 # else
258 # define rw_lock_s_unlock_gen(L, P) pfs_rw_lock_s_unlock_func(L)
259 # endif
260 
261 # define rw_lock_x_lock(M) \
262  pfs_rw_lock_x_lock_func((M), 0, __FILE__, __LINE__)
263 
264 # define rw_lock_x_lock_inline(M, P, F, L) \
265  pfs_rw_lock_x_lock_func((M), (P), (F), (L))
266 
267 # define rw_lock_x_lock_gen(M, P) \
268  pfs_rw_lock_x_lock_func((M), (P), __FILE__, __LINE__)
269 
270 # define rw_lock_x_lock_nowait(M) \
271  pfs_rw_lock_x_lock_func_nowait((M), __FILE__, __LINE__)
272 
273 # define rw_lock_x_lock_func_nowait_inline(M, F, L) \
274  pfs_rw_lock_x_lock_func_nowait((M), (F), (L))
275 
276 # ifdef UNIV_SYNC_DEBUG
277 # define rw_lock_x_unlock_gen(L, P) pfs_rw_lock_x_unlock_func(P, L)
278 # else
279 # define rw_lock_x_unlock_gen(L, P) pfs_rw_lock_x_unlock_func(L)
280 # endif
281 
282 # define rw_lock_free(M) pfs_rw_lock_free_func(M)
283 
284 #endif /* UNIV_PFS_RWLOCK */
285 
286 #define rw_lock_s_unlock(L) rw_lock_s_unlock_gen(L, 0)
287 #define rw_lock_x_unlock(L) rw_lock_x_unlock_gen(L, 0)
288 
289 /******************************************************************/
294 UNIV_INTERN
295 void
297 /*================*/
298  rw_lock_t* lock,
299 #ifdef UNIV_DEBUG
300 # ifdef UNIV_SYNC_DEBUG
301  ulint level,
302 # endif /* UNIV_SYNC_DEBUG */
303  const char* cmutex_name,
304 #endif /* UNIV_DEBUG */
305  const char* cfile_name,
306  ulint cline);
307 /******************************************************************/
311 UNIV_INTERN
312 void
314 /*==============*/
315  rw_lock_t* lock);
316 #ifdef UNIV_DEBUG
317 /******************************************************************/
321 UNIV_INTERN
322 ibool
324 /*=============*/
325  rw_lock_t* lock);
326 #endif /* UNIV_DEBUG */
327 /******************************************************************/
331 UNIV_INLINE
332 ibool
334 /*===============*/
335  rw_lock_t* lock,
336  ulint pass __attribute__((unused)),
339  const char* file_name,
340  ulint line);
341 /******************************************************************/
348 UNIV_INLINE
349 void
351 /*================*/
352  rw_lock_t* lock,
353  ulint pass,
355  const char* file_name,
356  ulint line);
357 /******************************************************************/
362 UNIV_INLINE
363 ibool
365 /*=======================*/
366  rw_lock_t* lock,
367  const char* file_name,
368  ulint line);
369 /******************************************************************/
371 UNIV_INLINE
372 void
374 /*==================*/
375 #ifdef UNIV_SYNC_DEBUG
376  ulint pass,
378 #endif
379  rw_lock_t* lock);
381 /******************************************************************/
390 UNIV_INTERN
391 void
393 /*================*/
394  rw_lock_t* lock,
395  ulint pass,
397  const char* file_name,
398  ulint line);
399 /******************************************************************/
401 UNIV_INLINE
402 void
404 /*==================*/
405 #ifdef UNIV_SYNC_DEBUG
406  ulint pass,
408 #endif
409  rw_lock_t* lock);
410 /******************************************************************/
418 UNIV_INTERN
419 void
421 /*==========================*/
422  rw_lock_t* lock);
424 /******************************************************************/
428 UNIV_INLINE
429 ulint
431 /*=====================*/
432  const rw_lock_t* lock);
433 /********************************************************************/
436 UNIV_INLINE
437 ulint
439 /*================*/
440  const rw_lock_t* lock);
441 /******************************************************************/
445 UNIV_INLINE
446 ulint
448 /*===============*/
449  const rw_lock_t* lock);
450 /******************************************************************/
453 UNIV_INLINE
454 ulint
456 /*=====================*/
457  const rw_lock_t* lock);
458 /******************************************************************/
462 UNIV_INLINE
463 ibool
465 /*===================*/
466  rw_lock_t* lock,
467  ulint amount);
468 /******************************************************************/
471 UNIV_INLINE
472 lint
474 /*===================*/
475  rw_lock_t* lock,
476  ulint amount);
477 /******************************************************************/
486 UNIV_INLINE
487 void
489 /*=====================================*/
490  rw_lock_t* lock,
491  ibool recursive);
493 #ifdef UNIV_SYNC_DEBUG
494 /******************************************************************/
497 UNIV_INTERN
498 ibool
500 /*========*/
501  rw_lock_t* lock,
502  ulint lock_type)
504  __attribute__((warn_unused_result));
505 #endif /* UNIV_SYNC_DEBUG */
506 /******************************************************************/
508 UNIV_INTERN
509 ibool
511 /*==============*/
512  rw_lock_t* lock,
513  ulint lock_type);
515 #ifdef UNIV_SYNC_DEBUG
516 /***************************************************************/
518 UNIV_INTERN
519 void
521 /*==========*/
522  rw_lock_t* lock);
523 /***************************************************************/
525 UNIV_INTERN
526 void
528 /*====================*/
529  FILE* file);
530 /***************************************************************/
534 UNIV_INTERN
535 ulint
536 rw_lock_n_locked(void);
537 /*==================*/
538 
539 /*#####################################################################*/
540 
541 /******************************************************************/
547 UNIV_INTERN
548 void
550 /*===========================*/
551 /******************************************************************/
553 UNIV_INTERN
554 void
556 /*==========================*/
557 /*********************************************************************/
559 UNIV_INTERN
560 void
562 /*================*/
563  FILE* f,
564  rw_lock_debug_t* info);
565 #endif /* UNIV_SYNC_DEBUG */
566 
567 /* NOTE! The structure appears here only for the compiler to know its size.
568 Do not use its fields directly! */
569 
577 struct rw_lock_t {
578  volatile lint lock_word;
580  volatile ulint waiters;
581  volatile ibool recursive;
593  volatile os_thread_id_t writer_thread;
601 #ifndef INNODB_RW_LOCKS_USE_ATOMICS
603 #endif /* INNODB_RW_LOCKS_USE_ATOMICS */
604 
605  UT_LIST_NODE_T(rw_lock_t) list;
608 #ifdef UNIV_SYNC_DEBUG
609  UT_LIST_BASE_NODE_T(rw_lock_debug_t) debug_list;
612  ulint level;
613 #endif /* UNIV_SYNC_DEBUG */
614 #ifdef UNIV_PFS_RWLOCK
615  struct PSI_rwlock *pfs_psi;
616 #endif
618  const char* cfile_name;
619  /* last s-lock file/line is not guaranteed to be correct */
620  const char* last_s_file_name;
621  const char* last_x_file_name;
629  unsigned cline:14;
630  unsigned last_s_line:14;
631  unsigned last_x_line:14;
632 #ifdef UNIV_DEBUG
633  ulint magic_n;
635 #define RW_LOCK_MAGIC_N 22643
636 #endif /* UNIV_DEBUG */
637 };
638 
639 #ifdef UNIV_SYNC_DEBUG
640 
643 
646  ulint pass;
647  ulint lock_type;
649  const char* file_name;
650  ulint line;
651  UT_LIST_NODE_T(rw_lock_debug_t) list;
654 };
655 #endif /* UNIV_SYNC_DEBUG */
656 
657 /* For performance schema instrumentation, a new set of rwlock
658 wrap functions are created if "UNIV_PFS_RWLOCK" is defined.
659 The instrumentations are not planted directly into original
660 functions, so that we keep the underlying function as they
661 are. And in case, user wants to "take out" some rwlock from
662 instrumentation even if performance schema (UNIV_PFS_RWLOCK)
663 is defined, they can do so by reinstating APIs directly link to
664 original underlying functions.
665 The instrumented function names have prefix of "pfs_rw_lock_" vs.
666 original name prefix of "rw_lock_". Following are list of functions
667 that have been instrumented:
668 
669 rw_lock_create()
670 rw_lock_x_lock()
671 rw_lock_x_lock_gen()
672 rw_lock_x_lock_nowait()
673 rw_lock_x_unlock_gen()
674 rw_lock_s_lock()
675 rw_lock_s_lock_gen()
676 rw_lock_s_lock_nowait()
677 rw_lock_s_unlock_gen()
678 rw_lock_free()
679 */
680 
681 #ifdef UNIV_PFS_RWLOCK
682 /******************************************************************/
686 UNIV_INLINE
687 void
688 pfs_rw_lock_create_func(
689 /*====================*/
690  PSI_rwlock_key key,
692  rw_lock_t* lock,
693 #ifdef UNIV_DEBUG
694 # ifdef UNIV_SYNC_DEBUG
695  ulint level,
696 # endif /* UNIV_SYNC_DEBUG */
697  const char* cmutex_name,
698 #endif /* UNIV_DEBUG */
699  const char* cfile_name,
700  ulint cline);
702 /******************************************************************/
706 UNIV_INLINE
707 void
708 pfs_rw_lock_x_lock_func(
709 /*====================*/
710  rw_lock_t* lock,
711  ulint pass,
713  const char* file_name,
714  ulint line);
715 /******************************************************************/
720 UNIV_INLINE
721 ibool
722 pfs_rw_lock_x_lock_func_nowait(
723 /*===========================*/
724  rw_lock_t* lock,
725  const char* file_name,
726  ulint line);
727 /******************************************************************/
731 UNIV_INLINE
732 void
733 pfs_rw_lock_s_lock_func(
734 /*====================*/
735  rw_lock_t* lock,
736  ulint pass,
738  const char* file_name,
739  ulint line);
740 /******************************************************************/
745 UNIV_INLINE
746 ibool
747 pfs_rw_lock_s_lock_low(
748 /*===================*/
749  rw_lock_t* lock,
750  ulint pass,
753  const char* file_name,
754  ulint line);
755 /******************************************************************/
759 UNIV_INLINE
760 void
761 pfs_rw_lock_x_lock_func(
762 /*====================*/
763  rw_lock_t* lock,
764  ulint pass,
766  const char* file_name,
767  ulint line);
768 /******************************************************************/
772 UNIV_INLINE
773 void
774 pfs_rw_lock_s_unlock_func(
775 /*======================*/
776 #ifdef UNIV_SYNC_DEBUG
777  ulint pass,
780 #endif
781  rw_lock_t* lock);
782 /******************************************************************/
786 UNIV_INLINE
787 void
788 pfs_rw_lock_x_unlock_func(
789 /*======================*/
790 #ifdef UNIV_SYNC_DEBUG
791  ulint pass,
794 #endif
795  rw_lock_t* lock);
796 /******************************************************************/
800 UNIV_INLINE
801 void
802 pfs_rw_lock_free_func(
803 /*==================*/
804  rw_lock_t* lock);
805 #endif /* UNIV_PFS_RWLOCK */
806 
807 
808 #ifndef UNIV_NONINL
809 #include "sync0rw.ic"
810 #endif
811 #endif /* !UNIV_HOTBACKUP */
812 
813 #endif