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 #include "sync0rw.h"
00034 #ifdef UNIV_NONINL
00035 #include "sync0rw.ic"
00036 #endif
00037
00038 #include "os0thread.h"
00039 #include "mem0mem.h"
00040 #include "srv0srv.h"
00041 #include "os0sync.h"
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00139 UNIV_INTERN ib_int64_t rw_s_spin_wait_count = 0;
00142 UNIV_INTERN ib_int64_t rw_s_spin_round_count = 0;
00143
00146 UNIV_INTERN ib_int64_t rw_s_os_wait_count = 0;
00147
00150 UNIV_INTERN ib_int64_t rw_s_exit_count = 0;
00151
00154 UNIV_INTERN ib_int64_t rw_x_spin_wait_count = 0;
00157 UNIV_INTERN ib_int64_t rw_x_spin_round_count = 0;
00158
00161 UNIV_INTERN ib_int64_t rw_x_os_wait_count = 0;
00162
00165 UNIV_INTERN ib_int64_t rw_x_exit_count = 0;
00166
00167
00168 UNIV_INTERN rw_lock_list_t rw_lock_list;
00169 UNIV_INTERN mutex_t rw_lock_list_mutex;
00170
00171 #ifdef UNIV_PFS_MUTEX
00172 UNIV_INTERN mysql_pfs_key_t rw_lock_list_mutex_key;
00173 UNIV_INTERN mysql_pfs_key_t rw_lock_mutex_key;
00174 #endif
00175
00176 #ifdef UNIV_SYNC_DEBUG
00177
00178
00179
00180
00181 UNIV_INTERN mutex_t rw_lock_debug_mutex;
00182
00183 # ifdef UNIV_PFS_MUTEX
00184 UNIV_INTERN mysql_pfs_key_t rw_lock_debug_mutex_key;
00185 # endif
00186
00187
00188
00189 UNIV_INTERN os_event_t rw_lock_debug_event;
00190
00191 UNIV_INTERN ibool rw_lock_debug_waiters;
00192
00193
00195 static
00196 rw_lock_debug_t*
00197 rw_lock_debug_create(void);
00198
00199
00201 static
00202 void
00203 rw_lock_debug_free(
00204
00205 rw_lock_debug_t* info);
00206
00207
00210 static
00211 rw_lock_debug_t*
00212 rw_lock_debug_create(void)
00213
00214 {
00215 return((rw_lock_debug_t*) mem_alloc(sizeof(rw_lock_debug_t)));
00216 }
00217
00218
00220 static
00221 void
00222 rw_lock_debug_free(
00223
00224 rw_lock_debug_t* info)
00225 {
00226 mem_free(info);
00227 }
00228 #endif
00229
00230
00235 UNIV_INTERN
00236 void
00237 rw_lock_create_func(
00238
00239 rw_lock_t* lock,
00240 #ifdef UNIV_DEBUG
00241 # ifdef UNIV_SYNC_DEBUG
00242 ulint level,
00243 # endif
00244 const char* cmutex_name,
00245 #endif
00246 const char* cfile_name,
00247 ulint cline)
00248 {
00249
00250
00251
00252 #ifndef INNODB_RW_LOCKS_USE_ATOMICS
00253 mutex_create(rw_lock_mutex_key, rw_lock_get_mutex(lock),
00254 SYNC_NO_ORDER_CHECK);
00255
00256 lock->mutex.cfile_name = cfile_name;
00257 lock->mutex.cline = cline;
00258
00259 ut_d(lock->mutex.cmutex_name = cmutex_name);
00260 ut_d(lock->mutex.mutex_type = 1);
00261 #else
00262 # ifdef UNIV_DEBUG
00263 UT_NOT_USED(cmutex_name);
00264 # endif
00265 #endif
00266
00267 lock->lock_word = X_LOCK_DECR;
00268 lock->waiters = 0;
00269
00270
00271
00272
00273 lock->recursive = FALSE;
00274
00275 #ifdef UNIV_SYNC_DEBUG
00276 UT_LIST_INIT(lock->debug_list);
00277
00278 lock->level = level;
00279 #endif
00280
00281 ut_d(lock->magic_n = RW_LOCK_MAGIC_N);
00282
00283 lock->cfile_name = cfile_name;
00284 lock->cline = (unsigned int) cline;
00285
00286 lock->count_os_wait = 0;
00287 lock->last_s_file_name = "not yet reserved";
00288 lock->last_x_file_name = "not yet reserved";
00289 lock->last_s_line = 0;
00290 lock->last_x_line = 0;
00291 lock->event = os_event_create(NULL);
00292 lock->wait_ex_event = os_event_create(NULL);
00293
00294 mutex_enter(&rw_lock_list_mutex);
00295
00296 ut_ad(UT_LIST_GET_FIRST(rw_lock_list) == NULL
00297 || UT_LIST_GET_FIRST(rw_lock_list)->magic_n == RW_LOCK_MAGIC_N);
00298
00299 UT_LIST_ADD_FIRST(list, rw_lock_list, lock);
00300
00301 mutex_exit(&rw_lock_list_mutex);
00302 }
00303
00304
00308 UNIV_INTERN
00309 void
00310 rw_lock_free_func(
00311
00312 rw_lock_t* lock)
00313 {
00314 ut_ad(rw_lock_validate(lock));
00315 ut_a(lock->lock_word == X_LOCK_DECR);
00316
00317 #ifndef INNODB_RW_LOCKS_USE_ATOMICS
00318 mutex_free(rw_lock_get_mutex(lock));
00319 #endif
00320
00321 mutex_enter(&rw_lock_list_mutex);
00322 os_event_free(lock->event);
00323
00324 os_event_free(lock->wait_ex_event);
00325
00326 ut_ad(UT_LIST_GET_PREV(list, lock) == NULL
00327 || UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N);
00328 ut_ad(UT_LIST_GET_NEXT(list, lock) == NULL
00329 || UT_LIST_GET_NEXT(list, lock)->magic_n == RW_LOCK_MAGIC_N);
00330
00331 UT_LIST_REMOVE(list, rw_lock_list, lock);
00332
00333 mutex_exit(&rw_lock_list_mutex);
00334
00335 ut_d(lock->magic_n = 0);
00336 }
00337
00338 #ifdef UNIV_DEBUG
00339
00343 UNIV_INTERN
00344 ibool
00345 rw_lock_validate(
00346
00347 rw_lock_t* lock)
00348 {
00349 ulint waiters;
00350 lint lock_word;
00351
00352 ut_a(lock);
00353
00354 waiters = rw_lock_get_waiters(lock);
00355 lock_word = lock->lock_word;
00356
00357 ut_ad(lock->magic_n == RW_LOCK_MAGIC_N);
00358 ut_a(waiters == 0 || waiters == 1);
00359 ut_a(lock_word > -X_LOCK_DECR ||(-lock_word) % X_LOCK_DECR == 0);
00360
00361 return(TRUE);
00362 }
00363 #endif
00364
00365
00370 UNIV_INTERN
00371 void
00372 rw_lock_s_lock_spin(
00373
00374 rw_lock_t* lock,
00375 ulint pass,
00377 const char* file_name,
00378 ulint line)
00379 {
00380 ulint index;
00381 ulint i = 0;
00382
00383 ut_ad(rw_lock_validate(lock));
00384
00385 rw_s_spin_wait_count++;
00386 lock_loop:
00387
00388
00389 while (i < SYNC_SPIN_ROUNDS && lock->lock_word <= 0) {
00390 if (srv_spin_wait_delay) {
00391 ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
00392 }
00393
00394 i++;
00395 }
00396
00397 if (i == SYNC_SPIN_ROUNDS) {
00398 os_thread_yield();
00399 }
00400
00401 if (srv_print_latch_waits) {
00402 fprintf(stderr,
00403 "Thread %lu spin wait rw-s-lock at %p"
00404 " cfile %s cline %lu rnds %lu\n",
00405 (ulong) os_thread_pf(os_thread_get_curr_id()),
00406 (void*) lock,
00407 lock->cfile_name, (ulong) lock->cline, (ulong) i);
00408 }
00409
00410
00411 if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) {
00412 rw_s_spin_round_count += i;
00413
00414 return;
00415 } else {
00416
00417 if (i < SYNC_SPIN_ROUNDS) {
00418 goto lock_loop;
00419 }
00420
00421 rw_s_spin_round_count += i;
00422
00423 sync_array_reserve_cell(sync_primary_wait_array,
00424 lock, RW_LOCK_SHARED,
00425 file_name, line,
00426 &index);
00427
00428
00429
00430 rw_lock_set_waiter_flag(lock);
00431
00432 if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) {
00433 sync_array_free_cell(sync_primary_wait_array, index);
00434 return;
00435 }
00436
00437 if (srv_print_latch_waits) {
00438 fprintf(stderr,
00439 "Thread %lu OS wait rw-s-lock at %p"
00440 " cfile %s cline %lu\n",
00441 os_thread_pf(os_thread_get_curr_id()),
00442 (void*) lock, lock->cfile_name,
00443 (ulong) lock->cline);
00444 }
00445
00446
00447 lock->count_os_wait++;
00448 rw_s_os_wait_count++;
00449
00450 sync_array_wait_event(sync_primary_wait_array, index);
00451
00452 i = 0;
00453 goto lock_loop;
00454 }
00455 }
00456
00457
00465 UNIV_INTERN
00466 void
00467 rw_lock_x_lock_move_ownership(
00468
00469 rw_lock_t* lock)
00471 {
00472 ut_ad(rw_lock_is_locked(lock, RW_LOCK_EX));
00473
00474 rw_lock_set_writer_id_and_recursion_flag(lock, TRUE);
00475 }
00476
00477
00480 UNIV_INLINE
00481 void
00482 rw_lock_x_lock_wait(
00483
00484 rw_lock_t* lock,
00485 #ifdef UNIV_SYNC_DEBUG
00486 ulint pass,
00488 #endif
00489 const char* file_name,
00490 ulint line)
00491 {
00492 ulint index;
00493 ulint i = 0;
00494
00495 ut_ad(lock->lock_word <= 0);
00496
00497 while (lock->lock_word < 0) {
00498 if (srv_spin_wait_delay) {
00499 ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
00500 }
00501 if(i < SYNC_SPIN_ROUNDS) {
00502 i++;
00503 continue;
00504 }
00505
00506
00507 rw_x_spin_round_count += i;
00508 i = 0;
00509 sync_array_reserve_cell(sync_primary_wait_array,
00510 lock,
00511 RW_LOCK_WAIT_EX,
00512 file_name, line,
00513 &index);
00514
00515 if(lock->lock_word < 0) {
00516
00517
00518 lock->count_os_wait++;
00519 rw_x_os_wait_count++;
00520
00521
00522
00523
00524 #ifdef UNIV_SYNC_DEBUG
00525 rw_lock_add_debug_info(lock, pass, RW_LOCK_WAIT_EX,
00526 file_name, line);
00527 #endif
00528
00529 sync_array_wait_event(sync_primary_wait_array,
00530 index);
00531 #ifdef UNIV_SYNC_DEBUG
00532 rw_lock_remove_debug_info(lock, pass,
00533 RW_LOCK_WAIT_EX);
00534 #endif
00535
00536
00537 } else {
00538 sync_array_free_cell(sync_primary_wait_array,
00539 index);
00540 }
00541 }
00542 rw_x_spin_round_count += i;
00543 }
00544
00545
00548 UNIV_INLINE
00549 ibool
00550 rw_lock_x_lock_low(
00551
00552 rw_lock_t* lock,
00553 ulint pass,
00555 const char* file_name,
00556 ulint line)
00557 {
00558 os_thread_id_t curr_thread = os_thread_get_curr_id();
00559
00560 if (rw_lock_lock_word_decr(lock, X_LOCK_DECR)) {
00561
00562
00563
00564
00565
00566 ut_a(!lock->recursive);
00567
00568
00569 rw_lock_set_writer_id_and_recursion_flag(lock,
00570 pass ? FALSE : TRUE);
00571
00572 rw_lock_x_lock_wait(lock,
00573 #ifdef UNIV_SYNC_DEBUG
00574 pass,
00575 #endif
00576 file_name, line);
00577
00578 } else {
00579
00580 if (!pass && lock->recursive
00581 && os_thread_eq(lock->writer_thread, curr_thread)) {
00582
00583 lock->lock_word -= X_LOCK_DECR;
00584 } else {
00585
00586 return(FALSE);
00587 }
00588 }
00589 #ifdef UNIV_SYNC_DEBUG
00590 rw_lock_add_debug_info(lock, pass, RW_LOCK_EX,
00591 file_name, line);
00592 #endif
00593 lock->last_x_file_name = file_name;
00594 lock->last_x_line = (unsigned int) line;
00595
00596 return(TRUE);
00597 }
00598
00599
00608 UNIV_INTERN
00609 void
00610 rw_lock_x_lock_func(
00611
00612 rw_lock_t* lock,
00613 ulint pass,
00615 const char* file_name,
00616 ulint line)
00617 {
00618 ulint index;
00619 ulint i;
00620 ibool spinning = FALSE;
00621
00622 ut_ad(rw_lock_validate(lock));
00623
00624 i = 0;
00625
00626 lock_loop:
00627
00628 if (rw_lock_x_lock_low(lock, pass, file_name, line)) {
00629 rw_x_spin_round_count += i;
00630
00631 return;
00632
00633 } else {
00634
00635 if (!spinning) {
00636 spinning = TRUE;
00637 rw_x_spin_wait_count++;
00638 }
00639
00640
00641 while (i < SYNC_SPIN_ROUNDS
00642 && lock->lock_word <= 0) {
00643 if (srv_spin_wait_delay) {
00644 ut_delay(ut_rnd_interval(0,
00645 srv_spin_wait_delay));
00646 }
00647
00648 i++;
00649 }
00650 if (i == SYNC_SPIN_ROUNDS) {
00651 os_thread_yield();
00652 } else {
00653 goto lock_loop;
00654 }
00655 }
00656
00657 rw_x_spin_round_count += i;
00658
00659 if (srv_print_latch_waits) {
00660 fprintf(stderr,
00661 "Thread %lu spin wait rw-x-lock at %p"
00662 " cfile %s cline %lu rnds %lu\n",
00663 os_thread_pf(os_thread_get_curr_id()), (void*) lock,
00664 lock->cfile_name, (ulong) lock->cline, (ulong) i);
00665 }
00666
00667 sync_array_reserve_cell(sync_primary_wait_array,
00668 lock,
00669 RW_LOCK_EX,
00670 file_name, line,
00671 &index);
00672
00673
00674
00675 rw_lock_set_waiter_flag(lock);
00676
00677 if (rw_lock_x_lock_low(lock, pass, file_name, line)) {
00678 sync_array_free_cell(sync_primary_wait_array, index);
00679 return;
00680 }
00681
00682 if (srv_print_latch_waits) {
00683 fprintf(stderr,
00684 "Thread %lu OS wait for rw-x-lock at %p"
00685 " cfile %s cline %lu\n",
00686 os_thread_pf(os_thread_get_curr_id()), (void*) lock,
00687 lock->cfile_name, (ulong) lock->cline);
00688 }
00689
00690
00691 lock->count_os_wait++;
00692 rw_x_os_wait_count++;
00693
00694 sync_array_wait_event(sync_primary_wait_array, index);
00695
00696 i = 0;
00697 goto lock_loop;
00698 }
00699
00700 #ifdef UNIV_SYNC_DEBUG
00701
00707 UNIV_INTERN
00708 void
00709 rw_lock_debug_mutex_enter(void)
00710
00711 {
00712 loop:
00713 if (0 == mutex_enter_nowait(&rw_lock_debug_mutex)) {
00714 return;
00715 }
00716
00717 os_event_reset(rw_lock_debug_event);
00718
00719 rw_lock_debug_waiters = TRUE;
00720
00721 if (0 == mutex_enter_nowait(&rw_lock_debug_mutex)) {
00722 return;
00723 }
00724
00725 os_event_wait(rw_lock_debug_event);
00726
00727 goto loop;
00728 }
00729
00730
00732 UNIV_INTERN
00733 void
00734 rw_lock_debug_mutex_exit(void)
00735
00736 {
00737 mutex_exit(&rw_lock_debug_mutex);
00738
00739 if (rw_lock_debug_waiters) {
00740 rw_lock_debug_waiters = FALSE;
00741 os_event_set(rw_lock_debug_event);
00742 }
00743 }
00744
00745
00747 UNIV_INTERN
00748 void
00749 rw_lock_add_debug_info(
00750
00751 rw_lock_t* lock,
00752 ulint pass,
00753 ulint lock_type,
00754 const char* file_name,
00755 ulint line)
00756 {
00757 rw_lock_debug_t* info;
00758
00759 ut_ad(lock);
00760 ut_ad(file_name);
00761
00762 info = rw_lock_debug_create();
00763
00764 rw_lock_debug_mutex_enter();
00765
00766 info->file_name = file_name;
00767 info->line = line;
00768 info->lock_type = lock_type;
00769 info->thread_id = os_thread_get_curr_id();
00770 info->pass = pass;
00771
00772 UT_LIST_ADD_FIRST(list, lock->debug_list, info);
00773
00774 rw_lock_debug_mutex_exit();
00775
00776 if ((pass == 0) && (lock_type != RW_LOCK_WAIT_EX)) {
00777 sync_thread_add_level(lock, lock->level);
00778 }
00779 }
00780
00781
00783 UNIV_INTERN
00784 void
00785 rw_lock_remove_debug_info(
00786
00787 rw_lock_t* lock,
00788 ulint pass,
00789 ulint lock_type)
00790 {
00791 rw_lock_debug_t* info;
00792
00793 ut_ad(lock);
00794
00795 if ((pass == 0) && (lock_type != RW_LOCK_WAIT_EX)) {
00796 sync_thread_reset_level(lock);
00797 }
00798
00799 rw_lock_debug_mutex_enter();
00800
00801 info = UT_LIST_GET_FIRST(lock->debug_list);
00802
00803 while (info != NULL) {
00804 if ((pass == info->pass)
00805 && ((pass != 0)
00806 || os_thread_eq(info->thread_id,
00807 os_thread_get_curr_id()))
00808 && (info->lock_type == lock_type)) {
00809
00810
00811 UT_LIST_REMOVE(list, lock->debug_list, info);
00812 rw_lock_debug_mutex_exit();
00813
00814 rw_lock_debug_free(info);
00815
00816 return;
00817 }
00818
00819 info = UT_LIST_GET_NEXT(list, info);
00820 }
00821
00822 ut_error;
00823 }
00824 #endif
00825
00826 #ifdef UNIV_SYNC_DEBUG
00827
00831 UNIV_INTERN
00832 ibool
00833 rw_lock_own(
00834
00835 rw_lock_t* lock,
00836 ulint lock_type)
00838 {
00839 rw_lock_debug_t* info;
00840
00841 ut_ad(lock);
00842 ut_ad(rw_lock_validate(lock));
00843
00844 rw_lock_debug_mutex_enter();
00845
00846 info = UT_LIST_GET_FIRST(lock->debug_list);
00847
00848 while (info != NULL) {
00849
00850 if (os_thread_eq(info->thread_id, os_thread_get_curr_id())
00851 && (info->pass == 0)
00852 && (info->lock_type == lock_type)) {
00853
00854 rw_lock_debug_mutex_exit();
00855
00856
00857 return(TRUE);
00858 }
00859
00860 info = UT_LIST_GET_NEXT(list, info);
00861 }
00862 rw_lock_debug_mutex_exit();
00863
00864 return(FALSE);
00865 }
00866 #endif
00867
00868
00871 UNIV_INTERN
00872 ibool
00873 rw_lock_is_locked(
00874
00875 rw_lock_t* lock,
00876 ulint lock_type)
00878 {
00879 ibool ret = FALSE;
00880
00881 ut_ad(lock);
00882 ut_ad(rw_lock_validate(lock));
00883
00884 if (lock_type == RW_LOCK_SHARED) {
00885 if (rw_lock_get_reader_count(lock) > 0) {
00886 ret = TRUE;
00887 }
00888 } else if (lock_type == RW_LOCK_EX) {
00889 if (rw_lock_get_writer(lock) == RW_LOCK_EX) {
00890 ret = TRUE;
00891 }
00892 } else {
00893 ut_error;
00894 }
00895
00896 return(ret);
00897 }
00898
00899 #ifdef UNIV_SYNC_DEBUG
00900
00902 UNIV_INTERN
00903 void
00904 rw_lock_list_print_info(
00905
00906 FILE* file)
00907 {
00908 rw_lock_t* lock;
00909 ulint count = 0;
00910 rw_lock_debug_t* info;
00911
00912 mutex_enter(&rw_lock_list_mutex);
00913
00914 fputs("-------------\n"
00915 "RW-LATCH INFO\n"
00916 "-------------\n", file);
00917
00918 lock = UT_LIST_GET_FIRST(rw_lock_list);
00919
00920 while (lock != NULL) {
00921
00922 count++;
00923
00924 #ifndef INNODB_RW_LOCKS_USE_ATOMICS
00925 mutex_enter(&(lock->mutex));
00926 #endif
00927 if (lock->lock_word != X_LOCK_DECR) {
00928
00929 fprintf(file, "RW-LOCK: %p ", (void*) lock);
00930
00931 if (rw_lock_get_waiters(lock)) {
00932 fputs(" Waiters for the lock exist\n", file);
00933 } else {
00934 putc('\n', file);
00935 }
00936
00937 info = UT_LIST_GET_FIRST(lock->debug_list);
00938 while (info != NULL) {
00939 rw_lock_debug_print(info);
00940 info = UT_LIST_GET_NEXT(list, info);
00941 }
00942 }
00943 #ifndef INNODB_RW_LOCKS_USE_ATOMICS
00944 mutex_exit(&(lock->mutex));
00945 #endif
00946
00947 lock = UT_LIST_GET_NEXT(list, lock);
00948 }
00949
00950 fprintf(file, "Total number of rw-locks %ld\n", count);
00951 mutex_exit(&rw_lock_list_mutex);
00952 }
00953
00954
00956 UNIV_INTERN
00957 void
00958 rw_lock_print(
00959
00960 rw_lock_t* lock)
00961 {
00962 rw_lock_debug_t* info;
00963
00964 fprintf(stderr,
00965 "-------------\n"
00966 "RW-LATCH INFO\n"
00967 "RW-LATCH: %p ", (void*) lock);
00968
00969 #ifndef INNODB_RW_LOCKS_USE_ATOMICS
00970
00971
00972
00973
00974
00975
00976 #endif
00977 if (lock->lock_word != X_LOCK_DECR) {
00978
00979 if (rw_lock_get_waiters(lock)) {
00980 fputs(" Waiters for the lock exist\n", stderr);
00981 } else {
00982 putc('\n', stderr);
00983 }
00984
00985 info = UT_LIST_GET_FIRST(lock->debug_list);
00986 while (info != NULL) {
00987 rw_lock_debug_print(info);
00988 info = UT_LIST_GET_NEXT(list, info);
00989 }
00990 }
00991 }
00992
00993
00995 UNIV_INTERN
00996 void
00997 rw_lock_debug_print(
00998
00999 rw_lock_debug_t* info)
01000 {
01001 ulint rwt;
01002
01003 rwt = info->lock_type;
01004
01005 fprintf(stderr, "Locked: thread %lu file %s line %lu ",
01006 (ulong) os_thread_pf(info->thread_id), info->file_name,
01007 (ulong) info->line);
01008 if (rwt == RW_LOCK_SHARED) {
01009 fputs("S-LOCK", stderr);
01010 } else if (rwt == RW_LOCK_EX) {
01011 fputs("X-LOCK", stderr);
01012 } else if (rwt == RW_LOCK_WAIT_EX) {
01013 fputs("WAIT X-LOCK", stderr);
01014 } else {
01015 ut_error;
01016 }
01017 if (info->pass != 0) {
01018 fprintf(stderr, " pass value %lu", (ulong) info->pass);
01019 }
01020 putc('\n', stderr);
01021 }
01022
01023
01027 UNIV_INTERN
01028 ulint
01029 rw_lock_n_locked(void)
01030
01031 {
01032 rw_lock_t* lock;
01033 ulint count = 0;
01034
01035 mutex_enter(&rw_lock_list_mutex);
01036
01037 lock = UT_LIST_GET_FIRST(rw_lock_list);
01038
01039 while (lock != NULL) {
01040
01041 if (lock->lock_word != X_LOCK_DECR) {
01042 count++;
01043 }
01044
01045 lock = UT_LIST_GET_NEXT(list, lock);
01046 }
01047
01048 mutex_exit(&rw_lock_list_mutex);
01049
01050 return(count);
01051 }
01052 #endif