00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00033 #pragma once
00034 #ifndef sync0rw_h
00035 #define sync0rw_h
00036
00037 #include "univ.i"
00038 #ifndef UNIV_HOTBACKUP
00039 #include "ut0lst.h"
00040 #include "sync0sync.h"
00041 #include "os0sync.h"
00042
00043
00044
00045 #undef rw_lock_t
00046 #endif
00047
00048
00049
00050 #define RW_S_LATCH 1
00051 #define RW_X_LATCH 2
00052 #define RW_NO_LATCH 3
00053
00054 #ifndef UNIV_HOTBACKUP
00055
00056
00057
00058
00059 #define X_LOCK_DECR 0x00100000
00060
00061 typedef struct rw_lock_struct rw_lock_t;
00062 #ifdef UNIV_SYNC_DEBUG
00063 typedef struct rw_lock_debug_struct rw_lock_debug_t;
00064 #endif
00065
00066 typedef UT_LIST_BASE_NODE_T(rw_lock_t) rw_lock_list_t;
00067
00068 extern rw_lock_list_t rw_lock_list;
00069 extern mutex_t rw_lock_list_mutex;
00070
00071 #ifdef UNIV_SYNC_DEBUG
00072
00073
00074
00075
00076 extern mutex_t rw_lock_debug_mutex;
00077 extern os_event_t rw_lock_debug_event;
00080 extern ibool rw_lock_debug_waiters;
00082 #endif
00083
00086 extern ib_int64_t rw_s_spin_wait_count;
00089 extern ib_int64_t rw_s_spin_round_count;
00092 extern ib_int64_t rw_s_exit_count;
00095 extern ib_int64_t rw_s_os_wait_count;
00098 extern ib_int64_t rw_x_spin_wait_count;
00101 extern ib_int64_t rw_x_spin_round_count;
00104 extern ib_int64_t rw_x_os_wait_count;
00107 extern ib_int64_t rw_x_exit_count;
00108
00109 #ifdef UNIV_PFS_RWLOCK
00110
00111
00112 # ifdef UNIV_LOG_ARCHIVE
00113 extern mysql_pfs_key_t archive_lock_key;
00114 # endif
00115 extern mysql_pfs_key_t btr_search_latch_key;
00116 extern mysql_pfs_key_t buf_block_lock_key;
00117 # ifdef UNIV_SYNC_DEBUG
00118 extern mysql_pfs_key_t buf_block_debug_latch_key;
00119 # endif
00120 extern mysql_pfs_key_t dict_operation_lock_key;
00121 extern mysql_pfs_key_t fil_space_latch_key;
00122 extern mysql_pfs_key_t checkpoint_lock_key;
00123 extern mysql_pfs_key_t trx_i_s_cache_lock_key;
00124 extern mysql_pfs_key_t trx_purge_latch_key;
00125 extern mysql_pfs_key_t index_tree_rw_lock_key;
00126 #endif
00127
00128
00129 #ifndef UNIV_PFS_RWLOCK
00130
00137 # ifdef UNIV_DEBUG
00138 # ifdef UNIV_SYNC_DEBUG
00139 # define rw_lock_create(K, L, level) \
00140 rw_lock_create_func((L), (level), #L, __FILE__, __LINE__)
00141 # else
00142 # define rw_lock_create(K, L, level) \
00143 rw_lock_create_func((L), #L, __FILE__, __LINE__)
00144 # endif
00145 # else
00146 # define rw_lock_create(K, L, level) \
00147 rw_lock_create_func((L), __FILE__, __LINE__)
00148 # endif
00149
00150
00154 # define rw_lock_s_lock(M) \
00155 rw_lock_s_lock_func((M), 0, __FILE__, __LINE__)
00156
00157 # define rw_lock_s_lock_gen(M, P) \
00158 rw_lock_s_lock_func((M), (P), __FILE__, __LINE__)
00159
00160 # define rw_lock_s_lock_nowait(M, F, L) \
00161 rw_lock_s_lock_low((M), 0, (F), (L))
00162
00163 # ifdef UNIV_SYNC_DEBUG
00164 # define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(P, L)
00165 # else
00166 # define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(L)
00167 # endif
00168
00169
00170 # define rw_lock_x_lock(M) \
00171 rw_lock_x_lock_func((M), 0, __FILE__, __LINE__)
00172
00173 # define rw_lock_x_lock_gen(M, P) \
00174 rw_lock_x_lock_func((M), (P), __FILE__, __LINE__)
00175
00176 # define rw_lock_x_lock_nowait(M) \
00177 rw_lock_x_lock_func_nowait((M), __FILE__, __LINE__)
00178
00179 # ifdef UNIV_SYNC_DEBUG
00180 # define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(P, L)
00181 # else
00182 # define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(L)
00183 # endif
00184
00185 # define rw_lock_free(M) rw_lock_free_func(M)
00186
00187 #else
00188
00189
00190 # ifdef UNIV_DEBUG
00191 # ifdef UNIV_SYNC_DEBUG
00192 # define rw_lock_create(K, L, level) \
00193 pfs_rw_lock_create_func((K), (L), (level), #L, __FILE__, __LINE__)
00194 # else
00195 # define rw_lock_create(K, L, level) \
00196 pfs_rw_lock_create_func((K), (L), #L, __FILE__, __LINE__)
00197 # endif
00198 # else
00199 # define rw_lock_create(K, L, level) \
00200 pfs_rw_lock_create_func((K), (L), __FILE__, __LINE__)
00201 # endif
00202
00203
00204
00205
00206
00207 # define rw_lock_s_lock(M) \
00208 pfs_rw_lock_s_lock_func((M), 0, __FILE__, __LINE__)
00209
00210 # define rw_lock_s_lock_gen(M, P) \
00211 pfs_rw_lock_s_lock_func((M), (P), __FILE__, __LINE__)
00212
00213 # define rw_lock_s_lock_nowait(M, F, L) \
00214 pfs_rw_lock_s_lock_low((M), 0, (F), (L))
00215
00216 # ifdef UNIV_SYNC_DEBUG
00217 # define rw_lock_s_unlock_gen(L, P) pfs_rw_lock_s_unlock_func(P, L)
00218 # else
00219 # define rw_lock_s_unlock_gen(L, P) pfs_rw_lock_s_unlock_func(L)
00220 # endif
00221
00222 # define rw_lock_x_lock(M) \
00223 pfs_rw_lock_x_lock_func((M), 0, __FILE__, __LINE__)
00224
00225 # define rw_lock_x_lock_gen(M, P) \
00226 pfs_rw_lock_x_lock_func((M), (P), __FILE__, __LINE__)
00227
00228 # define rw_lock_x_lock_nowait(M) \
00229 pfs_rw_lock_x_lock_func_nowait((M), __FILE__, __LINE__)
00230
00231 # ifdef UNIV_SYNC_DEBUG
00232 # define rw_lock_x_unlock_gen(L, P) pfs_rw_lock_x_unlock_func(P, L)
00233 # else
00234 # define rw_lock_x_unlock_gen(L, P) pfs_rw_lock_x_unlock_func(L)
00235 # endif
00236
00237 # define rw_lock_free(M) pfs_rw_lock_free_func(M)
00238
00239 #endif
00240
00241 #define rw_lock_s_unlock(L) rw_lock_s_unlock_gen(L, 0)
00242 #define rw_lock_x_unlock(L) rw_lock_x_unlock_gen(L, 0)
00243
00244
00249 UNIV_INTERN
00250 void
00251 rw_lock_create_func(
00252
00253 rw_lock_t* lock,
00254 #ifdef UNIV_DEBUG
00255 # ifdef UNIV_SYNC_DEBUG
00256 ulint level,
00257 # endif
00258 const char* cmutex_name,
00259 #endif
00260 const char* cfile_name,
00261 ulint cline);
00262
00266 UNIV_INTERN
00267 void
00268 rw_lock_free_func(
00269
00270 rw_lock_t* lock);
00271 #ifdef UNIV_DEBUG
00272
00276 UNIV_INTERN
00277 ibool
00278 rw_lock_validate(
00279
00280 rw_lock_t* lock);
00281 #endif
00282
00286 UNIV_INLINE
00287 ibool
00288 rw_lock_s_lock_low(
00289
00290 rw_lock_t* lock,
00291 ulint ,
00294 const char* file_name,
00295 ulint line);
00296
00303 UNIV_INLINE
00304 void
00305 rw_lock_s_lock_func(
00306
00307 rw_lock_t* lock,
00308 ulint pass,
00310 const char* file_name,
00311 ulint line);
00312
00317 UNIV_INLINE
00318 ibool
00319 rw_lock_x_lock_func_nowait(
00320
00321 rw_lock_t* lock,
00322 const char* file_name,
00323 ulint line);
00324
00326 UNIV_INLINE
00327 void
00328 rw_lock_s_unlock_func(
00329
00330 #ifdef UNIV_SYNC_DEBUG
00331 ulint pass,
00333 #endif
00334 rw_lock_t* lock);
00336
00345 UNIV_INTERN
00346 void
00347 rw_lock_x_lock_func(
00348
00349 rw_lock_t* lock,
00350 ulint pass,
00352 const char* file_name,
00353 ulint line);
00354
00356 UNIV_INLINE
00357 void
00358 rw_lock_x_unlock_func(
00359
00360 #ifdef UNIV_SYNC_DEBUG
00361 ulint pass,
00363 #endif
00364 rw_lock_t* lock);
00367
00371 UNIV_INLINE
00372 void
00373 rw_lock_s_lock_direct(
00374
00375 rw_lock_t* lock,
00376 const char* file_name,
00377 ulint line);
00378
00382 UNIV_INLINE
00383 void
00384 rw_lock_x_lock_direct(
00385
00386 rw_lock_t* lock,
00387 const char* file_name,
00388 ulint line);
00389
00397 UNIV_INTERN
00398 void
00399 rw_lock_x_lock_move_ownership(
00400
00401 rw_lock_t* lock);
00403
00406 UNIV_INLINE
00407 void
00408 rw_lock_s_unlock_direct(
00409
00410 rw_lock_t* lock);
00411
00414 UNIV_INLINE
00415 void
00416 rw_lock_x_unlock_direct(
00417
00418 rw_lock_t* lock);
00419
00423 UNIV_INLINE
00424 ulint
00425 rw_lock_get_x_lock_count(
00426
00427 const rw_lock_t* lock);
00428
00431 UNIV_INLINE
00432 ulint
00433 rw_lock_get_waiters(
00434
00435 const rw_lock_t* lock);
00436
00440 UNIV_INLINE
00441 ulint
00442 rw_lock_get_writer(
00443
00444 const rw_lock_t* lock);
00445
00448 UNIV_INLINE
00449 ulint
00450 rw_lock_get_reader_count(
00451
00452 const rw_lock_t* lock);
00453
00457 UNIV_INLINE
00458 ibool
00459 rw_lock_lock_word_decr(
00460
00461 rw_lock_t* lock,
00462 ulint amount);
00463
00466 UNIV_INLINE
00467 lint
00468 rw_lock_lock_word_incr(
00469
00470 rw_lock_t* lock,
00471 ulint amount);
00472
00481 UNIV_INLINE
00482 void
00483 rw_lock_set_writer_id_and_recursion_flag(
00484
00485 rw_lock_t* lock,
00486 ibool recursive);
00488 #ifdef UNIV_SYNC_DEBUG
00489
00492 UNIV_INTERN
00493 ibool
00494 rw_lock_own(
00495
00496 rw_lock_t* lock,
00497 ulint lock_type)
00499 __attribute__((warn_unused_result));
00500 #endif
00501
00503 UNIV_INTERN
00504 ibool
00505 rw_lock_is_locked(
00506
00507 rw_lock_t* lock,
00508 ulint lock_type);
00510 #ifdef UNIV_SYNC_DEBUG
00511
00513 UNIV_INTERN
00514 void
00515 rw_lock_print(
00516
00517 rw_lock_t* lock);
00518
00520 UNIV_INTERN
00521 void
00522 rw_lock_list_print_info(
00523
00524 FILE* file);
00525
00529 UNIV_INTERN
00530 ulint
00531 rw_lock_n_locked(void);
00532
00533
00534
00535
00536
00542 UNIV_INTERN
00543 void
00544 rw_lock_debug_mutex_enter(void);
00545
00546
00548 UNIV_INTERN
00549 void
00550 rw_lock_debug_mutex_exit(void);
00551
00552
00554 UNIV_INTERN
00555 void
00556 rw_lock_debug_print(
00557
00558 rw_lock_debug_t* info);
00559 #endif
00560
00561
00562
00563
00571 struct rw_lock_struct {
00572 volatile lint lock_word;
00574 volatile ulint waiters;
00575 volatile ibool recursive;
00587 volatile os_thread_id_t writer_thread;
00591 os_event_t event;
00592 os_event_t wait_ex_event;
00595 #ifndef INNODB_RW_LOCKS_USE_ATOMICS
00596 mutex_t mutex;
00597 #endif
00598
00599 UT_LIST_NODE_T(rw_lock_t) list;
00602 #ifdef UNIV_SYNC_DEBUG
00603 UT_LIST_BASE_NODE_T(rw_lock_debug_t) debug_list;
00606 ulint level;
00607 #endif
00608 #ifdef UNIV_PFS_RWLOCK
00609 struct PSI_rwlock *pfs_psi;
00610 #endif
00611 ulint count_os_wait;
00612 const char* cfile_name;
00613
00614 const char* last_s_file_name;
00615 const char* last_x_file_name;
00616 ibool writer_is_wait_ex;
00623 unsigned cline:14;
00624 unsigned last_s_line:14;
00625 unsigned last_x_line:14;
00626 #ifdef UNIV_DEBUG
00627 ulint magic_n;
00629 #define RW_LOCK_MAGIC_N 22643
00630 #endif
00631 };
00632
00633 #ifdef UNIV_SYNC_DEBUG
00634
00635 struct rw_lock_debug_struct {
00636
00637 os_thread_id_t thread_id;
00639 ulint pass;
00640 ulint lock_type;
00642 const char* file_name;
00643 ulint line;
00644 UT_LIST_NODE_T(rw_lock_debug_t) list;
00647 };
00648 #endif
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677 #ifdef UNIV_PFS_RWLOCK
00678
00682 UNIV_INLINE
00683 void
00684 pfs_rw_lock_create_func(
00685
00686 PSI_rwlock_key key,
00688 rw_lock_t* lock,
00689 #ifdef UNIV_DEBUG
00690 # ifdef UNIV_SYNC_DEBUG
00691 ulint level,
00692 # endif
00693 const char* cmutex_name,
00694 #endif
00695 const char* cfile_name,
00696 ulint cline);
00698
00702 UNIV_INLINE
00703 void
00704 pfs_rw_lock_x_lock_func(
00705
00706 rw_lock_t* lock,
00707 ulint pass,
00709 const char* file_name,
00710 ulint line);
00711
00716 UNIV_INLINE
00717 ibool
00718 pfs_rw_lock_x_lock_func_nowait(
00719
00720 rw_lock_t* lock,
00721 const char* file_name,
00722 ulint line);
00723
00727 UNIV_INLINE
00728 void
00729 pfs_rw_lock_s_lock_func(
00730
00731 rw_lock_t* lock,
00732 ulint pass,
00734 const char* file_name,
00735 ulint line);
00736
00741 UNIV_INLINE
00742 ibool
00743 pfs_rw_lock_s_lock_low(
00744
00745 rw_lock_t* lock,
00746 ulint pass,
00749 const char* file_name,
00750 ulint line);
00751
00755 UNIV_INLINE
00756 void
00757 pfs_rw_lock_x_lock_func(
00758
00759 rw_lock_t* lock,
00760 ulint pass,
00762 const char* file_name,
00763 ulint line);
00764
00768 UNIV_INLINE
00769 void
00770 pfs_rw_lock_s_unlock_func(
00771
00772 #ifdef UNIV_SYNC_DEBUG
00773 ulint pass,
00776 #endif
00777 rw_lock_t* lock);
00778
00782 UNIV_INLINE
00783 void
00784 pfs_rw_lock_x_unlock_func(
00785
00786 #ifdef UNIV_SYNC_DEBUG
00787 ulint pass,
00790 #endif
00791 rw_lock_t* lock);
00792
00796 UNIV_INLINE
00797 void
00798 pfs_rw_lock_free_func(
00799
00800 rw_lock_t* lock);
00801 #endif
00802
00803
00804 #ifndef UNIV_NONINL
00805 #include "sync0rw.ic"
00806 #endif
00807 #endif
00808
00809 #endif