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
ulint rw_s_system_call_count = 0;
21
/* number of spin waits on rw-latches,
22
resulted during shared (read) locks */
23
ulint rw_s_spin_wait_count = 0;
25
/* number of OS waits on rw-latches,
26
resulted during shared (read) locks */
27
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
ulint rw_s_exit_count = 0;
33
/* number of system calls made during exclusive latching */
34
ulint rw_x_system_call_count = 0;
36
/* number of spin waits on rw-latches,
37
resulted during exclusive (write) locks */
38
ulint rw_x_spin_wait_count = 0;
40
/* number of OS waits on rw-latches,
41
resulted during exclusive (write) locks */
42
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
ulint rw_x_exit_count = 0;
48
/* The global list of rw-locks */
49
rw_lock_list_t rw_lock_list;
50
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
mutex_t rw_lock_debug_mutex;
58
os_event_t rw_lock_debug_event; /* If deadlock detection does not
59
get immediately the mutex, it may
60
wait for this event */
61
ibool rw_lock_debug_waiters; /* This is set to TRUE, if there may
62
be waiters for the event */
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;
155
mutex_enter(&rw_lock_list_mutex);
157
if (UT_LIST_GET_LEN(rw_lock_list) > 0) {
158
ut_a(UT_LIST_GET_FIRST(rw_lock_list)->magic_n
162
UT_LIST_ADD_FIRST(list, rw_lock_list, lock);
164
mutex_exit(&rw_lock_list_mutex);
167
/**********************************************************************
168
Calling this function is obligatory only if the memory buffer containing
169
the rw-lock is freed. Removes an rw-lock object from the global list. The
170
rw-lock is checked to be in the non-locked state. */
175
rw_lock_t* lock) /* in: rw-lock */
177
ut_ad(rw_lock_validate(lock));
178
ut_a(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED);
179
ut_a(rw_lock_get_waiters(lock) == 0);
180
ut_a(rw_lock_get_reader_count(lock) == 0);
184
mutex_free(rw_lock_get_mutex(lock));
186
mutex_enter(&rw_lock_list_mutex);
188
if (UT_LIST_GET_PREV(list, lock)) {
189
ut_a(UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N);
191
if (UT_LIST_GET_NEXT(list, lock)) {
192
ut_a(UT_LIST_GET_NEXT(list, lock)->magic_n == RW_LOCK_MAGIC_N);
195
UT_LIST_REMOVE(list, rw_lock_list, lock);
197
mutex_exit(&rw_lock_list_mutex);
201
/**********************************************************************
202
Checks that the rw-lock has been initialized and that there are no
203
simultaneous shared and exclusive locks. */
212
mutex_enter(rw_lock_get_mutex(lock));
214
ut_a(lock->magic_n == RW_LOCK_MAGIC_N);
215
ut_a((rw_lock_get_reader_count(lock) == 0)
216
|| (rw_lock_get_writer(lock) != RW_LOCK_EX));
217
ut_a((rw_lock_get_writer(lock) == RW_LOCK_EX)
218
|| (rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX)
219
|| (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED));
220
ut_a((rw_lock_get_waiters(lock) == 0)
221
|| (rw_lock_get_waiters(lock) == 1));
222
ut_a((lock->writer != RW_LOCK_EX) || (lock->writer_count > 0));
224
mutex_exit(rw_lock_get_mutex(lock));
228
#endif /* UNIV_DEBUG */
230
/**********************************************************************
231
Lock an rw-lock in shared mode for the current thread. If the rw-lock is
232
locked in exclusive mode, or there is an exclusive lock request waiting,
233
the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting
234
for the lock, before suspending the thread. */
239
rw_lock_t* lock, /* in: pointer to rw-lock */
240
ulint pass, /* in: pass value; != 0, if the lock
241
will be passed to another thread to unlock */
242
const char* file_name, /* in: file name where lock requested */
243
ulint line) /* in: line where requested */
245
ulint index; /* index of the reserved wait cell */
246
ulint i; /* spin round count */
248
ut_ad(rw_lock_validate(lock));
251
rw_s_spin_wait_count++;
253
/* Spin waiting for the writer field to become free */
256
while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED
257
&& i < SYNC_SPIN_ROUNDS) {
258
if (srv_spin_wait_delay) {
259
ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
265
if (i == SYNC_SPIN_ROUNDS) {
269
if (srv_print_latch_waits) {
271
"Thread %lu spin wait rw-s-lock at %p"
272
" cfile %s cline %lu rnds %lu\n",
273
(ulong) os_thread_pf(os_thread_get_curr_id()),
275
lock->cfile_name, (ulong) lock->cline, (ulong) i);
278
mutex_enter(rw_lock_get_mutex(lock));
280
/* We try once again to obtain the lock */
282
if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) {
283
mutex_exit(rw_lock_get_mutex(lock));
285
return; /* Success */
287
/* If we get here, locking did not succeed, we may
288
suspend the thread to wait in the wait array */
290
rw_s_system_call_count++;
292
sync_array_reserve_cell(sync_primary_wait_array,
293
lock, RW_LOCK_SHARED,
297
rw_lock_set_waiters(lock, 1);
299
mutex_exit(rw_lock_get_mutex(lock));
301
if (srv_print_latch_waits) {
303
"Thread %lu OS wait rw-s-lock at %p"
304
" cfile %s cline %lu\n",
305
os_thread_pf(os_thread_get_curr_id()),
306
(void*) lock, lock->cfile_name,
307
(ulong) lock->cline);
310
rw_s_system_call_count++;
311
rw_s_os_wait_count++;
313
sync_array_wait_event(sync_primary_wait_array, index);
319
/**********************************************************************
320
This function is used in the insert buffer to move the ownership of an
321
x-latch on a buffer frame to the current thread. The x-latch was set by
322
the buffer read operation and it protected the buffer frame while the
323
read was done. The ownership is moved because we want that the current
324
thread is able to acquire a second x-latch which is stored in an mtr.
325
This, in turn, is needed to pass the debug checks of index page
329
rw_lock_x_lock_move_ownership(
330
/*==========================*/
331
rw_lock_t* lock) /* in: lock which was x-locked in the
334
ut_ad(rw_lock_is_locked(lock, RW_LOCK_EX));
336
mutex_enter(&(lock->mutex));
338
lock->writer_thread = os_thread_get_curr_id();
342
mutex_exit(&(lock->mutex));
345
/**********************************************************************
346
Low-level function for acquiring an exclusive lock. */
351
/* out: RW_LOCK_NOT_LOCKED if did
352
not succeed, RW_LOCK_EX if success,
353
RW_LOCK_WAIT_EX, if got wait reservation */
354
rw_lock_t* lock, /* in: pointer to rw-lock */
355
ulint pass, /* in: pass value; != 0, if the lock will
356
be passed to another thread to unlock */
357
const char* file_name,/* in: file name where lock requested */
358
ulint line) /* in: line where requested */
360
ut_ad(mutex_own(rw_lock_get_mutex(lock)));
362
if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
364
if (rw_lock_get_reader_count(lock) == 0) {
366
rw_lock_set_writer(lock, RW_LOCK_EX);
367
lock->writer_thread = os_thread_get_curr_id();
368
lock->writer_count++;
371
#ifdef UNIV_SYNC_DEBUG
372
rw_lock_add_debug_info(lock, pass, RW_LOCK_EX,
375
lock->last_x_file_name = file_name;
376
lock->last_x_line = (unsigned int) line;
378
/* Locking succeeded, we may return */
381
/* There are readers, we have to wait */
382
rw_lock_set_writer(lock, RW_LOCK_WAIT_EX);
383
lock->writer_thread = os_thread_get_curr_id();
385
lock->writer_is_wait_ex = TRUE;
387
#ifdef UNIV_SYNC_DEBUG
388
rw_lock_add_debug_info(lock, pass, RW_LOCK_WAIT_EX,
392
return(RW_LOCK_WAIT_EX);
395
} else if ((rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX)
396
&& os_thread_eq(lock->writer_thread,
397
os_thread_get_curr_id())) {
399
if (rw_lock_get_reader_count(lock) == 0) {
401
rw_lock_set_writer(lock, RW_LOCK_EX);
402
lock->writer_count++;
404
lock->writer_is_wait_ex = FALSE;
406
#ifdef UNIV_SYNC_DEBUG
407
rw_lock_remove_debug_info(lock, pass, RW_LOCK_WAIT_EX);
408
rw_lock_add_debug_info(lock, pass, RW_LOCK_EX,
412
lock->last_x_file_name = file_name;
413
lock->last_x_line = (unsigned int) line;
415
/* Locking succeeded, we may return */
419
return(RW_LOCK_WAIT_EX);
421
} else if ((rw_lock_get_writer(lock) == RW_LOCK_EX)
422
&& os_thread_eq(lock->writer_thread,
423
os_thread_get_curr_id())
427
lock->writer_count++;
429
#ifdef UNIV_SYNC_DEBUG
430
rw_lock_add_debug_info(lock, pass, RW_LOCK_EX, file_name,
434
lock->last_x_file_name = file_name;
435
lock->last_x_line = (unsigned int) line;
437
/* Locking succeeded, we may return */
441
/* Locking did not succeed */
442
return(RW_LOCK_NOT_LOCKED);
445
/**********************************************************************
446
NOTE! Use the corresponding macro, not directly this function! Lock an
447
rw-lock in exclusive mode for the current thread. If the rw-lock is locked
448
in shared or exclusive mode, or there is an exclusive lock request waiting,
449
the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting
450
for the lock before suspending the thread. If the same thread has an x-lock
451
on the rw-lock, locking succeed, with the following exception: if pass != 0,
452
only a single x-lock may be taken on the lock. NOTE: If the same thread has
453
an s-lock, locking does not succeed! */
458
rw_lock_t* lock, /* in: pointer to rw-lock */
459
ulint pass, /* in: pass value; != 0, if the lock will
460
be passed to another thread to unlock */
461
const char* file_name,/* in: file name where lock requested */
462
ulint line) /* in: line where requested */
464
ulint index; /* index of the reserved wait cell */
465
ulint state; /* lock state acquired */
466
ulint i; /* spin round count */
468
ut_ad(rw_lock_validate(lock));
471
/* Acquire the mutex protecting the rw-lock fields */
472
mutex_enter_fast(&(lock->mutex));
474
state = rw_lock_x_lock_low(lock, pass, file_name, line);
476
mutex_exit(&(lock->mutex));
478
if (state == RW_LOCK_EX) {
480
return; /* Locking succeeded */
482
} else if (state == RW_LOCK_NOT_LOCKED) {
484
/* Spin waiting for the writer field to become free */
487
while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED
488
&& i < SYNC_SPIN_ROUNDS) {
489
if (srv_spin_wait_delay) {
490
ut_delay(ut_rnd_interval(0,
491
srv_spin_wait_delay));
496
if (i == SYNC_SPIN_ROUNDS) {
499
} else if (state == RW_LOCK_WAIT_EX) {
501
/* Spin waiting for the reader count field to become zero */
504
while (rw_lock_get_reader_count(lock) != 0
505
&& i < SYNC_SPIN_ROUNDS) {
506
if (srv_spin_wait_delay) {
507
ut_delay(ut_rnd_interval(0,
508
srv_spin_wait_delay));
513
if (i == SYNC_SPIN_ROUNDS) {
517
i = 0; /* Eliminate a compiler warning */
521
if (srv_print_latch_waits) {
523
"Thread %lu spin wait rw-x-lock at %p"
524
" cfile %s cline %lu rnds %lu\n",
525
os_thread_pf(os_thread_get_curr_id()), (void*) lock,
526
lock->cfile_name, (ulong) lock->cline, (ulong) i);
529
rw_x_spin_wait_count++;
531
/* We try once again to obtain the lock. Acquire the mutex protecting
532
the rw-lock fields */
534
mutex_enter(rw_lock_get_mutex(lock));
536
state = rw_lock_x_lock_low(lock, pass, file_name, line);
538
if (state == RW_LOCK_EX) {
539
mutex_exit(rw_lock_get_mutex(lock));
541
return; /* Locking succeeded */
544
rw_x_system_call_count++;
546
sync_array_reserve_cell(sync_primary_wait_array,
551
rw_lock_set_waiters(lock, 1);
553
mutex_exit(rw_lock_get_mutex(lock));
555
if (srv_print_latch_waits) {
557
"Thread %lu OS wait for rw-x-lock at %p"
558
" cfile %s cline %lu\n",
559
os_thread_pf(os_thread_get_curr_id()), (void*) lock,
560
lock->cfile_name, (ulong) lock->cline);
563
rw_x_system_call_count++;
564
rw_x_os_wait_count++;
566
sync_array_wait_event(sync_primary_wait_array, index);
571
#ifdef UNIV_SYNC_DEBUG
572
/**********************************************************************
573
Acquires the debug mutex. We cannot use the mutex defined in sync0sync,
574
because the debug mutex is also acquired in sync0arr while holding the OS
575
mutex protecting the sync array, and the ordinary mutex_enter might
576
recursively call routines in sync0arr, leading to a deadlock on the OS
580
rw_lock_debug_mutex_enter(void)
581
/*==========================*/
584
if (0 == mutex_enter_nowait(&rw_lock_debug_mutex)) {
588
os_event_reset(rw_lock_debug_event);
590
rw_lock_debug_waiters = TRUE;
592
if (0 == mutex_enter_nowait(&rw_lock_debug_mutex)) {
596
os_event_wait(rw_lock_debug_event);
601
/**********************************************************************
602
Releases the debug mutex. */
605
rw_lock_debug_mutex_exit(void)
606
/*==========================*/
608
mutex_exit(&rw_lock_debug_mutex);
610
if (rw_lock_debug_waiters) {
611
rw_lock_debug_waiters = FALSE;
612
os_event_set(rw_lock_debug_event);
616
/**********************************************************************
617
Inserts the debug information for an rw-lock. */
620
rw_lock_add_debug_info(
621
/*===================*/
622
rw_lock_t* lock, /* in: rw-lock */
623
ulint pass, /* in: pass value */
624
ulint lock_type, /* in: lock type */
625
const char* file_name, /* in: file where requested */
626
ulint line) /* in: line where requested */
628
rw_lock_debug_t* info;
633
info = rw_lock_debug_create();
635
rw_lock_debug_mutex_enter();
637
info->file_name = file_name;
639
info->lock_type = lock_type;
640
info->thread_id = os_thread_get_curr_id();
643
UT_LIST_ADD_FIRST(list, lock->debug_list, info);
645
rw_lock_debug_mutex_exit();
647
if ((pass == 0) && (lock_type != RW_LOCK_WAIT_EX)) {
648
sync_thread_add_level(lock, lock->level);
652
/**********************************************************************
653
Removes a debug information struct for an rw-lock. */
656
rw_lock_remove_debug_info(
657
/*======================*/
658
rw_lock_t* lock, /* in: rw-lock */
659
ulint pass, /* in: pass value */
660
ulint lock_type) /* in: lock type */
662
rw_lock_debug_t* info;
666
if ((pass == 0) && (lock_type != RW_LOCK_WAIT_EX)) {
667
sync_thread_reset_level(lock);
670
rw_lock_debug_mutex_enter();
672
info = UT_LIST_GET_FIRST(lock->debug_list);
674
while (info != NULL) {
675
if ((pass == info->pass)
677
|| os_thread_eq(info->thread_id,
678
os_thread_get_curr_id()))
679
&& (info->lock_type == lock_type)) {
682
UT_LIST_REMOVE(list, lock->debug_list, info);
683
rw_lock_debug_mutex_exit();
685
rw_lock_debug_free(info);
690
info = UT_LIST_GET_NEXT(list, info);
695
#endif /* UNIV_SYNC_DEBUG */
697
#ifdef UNIV_SYNC_DEBUG
698
/**********************************************************************
699
Checks if the thread has locked the rw-lock in the specified mode, with
700
the pass value == 0. */
705
/* out: TRUE if locked */
706
rw_lock_t* lock, /* in: rw-lock */
707
ulint lock_type) /* in: lock type: RW_LOCK_SHARED,
710
rw_lock_debug_t* info;
713
ut_ad(rw_lock_validate(lock));
715
mutex_enter(&(lock->mutex));
717
info = UT_LIST_GET_FIRST(lock->debug_list);
719
while (info != NULL) {
721
if (os_thread_eq(info->thread_id, os_thread_get_curr_id())
723
&& (info->lock_type == lock_type)) {
725
mutex_exit(&(lock->mutex));
731
info = UT_LIST_GET_NEXT(list, info);
733
mutex_exit(&(lock->mutex));
737
#endif /* UNIV_SYNC_DEBUG */
739
/**********************************************************************
740
Checks if somebody has locked the rw-lock in the specified mode. */
745
/* out: TRUE if locked */
746
rw_lock_t* lock, /* in: rw-lock */
747
ulint lock_type) /* in: lock type: RW_LOCK_SHARED,
753
ut_ad(rw_lock_validate(lock));
755
mutex_enter(&(lock->mutex));
757
if (lock_type == RW_LOCK_SHARED) {
758
if (lock->reader_count > 0) {
761
} else if (lock_type == RW_LOCK_EX) {
762
if (lock->writer == RW_LOCK_EX) {
769
mutex_exit(&(lock->mutex));
774
#ifdef UNIV_SYNC_DEBUG
775
/*******************************************************************
776
Prints debug info of currently locked rw-locks. */
779
rw_lock_list_print_info(
780
/*====================*/
781
FILE* file) /* in: file where to print */
785
rw_lock_debug_t* info;
787
mutex_enter(&rw_lock_list_mutex);
789
fputs("-------------\n"
791
"-------------\n", file);
793
lock = UT_LIST_GET_FIRST(rw_lock_list);
795
while (lock != NULL) {
799
mutex_enter(&(lock->mutex));
801
if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
802
|| (rw_lock_get_reader_count(lock) != 0)
803
|| (rw_lock_get_waiters(lock) != 0)) {
805
fprintf(file, "RW-LOCK: %p ", (void*) lock);
807
if (rw_lock_get_waiters(lock)) {
808
fputs(" Waiters for the lock exist\n", file);
813
info = UT_LIST_GET_FIRST(lock->debug_list);
814
while (info != NULL) {
815
rw_lock_debug_print(info);
816
info = UT_LIST_GET_NEXT(list, info);
820
mutex_exit(&(lock->mutex));
821
lock = UT_LIST_GET_NEXT(list, lock);
824
fprintf(file, "Total number of rw-locks %ld\n", count);
825
mutex_exit(&rw_lock_list_mutex);
828
/*******************************************************************
829
Prints debug info of an rw-lock. */
834
rw_lock_t* lock) /* in: rw-lock */
836
rw_lock_debug_t* info;
841
"RW-LATCH: %p ", (void*) lock);
843
if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
844
|| (rw_lock_get_reader_count(lock) != 0)
845
|| (rw_lock_get_waiters(lock) != 0)) {
847
if (rw_lock_get_waiters(lock)) {
848
fputs(" Waiters for the lock exist\n", stderr);
853
info = UT_LIST_GET_FIRST(lock->debug_list);
854
while (info != NULL) {
855
rw_lock_debug_print(info);
856
info = UT_LIST_GET_NEXT(list, info);
861
/*************************************************************************
862
Prints info of a debug struct. */
867
rw_lock_debug_t* info) /* in: debug struct */
871
rwt = info->lock_type;
873
fprintf(stderr, "Locked: thread %ld file %s line %ld ",
874
(ulong) os_thread_pf(info->thread_id), info->file_name,
876
if (rwt == RW_LOCK_SHARED) {
877
fputs("S-LOCK", stderr);
878
} else if (rwt == RW_LOCK_EX) {
879
fputs("X-LOCK", stderr);
880
} else if (rwt == RW_LOCK_WAIT_EX) {
881
fputs("WAIT X-LOCK", stderr);
885
if (info->pass != 0) {
886
fprintf(stderr, " pass value %lu", (ulong) info->pass);
891
/*******************************************************************
892
Returns the number of currently locked rw-locks. Works only in the debug
896
rw_lock_n_locked(void)
897
/*==================*/
902
mutex_enter(&rw_lock_list_mutex);
904
lock = UT_LIST_GET_FIRST(rw_lock_list);
906
while (lock != NULL) {
907
mutex_enter(rw_lock_get_mutex(lock));
909
if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
910
|| (rw_lock_get_reader_count(lock) != 0)) {
914
mutex_exit(rw_lock_get_mutex(lock));
915
lock = UT_LIST_GET_NEXT(list, lock);
918
mutex_exit(&rw_lock_list_mutex);
922
#endif /* UNIV_SYNC_DEBUG */