#include "sync0rw.h"#include "os0thread.h"#include "mem0mem.h"#include "srv0srv.h"Include dependency graph for sync0rw.c:

Go to the source code of this file.
Functions | |
| void | rw_lock_create_func (rw_lock_t *lock, ulint level, const char *cfile_name, ulint cline, const char *cmutex_name) |
| void | rw_lock_free (rw_lock_t *lock) |
| ibool | rw_lock_validate (rw_lock_t *lock) |
| void | rw_lock_s_lock_spin (rw_lock_t *lock, ulint pass, const char *file_name, ulint line) |
| void | rw_lock_x_lock_move_ownership (rw_lock_t *lock) |
| UNIV_INLINE ulint | rw_lock_x_lock_low (rw_lock_t *lock, ulint pass, const char *file_name, ulint line) |
| void | rw_lock_x_lock_func (rw_lock_t *lock, ulint pass, const char *file_name, ulint line) |
| ibool | rw_lock_is_locked (rw_lock_t *lock, ulint lock_type) |
Variables | |
| ulint | rw_s_system_call_count = 0 |
| ulint | rw_s_spin_wait_count = 0 |
| ulint | rw_s_os_wait_count = 0 |
| ulint | rw_s_exit_count = 0 |
| ulint | rw_x_system_call_count = 0 |
| ulint | rw_x_spin_wait_count = 0 |
| ulint | rw_x_os_wait_count = 0 |
| ulint | rw_x_exit_count = 0 |
| rw_lock_list_t | rw_lock_list |
| mutex_t | rw_lock_list_mutex |
| void rw_lock_create_func | ( | rw_lock_t * | lock, | |
| ulint | level, | |||
| const char * | cfile_name, | |||
| ulint | cline, | |||
| const char * | cmutex_name | |||
| ) |
Definition at line 89 of file sync0rw.c.
References FALSE, list(), lock, mutex_create, mutex_enter, mutex_exit(), rw_lock_list, rw_lock_list_mutex, RW_LOCK_MAGIC_N, RW_LOCK_NOT_LOCKED, SYNC_NO_ORDER_CHECK, ut_a, UT_LIST_ADD_FIRST, UT_LIST_GET_FIRST, UT_LIST_GET_LEN, and UT_LIST_INIT.
00091 : pointer to memory */ 00092 ulint level, /* in: level */ 00093 const char* cfile_name, /* in: file name where created */ 00094 ulint cline, /* in: file line where created */ 00095 const char* cmutex_name) /* in: mutex name */ 00096 { 00097 /* If this is the very first time a synchronization object is 00098 created, then the following call initializes the sync system. */ 00099 00100 mutex_create(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK); 00101 00102 lock->mutex.cfile_name = cfile_name; 00103 lock->mutex.cline = cline; 00104 00105 #ifndef UNIV_HOTBACKUP 00106 lock->mutex.cmutex_name = cmutex_name; 00107 lock->mutex.mutex_type = 1; 00108 #endif /* !UNIV_HOTBACKUP */ 00109 00110 rw_lock_set_waiters(lock, 0); 00111 rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED); 00112 lock->writer_count = 0; 00113 rw_lock_set_reader_count(lock, 0); 00114 00115 lock->writer_is_wait_ex = FALSE; 00116 00117 #ifdef UNIV_SYNC_DEBUG 00118 UT_LIST_INIT(lock->debug_list); 00119 #endif /* UNIV_SYNC_DEBUG */ 00120 00121 lock->level = level; 00122 00123 lock->magic_n = RW_LOCK_MAGIC_N; 00124 00125 lock->cfile_name = cfile_name; 00126 lock->cline = cline; 00127 00128 lock->last_s_file_name = "not yet reserved"; 00129 lock->last_x_file_name = "not yet reserved"; 00130 lock->last_s_line = 0; 00131 lock->last_x_line = 0; 00132 00133 mutex_enter(&rw_lock_list_mutex); 00134 00135 if (UT_LIST_GET_LEN(rw_lock_list) > 0) { 00136 ut_a(UT_LIST_GET_FIRST(rw_lock_list)->magic_n 00137 == RW_LOCK_MAGIC_N); 00138 } 00139 00140 UT_LIST_ADD_FIRST(list, rw_lock_list, lock); 00141 00142 mutex_exit(&rw_lock_list_mutex); 00143 }
Here is the call graph for this function:

| void rw_lock_free | ( | rw_lock_t * | lock | ) |
Definition at line 151 of file sync0rw.c.
References list(), lock, mutex_enter, mutex_exit(), mutex_free(), rw_lock_get_reader_count(), rw_lock_get_waiters(), rw_lock_get_writer(), rw_lock_list, rw_lock_list_mutex, RW_LOCK_MAGIC_N, RW_LOCK_NOT_LOCKED, rw_lock_validate(), ut_a, UT_LIST_GET_NEXT, UT_LIST_GET_PREV, and UT_LIST_REMOVE.
Referenced by dict_tree_free(), and fil_space_free().
00153 : rw-lock */ 00154 { 00155 #ifdef UNIV_DEBUG 00156 ut_a(rw_lock_validate(lock)); 00157 #endif /* UNIV_DEBUG */ 00158 ut_a(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED); 00159 ut_a(rw_lock_get_waiters(lock) == 0); 00160 ut_a(rw_lock_get_reader_count(lock) == 0); 00161 00162 lock->magic_n = 0; 00163 00164 mutex_free(rw_lock_get_mutex(lock)); 00165 00166 mutex_enter(&rw_lock_list_mutex); 00167 00168 if (UT_LIST_GET_PREV(list, lock)) { 00169 ut_a(UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N); 00170 } 00171 if (UT_LIST_GET_NEXT(list, lock)) { 00172 ut_a(UT_LIST_GET_NEXT(list, lock)->magic_n == RW_LOCK_MAGIC_N); 00173 } 00174 00175 UT_LIST_REMOVE(list, rw_lock_list, lock); 00176 00177 mutex_exit(&rw_lock_list_mutex); 00178 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 719 of file sync0rw.c.
References FALSE, lock, mutex_enter, mutex_exit(), RW_LOCK_EX, RW_LOCK_SHARED, rw_lock_validate(), TRUE, ut_ad, and ut_error.
Referenced by rw_lock_x_lock_move_ownership().
00721 : TRUE if locked */ 00722 rw_lock_t* lock, /* in: rw-lock */ 00723 ulint lock_type) /* in: lock type: RW_LOCK_SHARED, 00724 RW_LOCK_EX */ 00725 { 00726 ibool ret = FALSE; 00727 00728 ut_ad(lock); 00729 ut_ad(rw_lock_validate(lock)); 00730 00731 mutex_enter(&(lock->mutex)); 00732 00733 if (lock_type == RW_LOCK_SHARED) { 00734 if (lock->reader_count > 0) { 00735 ret = TRUE; 00736 } 00737 } else if (lock_type == RW_LOCK_EX) { 00738 if (lock->writer == RW_LOCK_EX) { 00739 ret = TRUE; 00740 } 00741 } else { 00742 ut_error; 00743 } 00744 00745 mutex_exit(&(lock->mutex)); 00746 00747 return(ret); 00748 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 215 of file sync0rw.c.
References index(), lock, mutex_enter, mutex_exit(), os_thread_get_curr_id(), os_thread_pf(), os_thread_yield(), rw_lock_get_writer(), RW_LOCK_NOT_LOCKED, RW_LOCK_SHARED, rw_lock_validate(), rw_s_os_wait_count, rw_s_spin_wait_count, rw_s_system_call_count, srv_print_latch_waits, srv_spin_wait_delay, sync_array_reserve_cell(), sync_array_wait_event(), sync_primary_wait_array, SYNC_SPIN_ROUNDS, TRUE, ut_ad, ut_delay(), and ut_rnd_interval().
00217 : pointer to rw-lock */ 00218 ulint pass, /* in: pass value; != 0, if the lock 00219 will be passed to another thread to unlock */ 00220 const char* file_name, /* in: file name where lock requested */ 00221 ulint line) /* in: line where requested */ 00222 { 00223 ulint index; /* index of the reserved wait cell */ 00224 ulint i; /* spin round count */ 00225 00226 ut_ad(rw_lock_validate(lock)); 00227 00228 lock_loop: 00229 rw_s_spin_wait_count++; 00230 00231 /* Spin waiting for the writer field to become free */ 00232 i = 0; 00233 00234 while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED 00235 && i < SYNC_SPIN_ROUNDS) { 00236 if (srv_spin_wait_delay) { 00237 ut_delay(ut_rnd_interval(0, srv_spin_wait_delay)); 00238 } 00239 00240 i++; 00241 } 00242 00243 if (i == SYNC_SPIN_ROUNDS) { 00244 os_thread_yield(); 00245 } 00246 00247 if (srv_print_latch_waits) { 00248 fprintf(stderr, 00249 "Thread %lu spin wait rw-s-lock at %p cfile %s cline %lu rnds %lu\n", 00250 (ulong) os_thread_pf(os_thread_get_curr_id()), (void*) lock, 00251 lock->cfile_name, (ulong) lock->cline, (ulong) i); 00252 } 00253 00254 mutex_enter(rw_lock_get_mutex(lock)); 00255 00256 /* We try once again to obtain the lock */ 00257 00258 if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) { 00259 mutex_exit(rw_lock_get_mutex(lock)); 00260 00261 return; /* Success */ 00262 } else { 00263 /* If we get here, locking did not succeed, we may 00264 suspend the thread to wait in the wait array */ 00265 00266 rw_s_system_call_count++; 00267 00268 sync_array_reserve_cell(sync_primary_wait_array, 00269 lock, RW_LOCK_SHARED, 00270 file_name, line, 00271 &index); 00272 00273 rw_lock_set_waiters(lock, 1); 00274 00275 mutex_exit(rw_lock_get_mutex(lock)); 00276 00277 if (srv_print_latch_waits) { 00278 fprintf(stderr, 00279 "Thread %lu OS wait rw-s-lock at %p cfile %s cline %lu\n", 00280 os_thread_pf(os_thread_get_curr_id()), 00281 (void*) lock, lock->cfile_name, 00282 (ulong) lock->cline); 00283 } 00284 00285 rw_s_system_call_count++; 00286 rw_s_os_wait_count++; 00287 00288 sync_array_wait_event(sync_primary_wait_array, index); 00289 00290 goto lock_loop; 00291 } 00292 }
Here is the call graph for this function:

| ibool rw_lock_validate | ( | rw_lock_t * | lock | ) |
Definition at line 185 of file sync0rw.c.
References lock, mutex_enter, mutex_exit(), RW_LOCK_EX, rw_lock_get_reader_count(), rw_lock_get_waiters(), rw_lock_get_writer(), RW_LOCK_MAGIC_N, RW_LOCK_NOT_LOCKED, RW_LOCK_WAIT_EX, TRUE, and ut_a.
Referenced by buf_block_init(), rw_lock_free(), rw_lock_is_locked(), rw_lock_s_lock_spin(), and rw_lock_x_lock_func().
00188 { 00189 ut_a(lock); 00190 00191 mutex_enter(rw_lock_get_mutex(lock)); 00192 00193 ut_a(lock->magic_n == RW_LOCK_MAGIC_N); 00194 ut_a((rw_lock_get_reader_count(lock) == 0) 00195 || (rw_lock_get_writer(lock) != RW_LOCK_EX)); 00196 ut_a((rw_lock_get_writer(lock) == RW_LOCK_EX) 00197 || (rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX) 00198 || (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED)); 00199 ut_a((rw_lock_get_waiters(lock) == 0) 00200 || (rw_lock_get_waiters(lock) == 1)); 00201 ut_a((lock->writer != RW_LOCK_EX) || (lock->writer_count > 0)); 00202 00203 mutex_exit(rw_lock_get_mutex(lock)); 00204 00205 return(TRUE); 00206 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 432 of file sync0rw.c.
References index(), lock, mutex_enter, mutex_enter_fast, mutex_exit(), os_thread_get_curr_id(), os_thread_pf(), os_thread_yield(), RW_LOCK_EX, rw_lock_get_reader_count(), rw_lock_get_writer(), RW_LOCK_NOT_LOCKED, rw_lock_validate(), RW_LOCK_WAIT_EX, rw_lock_x_lock_low(), rw_x_os_wait_count, rw_x_spin_wait_count, rw_x_system_call_count, srv_print_latch_waits, srv_spin_wait_delay, sync_array_reserve_cell(), sync_array_wait_event(), sync_primary_wait_array, SYNC_SPIN_ROUNDS, ut_ad, ut_delay(), ut_error, and ut_rnd_interval().
00434 : pointer to rw-lock */ 00435 ulint pass, /* in: pass value; != 0, if the lock will 00436 be passed to another thread to unlock */ 00437 const char* file_name,/* in: file name where lock requested */ 00438 ulint line) /* in: line where requested */ 00439 { 00440 ulint index; /* index of the reserved wait cell */ 00441 ulint state; /* lock state acquired */ 00442 ulint i; /* spin round count */ 00443 00444 ut_ad(rw_lock_validate(lock)); 00445 00446 lock_loop: 00447 /* Acquire the mutex protecting the rw-lock fields */ 00448 mutex_enter_fast(&(lock->mutex)); 00449 00450 state = rw_lock_x_lock_low(lock, pass, file_name, line); 00451 00452 mutex_exit(&(lock->mutex)); 00453 00454 if (state == RW_LOCK_EX) { 00455 00456 return; /* Locking succeeded */ 00457 00458 } else if (state == RW_LOCK_NOT_LOCKED) { 00459 00460 /* Spin waiting for the writer field to become free */ 00461 i = 0; 00462 00463 while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED 00464 && i < SYNC_SPIN_ROUNDS) { 00465 if (srv_spin_wait_delay) { 00466 ut_delay(ut_rnd_interval(0, 00467 srv_spin_wait_delay)); 00468 } 00469 00470 i++; 00471 } 00472 if (i == SYNC_SPIN_ROUNDS) { 00473 os_thread_yield(); 00474 } 00475 } else if (state == RW_LOCK_WAIT_EX) { 00476 00477 /* Spin waiting for the reader count field to become zero */ 00478 i = 0; 00479 00480 while (rw_lock_get_reader_count(lock) != 0 00481 && i < SYNC_SPIN_ROUNDS) { 00482 if (srv_spin_wait_delay) { 00483 ut_delay(ut_rnd_interval(0, 00484 srv_spin_wait_delay)); 00485 } 00486 00487 i++; 00488 } 00489 if (i == SYNC_SPIN_ROUNDS) { 00490 os_thread_yield(); 00491 } 00492 } else { 00493 i = 0; /* Eliminate a compiler warning */ 00494 ut_error; 00495 } 00496 00497 if (srv_print_latch_waits) { 00498 fprintf(stderr, 00499 "Thread %lu spin wait rw-x-lock at %p cfile %s cline %lu rnds %lu\n", 00500 os_thread_pf(os_thread_get_curr_id()), (void*) lock, 00501 lock->cfile_name, (ulong) lock->cline, (ulong) i); 00502 } 00503 00504 rw_x_spin_wait_count++; 00505 00506 /* We try once again to obtain the lock. Acquire the mutex protecting 00507 the rw-lock fields */ 00508 00509 mutex_enter(rw_lock_get_mutex(lock)); 00510 00511 state = rw_lock_x_lock_low(lock, pass, file_name, line); 00512 00513 if (state == RW_LOCK_EX) { 00514 mutex_exit(rw_lock_get_mutex(lock)); 00515 00516 return; /* Locking succeeded */ 00517 } 00518 00519 rw_x_system_call_count++; 00520 00521 sync_array_reserve_cell(sync_primary_wait_array, 00522 lock, RW_LOCK_EX, 00523 file_name, line, 00524 &index); 00525 00526 rw_lock_set_waiters(lock, 1); 00527 00528 mutex_exit(rw_lock_get_mutex(lock)); 00529 00530 if (srv_print_latch_waits) { 00531 fprintf(stderr, 00532 "Thread %lu OS wait for rw-x-lock at %p cfile %s cline %lu\n", 00533 os_thread_pf(os_thread_get_curr_id()), (void*) lock, 00534 lock->cfile_name, (ulong) lock->cline); 00535 } 00536 00537 rw_x_system_call_count++; 00538 rw_x_os_wait_count++; 00539 00540 sync_array_wait_event(sync_primary_wait_array, index); 00541 00542 goto lock_loop; 00543 }
Here is the call graph for this function:

| UNIV_INLINE ulint rw_lock_x_lock_low | ( | rw_lock_t * | lock, | |
| ulint | pass, | |||
| const char * | file_name, | |||
| ulint | line | |||
| ) |
Definition at line 324 of file sync0rw.c.
References FALSE, lock, os_thread_eq(), os_thread_get_curr_id(), RW_LOCK_EX, rw_lock_get_reader_count(), rw_lock_get_writer(), RW_LOCK_NOT_LOCKED, RW_LOCK_WAIT_EX, TRUE, and ut_ad.
Referenced by rw_lock_x_lock_func().
00326 : RW_LOCK_NOT_LOCKED if did 00327 not succeed, RW_LOCK_EX if success, 00328 RW_LOCK_WAIT_EX, if got wait reservation */ 00329 rw_lock_t* lock, /* in: pointer to rw-lock */ 00330 ulint pass, /* in: pass value; != 0, if the lock will 00331 be passed to another thread to unlock */ 00332 const char* file_name,/* in: file name where lock requested */ 00333 ulint line) /* in: line where requested */ 00334 { 00335 #ifdef UNIV_SYNC_DEBUG 00336 ut_ad(mutex_own(rw_lock_get_mutex(lock))); 00337 #endif /* UNIV_SYNC_DEBUG */ 00338 if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) { 00339 00340 if (rw_lock_get_reader_count(lock) == 0) { 00341 00342 rw_lock_set_writer(lock, RW_LOCK_EX); 00343 lock->writer_thread = os_thread_get_curr_id(); 00344 lock->writer_count++; 00345 lock->pass = pass; 00346 00347 #ifdef UNIV_SYNC_DEBUG 00348 rw_lock_add_debug_info(lock, pass, RW_LOCK_EX, 00349 file_name, line); 00350 #endif 00351 lock->last_x_file_name = file_name; 00352 lock->last_x_line = line; 00353 00354 /* Locking succeeded, we may return */ 00355 return(RW_LOCK_EX); 00356 } else { 00357 /* There are readers, we have to wait */ 00358 rw_lock_set_writer(lock, RW_LOCK_WAIT_EX); 00359 lock->writer_thread = os_thread_get_curr_id(); 00360 lock->pass = pass; 00361 lock->writer_is_wait_ex = TRUE; 00362 00363 #ifdef UNIV_SYNC_DEBUG 00364 rw_lock_add_debug_info(lock, pass, RW_LOCK_WAIT_EX, 00365 file_name, line); 00366 #endif 00367 00368 return(RW_LOCK_WAIT_EX); 00369 } 00370 00371 } else if ((rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX) 00372 && os_thread_eq(lock->writer_thread, 00373 os_thread_get_curr_id())) { 00374 00375 if (rw_lock_get_reader_count(lock) == 0) { 00376 00377 rw_lock_set_writer(lock, RW_LOCK_EX); 00378 lock->writer_count++; 00379 lock->pass = pass; 00380 lock->writer_is_wait_ex = FALSE; 00381 00382 #ifdef UNIV_SYNC_DEBUG 00383 rw_lock_remove_debug_info(lock, pass, RW_LOCK_WAIT_EX); 00384 rw_lock_add_debug_info(lock, pass, RW_LOCK_EX, 00385 file_name, line); 00386 #endif 00387 00388 lock->last_x_file_name = file_name; 00389 lock->last_x_line = line; 00390 00391 /* Locking succeeded, we may return */ 00392 return(RW_LOCK_EX); 00393 } 00394 00395 return(RW_LOCK_WAIT_EX); 00396 00397 } else if ((rw_lock_get_writer(lock) == RW_LOCK_EX) 00398 && os_thread_eq(lock->writer_thread, 00399 os_thread_get_curr_id()) 00400 && (lock->pass == 0) 00401 && (pass == 0)) { 00402 00403 lock->writer_count++; 00404 00405 #ifdef UNIV_SYNC_DEBUG 00406 rw_lock_add_debug_info(lock, pass, RW_LOCK_EX, file_name, 00407 line); 00408 #endif 00409 00410 lock->last_x_file_name = file_name; 00411 lock->last_x_line = line; 00412 00413 /* Locking succeeded, we may return */ 00414 return(RW_LOCK_EX); 00415 } 00416 00417 /* Locking did not succeed */ 00418 return(RW_LOCK_NOT_LOCKED); 00419 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void rw_lock_x_lock_move_ownership | ( | rw_lock_t * | lock | ) |
Definition at line 304 of file sync0rw.c.
References lock, mutex_enter, mutex_exit(), os_thread_get_curr_id(), RW_LOCK_EX, rw_lock_is_locked(), and ut_ad.
Referenced by ibuf_merge_or_delete_for_page(), and recv_recover_page().
00306 : lock which was x-locked in the 00307 buffer read */ 00308 { 00309 ut_ad(rw_lock_is_locked(lock, RW_LOCK_EX)); 00310 00311 mutex_enter(&(lock->mutex)); 00312 00313 lock->writer_thread = os_thread_get_curr_id(); 00314 00315 lock->pass = 0; 00316 00317 mutex_exit(&(lock->mutex)); 00318 }
Here is the call graph for this function:

Here is the caller graph for this function:

| rw_lock_list_t rw_lock_list |
Definition at line 31 of file sync0rw.c.
Referenced by rw_lock_create_func(), rw_lock_free(), and sync_init().
Definition at line 32 of file sync0rw.c.
Referenced by rw_lock_create_func(), rw_lock_free(), sync_init(), sync_thread_add_level(), and sync_thread_reset_level().
| ulint rw_s_exit_count = 0 |
Definition at line 20 of file sync0rw.c.
Referenced by rw_lock_s_lock_spin(), and sync_print_wait_info().
Definition at line 19 of file sync0rw.c.
Referenced by rw_lock_s_lock_spin(), and sync_print_wait_info().
| ulint rw_x_exit_count = 0 |
Definition at line 26 of file sync0rw.c.
Referenced by rw_lock_x_lock_func(), and sync_print_wait_info().
Definition at line 25 of file sync0rw.c.
Referenced by rw_lock_x_lock_func(), and sync_print_wait_info().
1.4.7

