1
/******************************************************
2
The read-write lock (for thread synchronization)
6
Created 9/11/1995 Heikki Tuuri
7
*******************************************************/
14
#include "os0thread.h"
18
/* number of system calls made during shared latching */
19
UNIV_INTERN ulint rw_s_system_call_count = 0;
21
/* number of spin waits on rw-latches,
22
resulted during shared (read) locks */
23
UNIV_INTERN ulint rw_s_spin_wait_count = 0;
25
/* number of OS waits on rw-latches,
26
resulted during shared (read) locks */
27
UNIV_INTERN ulint rw_s_os_wait_count = 0;
29
/* number of unlocks (that unlock shared locks),
30
set only when UNIV_SYNC_PERF_STAT is defined */
31
UNIV_INTERN ulint rw_s_exit_count = 0;
33
/* number of system calls made during exclusive latching */
34
UNIV_INTERN ulint rw_x_system_call_count = 0;
36
/* number of spin waits on rw-latches,
37
resulted during exclusive (write) locks */
38
UNIV_INTERN ulint rw_x_spin_wait_count = 0;
40
/* number of OS waits on rw-latches,
41
resulted during exclusive (write) locks */
42
UNIV_INTERN ulint rw_x_os_wait_count = 0;
44
/* number of unlocks (that unlock exclusive locks),
45
set only when UNIV_SYNC_PERF_STAT is defined */
46
UNIV_INTERN ulint rw_x_exit_count = 0;
48
/* The global list of rw-locks */
49
UNIV_INTERN rw_lock_list_t rw_lock_list;
50
UNIV_INTERN mutex_t rw_lock_list_mutex;
52
#ifdef UNIV_SYNC_DEBUG
53
/* The global mutex which protects debug info lists of all rw-locks.
54
To modify the debug info list of an rw-lock, this mutex has to be
55
acquired in addition to the mutex protecting the lock. */
57
UNIV_INTERN mutex_t rw_lock_debug_mutex;
58
/* If deadlock detection does not get immediately the mutex,
59
it may wait for this event */
60
UNIV_INTERN os_event_t rw_lock_debug_event;
61
/* This is set to TRUE, if there may be waiters for the event */
62
UNIV_INTERN ibool rw_lock_debug_waiters;
64
/**********************************************************************
65
Creates a debug info struct. */
68
rw_lock_debug_create(void);
69
/*======================*/
70
/**********************************************************************
71
Frees a debug info struct. */
76
rw_lock_debug_t* info);
78
/**********************************************************************
79
Creates a debug info struct. */
82
rw_lock_debug_create(void)
83
/*======================*/
85
return((rw_lock_debug_t*) mem_alloc(sizeof(rw_lock_debug_t)));
88
/**********************************************************************
89
Frees a debug info struct. */
94
rw_lock_debug_t* info)
98
#endif /* UNIV_SYNC_DEBUG */
100
/**********************************************************************
101
Creates, or rather, initializes an rw-lock object in a specified memory
102
location (which must be appropriately aligned). The rw-lock is initialized
103
to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free
104
is necessary only if the memory block containing it is freed. */
109
rw_lock_t* lock, /* in: pointer to memory */
111
# ifdef UNIV_SYNC_DEBUG
112
ulint level, /* in: level */
113
# endif /* UNIV_SYNC_DEBUG */
114
const char* cmutex_name, /* in: mutex name */
115
#endif /* UNIV_DEBUG */
116
const char* cfile_name, /* in: file name where created */
117
ulint cline) /* in: file line where created */
119
/* If this is the very first time a synchronization object is
120
created, then the following call initializes the sync system. */
122
mutex_create(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK);
124
lock->mutex.cfile_name = cfile_name;
125
lock->mutex.cline = cline;
127
#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP
128
lock->mutex.cmutex_name = cmutex_name;
129
lock->mutex.mutex_type = 1;
130
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
132
rw_lock_set_waiters(lock, 0);
133
rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
134
lock->writer_count = 0;
135
rw_lock_set_reader_count(lock, 0);
137
lock->writer_is_wait_ex = FALSE;
139
#ifdef UNIV_SYNC_DEBUG
140
UT_LIST_INIT(lock->debug_list);
143
#endif /* UNIV_SYNC_DEBUG */
145
lock->magic_n = RW_LOCK_MAGIC_N;
147
lock->cfile_name = cfile_name;
148
lock->cline = (unsigned int) cline;
150
lock->last_s_file_name = "not yet reserved";
151
lock->last_x_file_name = "not yet reserved";
152
lock->last_s_line = 0;
153
lock->last_x_line = 0;
154
lock->event = os_event_create(NULL);
157
lock->wait_ex_event = os_event_create(NULL);
160
mutex_enter(&rw_lock_list_mutex);
162
if (UT_LIST_GET_LEN(rw_lock_list) > 0) {
163
ut_a(UT_LIST_GET_FIRST(rw_lock_list)->magic_n
167
UT_LIST_ADD_FIRST(list, rw_lock_list, lock);
169
mutex_exit(&rw_lock_list_mutex);
172
/**********************************************************************
173
Calling this function is obligatory only if the memory buffer containing
174
the rw-lock is freed. Removes an rw-lock object from the global list. The
175
rw-lock is checked to be in the non-locked state. */
180
rw_lock_t* lock) /* in: rw-lock */
182
ut_ad(rw_lock_validate(lock));
183
ut_a(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED);
184
ut_a(rw_lock_get_waiters(lock) == 0);
185
ut_a(rw_lock_get_reader_count(lock) == 0);
189
mutex_free(rw_lock_get_mutex(lock));
191
mutex_enter(&rw_lock_list_mutex);
192
os_event_free(lock->event);
195
os_event_free(lock->wait_ex_event);
198
if (UT_LIST_GET_PREV(list, lock)) {
199
ut_a(UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N);
201
if (UT_LIST_GET_NEXT(list, lock)) {
202
ut_a(UT_LIST_GET_NEXT(list, lock)->magic_n == RW_LOCK_MAGIC_N);
205
UT_LIST_REMOVE(list, rw_lock_list, lock);
207
mutex_exit(&rw_lock_list_mutex);
211
/**********************************************************************
212
Checks that the rw-lock has been initialized and that there are no
213
simultaneous shared and exclusive locks. */
222
mutex_enter(rw_lock_get_mutex(lock));
224
ut_a(lock->magic_n == RW_LOCK_MAGIC_N);
225
ut_a((rw_lock_get_reader_count(lock) == 0)
226
|| (rw_lock_get_writer(lock) != RW_LOCK_EX));
227
ut_a((rw_lock_get_writer(lock) == RW_LOCK_EX)
228
|| (rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX)
229
|| (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED));
230
ut_a((rw_lock_get_waiters(lock) == 0)
231
|| (rw_lock_get_waiters(lock) == 1));
232
ut_a((lock->writer != RW_LOCK_EX) || (lock->writer_count > 0));
234
mutex_exit(rw_lock_get_mutex(lock));
238
#endif /* UNIV_DEBUG */
240
/**********************************************************************
241
Lock an rw-lock in shared mode for the current thread. If the rw-lock is
242
locked in exclusive mode, or there is an exclusive lock request waiting,
243
the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting
244
for the lock, before suspending the thread. */
249
rw_lock_t* lock, /* in: pointer to rw-lock */
250
ulint pass, /* in: pass value; != 0, if the lock
251
will be passed to another thread to unlock */
252
const char* file_name, /* in: file name where lock requested */
253
ulint line) /* in: line where requested */
255
ulint index; /* index of the reserved wait cell */
256
ulint i; /* spin round count */
258
ut_ad(rw_lock_validate(lock));
261
rw_s_spin_wait_count++;
263
/* Spin waiting for the writer field to become free */
266
while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED
267
&& i < SYNC_SPIN_ROUNDS) {
268
if (srv_spin_wait_delay) {
269
ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
275
if (i == SYNC_SPIN_ROUNDS) {
279
if (srv_print_latch_waits) {
281
"Thread %lu spin wait rw-s-lock at %p"
282
" cfile %s cline %lu rnds %lu\n",
283
(ulong) os_thread_pf(os_thread_get_curr_id()),
285
lock->cfile_name, (ulong) lock->cline, (ulong) i);
288
mutex_enter(rw_lock_get_mutex(lock));
290
/* We try once again to obtain the lock */
292
if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) {
293
mutex_exit(rw_lock_get_mutex(lock));
295
return; /* Success */
297
/* If we get here, locking did not succeed, we may
298
suspend the thread to wait in the wait array */
300
rw_s_system_call_count++;
302
sync_array_reserve_cell(sync_primary_wait_array,
303
lock, RW_LOCK_SHARED,
307
rw_lock_set_waiters(lock, 1);
309
mutex_exit(rw_lock_get_mutex(lock));
311
if (srv_print_latch_waits) {
313
"Thread %lu OS wait rw-s-lock at %p"
314
" cfile %s cline %lu\n",
315
os_thread_pf(os_thread_get_curr_id()),
316
(void*) lock, lock->cfile_name,
317
(ulong) lock->cline);
320
rw_s_system_call_count++;
321
rw_s_os_wait_count++;
323
sync_array_wait_event(sync_primary_wait_array, index);
329
/**********************************************************************
330
This function is used in the insert buffer to move the ownership of an
331
x-latch on a buffer frame to the current thread. The x-latch was set by
332
the buffer read operation and it protected the buffer frame while the
333
read was done. The ownership is moved because we want that the current
334
thread is able to acquire a second x-latch which is stored in an mtr.
335
This, in turn, is needed to pass the debug checks of index page
339
rw_lock_x_lock_move_ownership(
340
/*==========================*/
341
rw_lock_t* lock) /* in: lock which was x-locked in the
344
ut_ad(rw_lock_is_locked(lock, RW_LOCK_EX));
346
mutex_enter(&(lock->mutex));
348
lock->writer_thread = os_thread_get_curr_id();
352
mutex_exit(&(lock->mutex));
355
/**********************************************************************
356
Low-level function for acquiring an exclusive lock. */
361
/* out: RW_LOCK_NOT_LOCKED if did
362
not succeed, RW_LOCK_EX if success,
363
RW_LOCK_WAIT_EX, if got wait reservation */
364
rw_lock_t* lock, /* in: pointer to rw-lock */
365
ulint pass, /* in: pass value; != 0, if the lock will
366
be passed to another thread to unlock */
367
const char* file_name,/* in: file name where lock requested */
368
ulint line) /* in: line where requested */
370
ut_ad(mutex_own(rw_lock_get_mutex(lock)));
372
if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
374
if (rw_lock_get_reader_count(lock) == 0) {
376
rw_lock_set_writer(lock, RW_LOCK_EX);
377
lock->writer_thread = os_thread_get_curr_id();
378
lock->writer_count++;
381
#ifdef UNIV_SYNC_DEBUG
382
rw_lock_add_debug_info(lock, pass, RW_LOCK_EX,
385
lock->last_x_file_name = file_name;
386
lock->last_x_line = (unsigned int) line;
388
/* Locking succeeded, we may return */
391
/* There are readers, we have to wait */
392
rw_lock_set_writer(lock, RW_LOCK_WAIT_EX);
393
lock->writer_thread = os_thread_get_curr_id();
395
lock->writer_is_wait_ex = TRUE;
397
#ifdef UNIV_SYNC_DEBUG
398
rw_lock_add_debug_info(lock, pass, RW_LOCK_WAIT_EX,
402
return(RW_LOCK_WAIT_EX);
405
} else if ((rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX)
406
&& os_thread_eq(lock->writer_thread,
407
os_thread_get_curr_id())) {
409
if (rw_lock_get_reader_count(lock) == 0) {
411
rw_lock_set_writer(lock, RW_LOCK_EX);
412
lock->writer_count++;
414
lock->writer_is_wait_ex = FALSE;
416
#ifdef UNIV_SYNC_DEBUG
417
rw_lock_remove_debug_info(lock, pass, RW_LOCK_WAIT_EX);
418
rw_lock_add_debug_info(lock, pass, RW_LOCK_EX,
422
lock->last_x_file_name = file_name;
423
lock->last_x_line = (unsigned int) line;
425
/* Locking succeeded, we may return */
429
return(RW_LOCK_WAIT_EX);
431
} else if ((rw_lock_get_writer(lock) == RW_LOCK_EX)
432
&& os_thread_eq(lock->writer_thread,
433
os_thread_get_curr_id())
437
lock->writer_count++;
439
#ifdef UNIV_SYNC_DEBUG
440
rw_lock_add_debug_info(lock, pass, RW_LOCK_EX, file_name,
444
lock->last_x_file_name = file_name;
445
lock->last_x_line = (unsigned int) line;
447
/* Locking succeeded, we may return */
451
/* Locking did not succeed */
452
return(RW_LOCK_NOT_LOCKED);
455
/**********************************************************************
456
NOTE! Use the corresponding macro, not directly this function! Lock an
457
rw-lock in exclusive mode for the current thread. If the rw-lock is locked
458
in shared or exclusive mode, or there is an exclusive lock request waiting,
459
the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting
460
for the lock before suspending the thread. If the same thread has an x-lock
461
on the rw-lock, locking succeed, with the following exception: if pass != 0,
462
only a single x-lock may be taken on the lock. NOTE: If the same thread has
463
an s-lock, locking does not succeed! */
468
rw_lock_t* lock, /* in: pointer to rw-lock */
469
ulint pass, /* in: pass value; != 0, if the lock will
470
be passed to another thread to unlock */
471
const char* file_name,/* in: file name where lock requested */
472
ulint line) /* in: line where requested */
474
ulint index; /* index of the reserved wait cell */
475
ulint state; /* lock state acquired */
476
ulint i; /* spin round count */
478
ut_ad(rw_lock_validate(lock));
481
/* Acquire the mutex protecting the rw-lock fields */
482
mutex_enter_fast(&(lock->mutex));
484
state = rw_lock_x_lock_low(lock, pass, file_name, line);
486
mutex_exit(&(lock->mutex));
488
if (state == RW_LOCK_EX) {
490
return; /* Locking succeeded */
492
} else if (state == RW_LOCK_NOT_LOCKED) {
494
/* Spin waiting for the writer field to become free */
497
while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED
498
&& i < SYNC_SPIN_ROUNDS) {
499
if (srv_spin_wait_delay) {
500
ut_delay(ut_rnd_interval(0,
501
srv_spin_wait_delay));
506
if (i == SYNC_SPIN_ROUNDS) {
509
} else if (state == RW_LOCK_WAIT_EX) {
511
/* Spin waiting for the reader count field to become zero */
514
while (rw_lock_get_reader_count(lock) != 0
515
&& i < SYNC_SPIN_ROUNDS) {
516
if (srv_spin_wait_delay) {
517
ut_delay(ut_rnd_interval(0,
518
srv_spin_wait_delay));
523
if (i == SYNC_SPIN_ROUNDS) {
527
i = 0; /* Eliminate a compiler warning */
531
if (srv_print_latch_waits) {
533
"Thread %lu spin wait rw-x-lock at %p"
534
" cfile %s cline %lu rnds %lu\n",
535
os_thread_pf(os_thread_get_curr_id()), (void*) lock,
536
lock->cfile_name, (ulong) lock->cline, (ulong) i);
539
rw_x_spin_wait_count++;
541
/* We try once again to obtain the lock. Acquire the mutex protecting
542
the rw-lock fields */
544
mutex_enter(rw_lock_get_mutex(lock));
546
state = rw_lock_x_lock_low(lock, pass, file_name, line);
548
if (state == RW_LOCK_EX) {
549
mutex_exit(rw_lock_get_mutex(lock));
551
return; /* Locking succeeded */
554
rw_x_system_call_count++;
556
sync_array_reserve_cell(sync_primary_wait_array,
559
/* On windows RW_LOCK_WAIT_EX signifies
560
that this thread should wait on the
561
special wait_ex_event. */
562
(state == RW_LOCK_WAIT_EX)
569
rw_lock_set_waiters(lock, 1);
571
mutex_exit(rw_lock_get_mutex(lock));
573
if (srv_print_latch_waits) {
575
"Thread %lu OS wait for rw-x-lock at %p"
576
" cfile %s cline %lu\n",
577
os_thread_pf(os_thread_get_curr_id()), (void*) lock,
578
lock->cfile_name, (ulong) lock->cline);
581
rw_x_system_call_count++;
582
rw_x_os_wait_count++;
584
sync_array_wait_event(sync_primary_wait_array, index);
589
#ifdef UNIV_SYNC_DEBUG
590
/**********************************************************************
591
Acquires the debug mutex. We cannot use the mutex defined in sync0sync,
592
because the debug mutex is also acquired in sync0arr while holding the OS
593
mutex protecting the sync array, and the ordinary mutex_enter might
594
recursively call routines in sync0arr, leading to a deadlock on the OS
598
rw_lock_debug_mutex_enter(void)
599
/*==========================*/
602
if (0 == mutex_enter_nowait(&rw_lock_debug_mutex)) {
606
os_event_reset(rw_lock_debug_event);
608
rw_lock_debug_waiters = TRUE;
610
if (0 == mutex_enter_nowait(&rw_lock_debug_mutex)) {
614
os_event_wait(rw_lock_debug_event);
619
/**********************************************************************
620
Releases the debug mutex. */
623
rw_lock_debug_mutex_exit(void)
624
/*==========================*/
626
mutex_exit(&rw_lock_debug_mutex);
628
if (rw_lock_debug_waiters) {
629
rw_lock_debug_waiters = FALSE;
630
os_event_set(rw_lock_debug_event);
634
/**********************************************************************
635
Inserts the debug information for an rw-lock. */
638
rw_lock_add_debug_info(
639
/*===================*/
640
rw_lock_t* lock, /* in: rw-lock */
641
ulint pass, /* in: pass value */
642
ulint lock_type, /* in: lock type */
643
const char* file_name, /* in: file where requested */
644
ulint line) /* in: line where requested */
646
rw_lock_debug_t* info;
651
info = rw_lock_debug_create();
653
rw_lock_debug_mutex_enter();
655
info->file_name = file_name;
657
info->lock_type = lock_type;
658
info->thread_id = os_thread_get_curr_id();
661
UT_LIST_ADD_FIRST(list, lock->debug_list, info);
663
rw_lock_debug_mutex_exit();
665
if ((pass == 0) && (lock_type != RW_LOCK_WAIT_EX)) {
666
sync_thread_add_level(lock, lock->level);
670
/**********************************************************************
671
Removes a debug information struct for an rw-lock. */
674
rw_lock_remove_debug_info(
675
/*======================*/
676
rw_lock_t* lock, /* in: rw-lock */
677
ulint pass, /* in: pass value */
678
ulint lock_type) /* in: lock type */
680
rw_lock_debug_t* info;
684
if ((pass == 0) && (lock_type != RW_LOCK_WAIT_EX)) {
685
sync_thread_reset_level(lock);
688
rw_lock_debug_mutex_enter();
690
info = UT_LIST_GET_FIRST(lock->debug_list);
692
while (info != NULL) {
693
if ((pass == info->pass)
695
|| os_thread_eq(info->thread_id,
696
os_thread_get_curr_id()))
697
&& (info->lock_type == lock_type)) {
700
UT_LIST_REMOVE(list, lock->debug_list, info);
701
rw_lock_debug_mutex_exit();
703
rw_lock_debug_free(info);
708
info = UT_LIST_GET_NEXT(list, info);
713
#endif /* UNIV_SYNC_DEBUG */
715
#ifdef UNIV_SYNC_DEBUG
716
/**********************************************************************
717
Checks if the thread has locked the rw-lock in the specified mode, with
718
the pass value == 0. */
723
/* out: TRUE if locked */
724
rw_lock_t* lock, /* in: rw-lock */
725
ulint lock_type) /* in: lock type: RW_LOCK_SHARED,
728
rw_lock_debug_t* info;
731
ut_ad(rw_lock_validate(lock));
733
mutex_enter(&(lock->mutex));
735
info = UT_LIST_GET_FIRST(lock->debug_list);
737
while (info != NULL) {
739
if (os_thread_eq(info->thread_id, os_thread_get_curr_id())
741
&& (info->lock_type == lock_type)) {
743
mutex_exit(&(lock->mutex));
749
info = UT_LIST_GET_NEXT(list, info);
751
mutex_exit(&(lock->mutex));
755
#endif /* UNIV_SYNC_DEBUG */
757
/**********************************************************************
758
Checks if somebody has locked the rw-lock in the specified mode. */
763
/* out: TRUE if locked */
764
rw_lock_t* lock, /* in: rw-lock */
765
ulint lock_type) /* in: lock type: RW_LOCK_SHARED,
771
ut_ad(rw_lock_validate(lock));
773
mutex_enter(&(lock->mutex));
775
if (lock_type == RW_LOCK_SHARED) {
776
if (lock->reader_count > 0) {
779
} else if (lock_type == RW_LOCK_EX) {
780
if (lock->writer == RW_LOCK_EX) {
787
mutex_exit(&(lock->mutex));
792
#ifdef UNIV_SYNC_DEBUG
793
/*******************************************************************
794
Prints debug info of currently locked rw-locks. */
797
rw_lock_list_print_info(
798
/*====================*/
799
FILE* file) /* in: file where to print */
803
rw_lock_debug_t* info;
805
mutex_enter(&rw_lock_list_mutex);
807
fputs("-------------\n"
809
"-------------\n", file);
811
lock = UT_LIST_GET_FIRST(rw_lock_list);
813
while (lock != NULL) {
817
mutex_enter(&(lock->mutex));
819
if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
820
|| (rw_lock_get_reader_count(lock) != 0)
821
|| (rw_lock_get_waiters(lock) != 0)) {
823
fprintf(file, "RW-LOCK: %p ", (void*) lock);
825
if (rw_lock_get_waiters(lock)) {
826
fputs(" Waiters for the lock exist\n", file);
831
info = UT_LIST_GET_FIRST(lock->debug_list);
832
while (info != NULL) {
833
rw_lock_debug_print(info);
834
info = UT_LIST_GET_NEXT(list, info);
838
mutex_exit(&(lock->mutex));
839
lock = UT_LIST_GET_NEXT(list, lock);
842
fprintf(file, "Total number of rw-locks %ld\n", count);
843
mutex_exit(&rw_lock_list_mutex);
846
/*******************************************************************
847
Prints debug info of an rw-lock. */
852
rw_lock_t* lock) /* in: rw-lock */
854
rw_lock_debug_t* info;
859
"RW-LATCH: %p ", (void*) lock);
861
if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
862
|| (rw_lock_get_reader_count(lock) != 0)
863
|| (rw_lock_get_waiters(lock) != 0)) {
865
if (rw_lock_get_waiters(lock)) {
866
fputs(" Waiters for the lock exist\n", stderr);
871
info = UT_LIST_GET_FIRST(lock->debug_list);
872
while (info != NULL) {
873
rw_lock_debug_print(info);
874
info = UT_LIST_GET_NEXT(list, info);
879
/*************************************************************************
880
Prints info of a debug struct. */
885
rw_lock_debug_t* info) /* in: debug struct */
889
rwt = info->lock_type;
891
fprintf(stderr, "Locked: thread %ld file %s line %ld ",
892
(ulong) os_thread_pf(info->thread_id), info->file_name,
894
if (rwt == RW_LOCK_SHARED) {
895
fputs("S-LOCK", stderr);
896
} else if (rwt == RW_LOCK_EX) {
897
fputs("X-LOCK", stderr);
898
} else if (rwt == RW_LOCK_WAIT_EX) {
899
fputs("WAIT X-LOCK", stderr);
903
if (info->pass != 0) {
904
fprintf(stderr, " pass value %lu", (ulong) info->pass);
909
/*******************************************************************
910
Returns the number of currently locked rw-locks. Works only in the debug
914
rw_lock_n_locked(void)
915
/*==================*/
920
mutex_enter(&rw_lock_list_mutex);
922
lock = UT_LIST_GET_FIRST(rw_lock_list);
924
while (lock != NULL) {
925
mutex_enter(rw_lock_get_mutex(lock));
927
if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
928
|| (rw_lock_get_reader_count(lock) != 0)) {
932
mutex_exit(rw_lock_get_mutex(lock));
933
lock = UT_LIST_GET_NEXT(list, lock);
936
mutex_exit(&rw_lock_list_mutex);
940
#endif /* UNIV_SYNC_DEBUG */