sync0rw.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:22k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /******************************************************
  2. The read-write lock (for thread synchronization)
  3. (c) 1995 Innobase Oy
  4. Created 9/11/1995 Heikki Tuuri
  5. *******************************************************/
  6. #include "sync0rw.h"
  7. #ifdef UNIV_NONINL
  8. #include "sync0rw.ic"
  9. #endif
  10. #include "os0thread.h"
  11. #include "mem0mem.h"
  12. #include "srv0srv.h"
  13. ulint rw_s_system_call_count = 0;
  14. ulint rw_s_spin_wait_count = 0;
  15. ulint rw_s_exit_count = 0;
  16. ulint rw_x_system_call_count = 0;
  17. ulint rw_x_spin_wait_count = 0;
  18. ulint rw_x_exit_count = 0;
  19. /* The global list of rw-locks */
  20. rw_lock_list_t rw_lock_list;
  21. mutex_t rw_lock_list_mutex;
  22. /* The global mutex which protects debug info lists of all rw-locks.
  23. To modify the debug info list of an rw-lock, this mutex has to be
  24. acquired in addition to the mutex protecting the lock. */
  25. mutex_t rw_lock_debug_mutex;
  26. os_event_t rw_lock_debug_event; /* If deadlock detection does not
  27. get immediately the mutex, it may
  28. wait for this event */
  29. ibool rw_lock_debug_waiters; /* This is set to TRUE, if there may
  30. be waiters for the event */
  31. /**********************************************************************
  32. Creates a debug info struct. */
  33. static
  34. rw_lock_debug_t*
  35. rw_lock_debug_create(void);
  36. /*======================*/
  37. /**********************************************************************
  38. Frees a debug info struct. */
  39. static
  40. void
  41. rw_lock_debug_free(
  42. /*===============*/
  43. rw_lock_debug_t* info);
  44. /**********************************************************************
  45. Creates a debug info struct. */
  46. static
  47. rw_lock_debug_t*
  48. rw_lock_debug_create(void)
  49. /*======================*/
  50. {
  51. return((rw_lock_debug_t*) mem_alloc(sizeof(rw_lock_debug_t)));
  52. }
  53. /**********************************************************************
  54. Frees a debug info struct. */
  55. static
  56. void
  57. rw_lock_debug_free(
  58. /*===============*/
  59. rw_lock_debug_t* info)
  60. {
  61. mem_free(info);
  62. }
  63. /**********************************************************************
  64. Creates, or rather, initializes an rw-lock object in a specified memory
  65. location (which must be appropriately aligned). The rw-lock is initialized
  66. to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free
  67. is necessary only if the memory block containing it is freed. */
  68. void
  69. rw_lock_create_func(
  70. /*================*/
  71. rw_lock_t* lock, /* in: pointer to memory */
  72. char* cfile_name, /* in: file name where created */
  73. ulint cline) /* in: file line where created */
  74. {
  75. /* If this is the very first time a synchronization
  76. object is created, then the following call initializes
  77. the sync system. */
  78. mutex_create(rw_lock_get_mutex(lock));
  79. mutex_set_level(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK);
  80. ut_memcpy(&(lock->mutex.cfile_name), cfile_name,
  81. ut_min(RW_CNAME_LEN - 1, ut_strlen(cfile_name)));
  82. lock->mutex.cline = cline;
  83. rw_lock_set_waiters(lock, 0);
  84. rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
  85. lock->writer_count = 0;
  86. rw_lock_set_reader_count(lock, 0);
  87. lock->writer_is_wait_ex = FALSE;
  88. UT_LIST_INIT(lock->debug_list);
  89. lock->magic_n = RW_LOCK_MAGIC_N;
  90. lock->level = SYNC_LEVEL_NONE;
  91. ut_memcpy(&(lock->cfile_name), cfile_name,
  92. ut_min(RW_CNAME_LEN - 1, ut_strlen(cfile_name)));
  93. lock->cfile_name[RW_CNAME_LEN - 1] = '';
  94. lock->cline = cline;
  95. mutex_enter(&rw_lock_list_mutex);
  96. UT_LIST_ADD_FIRST(list, rw_lock_list, lock);
  97. mutex_exit(&rw_lock_list_mutex);
  98. }
  99. /**********************************************************************
  100. Calling this function is obligatory only if the memory buffer containing
  101. the rw-lock is freed. Removes an rw-lock object from the global list. The
  102. rw-lock is checked to be in the non-locked state. */
  103. void
  104. rw_lock_free(
  105. /*=========*/
  106. rw_lock_t* lock) /* in: rw-lock */
  107. {
  108. ut_ad(rw_lock_validate(lock));
  109. ut_a(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED);
  110. ut_a(rw_lock_get_waiters(lock) == 0);
  111. ut_a(rw_lock_get_reader_count(lock) == 0);
  112. lock->magic_n = 0;
  113. mutex_free(rw_lock_get_mutex(lock));
  114. mutex_enter(&rw_lock_list_mutex);
  115. UT_LIST_REMOVE(list, rw_lock_list, lock);
  116. mutex_exit(&rw_lock_list_mutex);
  117. }
  118. /**********************************************************************
  119. Checks that the rw-lock has been initialized and that there are no
  120. simultaneous shared and exclusive locks. */
  121. ibool
  122. rw_lock_validate(
  123. /*=============*/
  124. rw_lock_t* lock)
  125. {
  126. ut_a(lock);
  127. mutex_enter(rw_lock_get_mutex(lock));
  128. ut_a(lock->magic_n == RW_LOCK_MAGIC_N);
  129. ut_a((rw_lock_get_reader_count(lock) == 0)
  130.      || (rw_lock_get_writer(lock) != RW_LOCK_EX));
  131. ut_a((rw_lock_get_writer(lock) == RW_LOCK_EX)
  132.      || (rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX)
  133.      || (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED));
  134. ut_a((rw_lock_get_waiters(lock) == 0)
  135.      || (rw_lock_get_waiters(lock) == 1));
  136. ut_a((lock->writer != RW_LOCK_EX) || (lock->writer_count > 0));
  137.      
  138. mutex_exit(rw_lock_get_mutex(lock));
  139. return(TRUE);
  140. }
  141. /**********************************************************************
  142. Lock an rw-lock in shared mode for the current thread. If the rw-lock is
  143. locked in exclusive mode, or there is an exclusive lock request waiting,
  144. the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting
  145. for the lock, before suspending the thread. */
  146. void
  147. rw_lock_s_lock_spin(
  148. /*================*/
  149.         rw_lock_t*    lock   /* in: pointer to rw-lock */
  150. #ifdef UNIV_SYNC_DEBUG
  151. ,ulint pass, /* in: pass value; != 0, if the lock
  152. will be passed to another thread to unlock */
  153. char* file_name, /* in: file name where lock requested */
  154. ulint line /* in: line where requested */
  155. #endif
  156. )
  157. {
  158.         ulint    index; /* index of the reserved wait cell */
  159.         ulint    i;    /* spin round count */
  160.         
  161.         ut_ad(rw_lock_validate(lock));
  162. lock_loop:
  163. rw_s_spin_wait_count++;
  164.   /* Spin waiting for the writer field to become free */
  165.         i = 0;
  166.         while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED
  167. && i < SYNC_SPIN_ROUNDS) {
  168.          if (srv_spin_wait_delay) {
  169.          ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
  170.          }
  171.          i++;
  172.         }
  173. if (i == SYNC_SPIN_ROUNDS) {
  174. os_thread_yield();
  175. }
  176. if (srv_print_latch_waits) {
  177. printf(
  178. "Thread %lu spin wait rw-s-lock at %lx cfile %s cline %lu rnds %lun",
  179. os_thread_get_curr_id(), (ulint)lock,
  180. &(lock->cfile_name), lock->cline, i);
  181. }
  182. mutex_enter(rw_lock_get_mutex(lock));
  183.         /* We try once again to obtain the lock */
  184. if (TRUE == rw_lock_s_lock_low(lock
  185. #ifdef UNIV_SYNC_DEBUG
  186. , pass, file_name,
  187. line
  188. #endif
  189.    )) {
  190. mutex_exit(rw_lock_get_mutex(lock));
  191. return; /* Success */
  192. } else {
  193. /* If we get here, locking did not succeed, we may
  194. suspend the thread to wait in the wait array */
  195. rw_s_system_call_count++;
  196.          sync_array_reserve_cell(sync_primary_wait_array,
  197. lock, RW_LOCK_SHARED,
  198. #ifdef UNIV_SYNC_DEBUG
  199. file_name, line,
  200. #endif
  201. &index);
  202. rw_lock_set_waiters(lock, 1);
  203. mutex_exit(rw_lock_get_mutex(lock));
  204. if (srv_print_latch_waits) {
  205. printf(
  206. "Thread %lu OS wait rw-s-lock at %lx cfile %s cline %lun",
  207. os_thread_get_curr_id(), (ulint)lock,
  208. &(lock->cfile_name), lock->cline);
  209. }
  210. rw_s_system_call_count++;
  211.          sync_array_wait_event(sync_primary_wait_array, index);
  212.          goto lock_loop;
  213. }        
  214. }
  215. /**********************************************************************
  216. This function is used in the insert buffer to move the ownership of an
  217. x-latch on a buffer frame to the current thread. The x-latch was set by
  218. the buffer read operation and it protected the buffer frame while the
  219. read was done. The ownership is moved because we want that the current
  220. thread is able to acquire a second x-latch which is stored in an mtr.
  221. This, in turn, is needed to pass the debug checks of index page
  222. operations. */
  223. void
  224. rw_lock_x_lock_move_ownership(
  225. /*==========================*/
  226. rw_lock_t* lock) /* in: lock which was x-locked in the
  227. buffer read */
  228. {
  229. ut_ad(rw_lock_is_locked(lock, RW_LOCK_EX));
  230. mutex_enter(&(lock->mutex));
  231. lock->writer_thread = os_thread_get_curr_id();
  232. lock->pass = 0;
  233. mutex_exit(&(lock->mutex));
  234. }
  235. /**********************************************************************
  236. Low-level function for acquiring an exclusive lock. */
  237. UNIV_INLINE
  238. ulint
  239. rw_lock_x_lock_low(
  240. /*===============*/
  241. /* out: RW_LOCK_NOT_LOCKED if did
  242. not succeed, RW_LOCK_EX if success,
  243. RW_LOCK_WAIT_EX, if got wait reservation */
  244.         rw_lock_t*    lock,   /* in: pointer to rw-lock */
  245. ulint pass /* in: pass value; != 0, if the lock will
  246. be passed to another thread to unlock */
  247. #ifdef UNIV_SYNC_DEBUG
  248. ,char* file_name, /* in: file name where lock requested */
  249. ulint line /* in: line where requested */
  250. #endif
  251. )
  252. {
  253. ut_ad(mutex_own(rw_lock_get_mutex(lock)));
  254. if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
  255. if (rw_lock_get_reader_count(lock) == 0) {
  256. rw_lock_set_writer(lock, RW_LOCK_EX);
  257. lock->writer_thread = os_thread_get_curr_id();
  258. lock->writer_count++;
  259. lock->pass = pass;
  260. #ifdef UNIV_SYNC_DEBUG
  261. rw_lock_add_debug_info(lock, pass, RW_LOCK_EX,
  262. file_name, line);
  263. #endif
  264. /* Locking succeeded, we may return */
  265. return(RW_LOCK_EX);
  266. } else {
  267. /* There are readers, we have to wait */
  268. rw_lock_set_writer(lock, RW_LOCK_WAIT_EX);
  269. lock->writer_thread = os_thread_get_curr_id();
  270. lock->pass = pass;
  271. lock->writer_is_wait_ex = TRUE;
  272. #ifdef UNIV_SYNC_DEBUG
  273. rw_lock_add_debug_info(lock, pass, RW_LOCK_WAIT_EX,
  274. file_name, line);
  275. #endif
  276. return(RW_LOCK_WAIT_EX);
  277. }
  278. } else if ((rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX)
  279.    && (lock->writer_thread == os_thread_get_curr_id())) {
  280. if (rw_lock_get_reader_count(lock) == 0) {
  281. rw_lock_set_writer(lock, RW_LOCK_EX);
  282. lock->writer_count++;
  283. lock->pass = pass;
  284. lock->writer_is_wait_ex = FALSE;
  285. #ifdef UNIV_SYNC_DEBUG
  286. rw_lock_remove_debug_info(lock, pass, RW_LOCK_WAIT_EX);
  287. rw_lock_add_debug_info(lock, pass, RW_LOCK_EX,
  288. file_name, line);
  289. #endif
  290. /* Locking succeeded, we may return */
  291. return(RW_LOCK_EX);
  292. }
  293. return(RW_LOCK_WAIT_EX);
  294. } else if ((rw_lock_get_writer(lock) == RW_LOCK_EX)
  295.    && (lock->writer_thread == os_thread_get_curr_id())
  296.    && (lock->pass == 0)
  297.    && (pass == 0)) {
  298. lock->writer_count++;
  299. #ifdef UNIV_SYNC_DEBUG
  300. rw_lock_add_debug_info(lock, pass, RW_LOCK_EX, file_name,
  301. line);
  302. #endif
  303. /* Locking succeeded, we may return */
  304. return(RW_LOCK_EX);
  305. }
  306. /* Locking did not succeed */
  307. return(RW_LOCK_NOT_LOCKED);
  308. }
  309. /**********************************************************************
  310. NOTE! Use the corresponding macro, not directly this function! Lock an
  311. rw-lock in exclusive mode for the current thread. If the rw-lock is locked
  312. in shared or exclusive mode, or there is an exclusive lock request waiting,
  313. the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting
  314. for the lock before suspending the thread. If the same thread has an x-lock
  315. on the rw-lock, locking succeed, with the following exception: if pass != 0,
  316. only a single x-lock may be taken on the lock. NOTE: If the same thread has
  317. an s-lock, locking does not succeed! */
  318. void
  319. rw_lock_x_lock_func(
  320. /*================*/
  321.         rw_lock_t*    lock,   /* in: pointer to rw-lock */
  322. ulint pass /* in: pass value; != 0, if the lock will
  323. be passed to another thread to unlock */
  324. #ifdef UNIV_SYNC_DEBUG
  325. ,char* file_name, /* in: file name where lock requested */
  326. ulint line /* in: line where requested */
  327. #endif
  328. )
  329. {
  330.         ulint index;  /* index of the reserved wait cell */
  331.         ulint state; /* lock state acquired */
  332.         ulint i; /* spin round count */
  333.         
  334.         ut_ad(rw_lock_validate(lock));
  335. lock_loop:
  336.         /* Acquire the mutex protecting the rw-lock fields */
  337. mutex_enter_fast(&(lock->mutex));
  338. state = rw_lock_x_lock_low(lock, pass
  339. #ifdef UNIV_SYNC_DEBUG
  340. ,file_name, line
  341. #endif
  342.        );
  343. mutex_exit(&(lock->mutex));
  344.         
  345. if (state == RW_LOCK_EX) {
  346. return; /* Locking succeeded */
  347. } else if (state == RW_LOCK_NOT_LOCKED) {
  348.   /* Spin waiting for the writer field to become free */
  349. i = 0;
  350.          while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED 
  351.                 && i < SYNC_SPIN_ROUNDS) {
  352.          if (srv_spin_wait_delay) {
  353. ut_delay(ut_rnd_interval(0,
  354. srv_spin_wait_delay));
  355.          }
  356.         
  357.          i++;
  358.          }
  359. if (i == SYNC_SPIN_ROUNDS) {
  360. os_thread_yield();
  361. }
  362.         } else if (state == RW_LOCK_WAIT_EX) {
  363.   /* Spin waiting for the reader count field to become zero */
  364. i = 0;
  365.          while (rw_lock_get_reader_count(lock) != 0 
  366.                 && i < SYNC_SPIN_ROUNDS) {
  367.          if (srv_spin_wait_delay) {
  368. ut_delay(ut_rnd_interval(0,
  369. srv_spin_wait_delay));
  370.          }
  371. i++;
  372.          }
  373. if (i == SYNC_SPIN_ROUNDS) {
  374. os_thread_yield();
  375. }
  376.         } else {
  377. ut_error;
  378. }
  379. if (srv_print_latch_waits) {
  380. printf(
  381. "Thread %lu spin wait rw-x-lock at %lx cfile %s cline %lu rnds %lun",
  382. os_thread_get_curr_id(), (ulint)lock,
  383. &(lock->cfile_name), lock->cline, i);
  384. }
  385. rw_x_spin_wait_count++;
  386.         /* We try once again to obtain the lock. Acquire the mutex protecting
  387. the rw-lock fields */
  388. mutex_enter(rw_lock_get_mutex(lock));
  389. state = rw_lock_x_lock_low(lock, pass
  390. #ifdef UNIV_SYNC_DEBUG
  391. ,file_name, line
  392. #endif
  393.        );
  394. if (state == RW_LOCK_EX) {
  395. mutex_exit(rw_lock_get_mutex(lock));
  396. return; /* Locking succeeded */
  397. }
  398. rw_x_system_call_count++;
  399.         sync_array_reserve_cell(sync_primary_wait_array,
  400. lock, RW_LOCK_EX,
  401. #ifdef UNIV_SYNC_DEBUG
  402. file_name, line,
  403. #endif
  404. &index);
  405. rw_lock_set_waiters(lock, 1);
  406. mutex_exit(rw_lock_get_mutex(lock));
  407. if (srv_print_latch_waits) {
  408. printf(
  409. "Thread %lu OS wait for rw-x-lock at %lx cfile %s cline %lun",
  410. os_thread_get_curr_id(), (ulint)lock, &(lock->cfile_name),
  411. lock->cline);
  412. }
  413. rw_x_system_call_count++;
  414.         sync_array_wait_event(sync_primary_wait_array, index);
  415.         goto lock_loop;
  416. }
  417. /**********************************************************************
  418. Acquires the debug mutex. We cannot use the mutex defined in sync0sync,
  419. because the debug mutex is also acquired in sync0arr while holding the OS
  420. mutex protecting the sync array, and the ordinary mutex_enter might
  421. recursively call routines in sync0arr, leading to a deadlock on the OS
  422. mutex. */
  423. void
  424. rw_lock_debug_mutex_enter(void)
  425. /*==========================*/
  426. {
  427. loop:
  428. if (0 == mutex_enter_nowait(&rw_lock_debug_mutex)) {
  429. return;
  430. }
  431. os_event_reset(rw_lock_debug_event);
  432. rw_lock_debug_waiters = TRUE;
  433. if (0 == mutex_enter_nowait(&rw_lock_debug_mutex)) {
  434. return;
  435. }
  436. os_event_wait(rw_lock_debug_event);
  437. goto loop;
  438. }
  439. /**********************************************************************
  440. Releases the debug mutex. */
  441. void
  442. rw_lock_debug_mutex_exit(void)
  443. /*==========================*/
  444. {
  445. mutex_exit(&rw_lock_debug_mutex);
  446. if (rw_lock_debug_waiters) {
  447. rw_lock_debug_waiters = FALSE;
  448. os_event_set(rw_lock_debug_event);
  449. }
  450. }
  451. /**********************************************************************
  452. Inserts the debug information for an rw-lock. */
  453. void
  454. rw_lock_add_debug_info(
  455. /*===================*/
  456. rw_lock_t* lock, /* in: rw-lock */
  457. ulint pass, /* in: pass value */
  458. ulint lock_type, /* in: lock type */
  459. char* file_name, /* in: file where requested */
  460. ulint line) /* in: line where requested */
  461. {
  462. rw_lock_debug_t* info;
  463. ut_ad(lock);
  464. ut_ad(file_name);
  465. info = rw_lock_debug_create();
  466. rw_lock_debug_mutex_enter();
  467. info->file_name = file_name;
  468. info->line  = line;
  469. info->lock_type = lock_type;
  470. info->thread_id = os_thread_get_curr_id();
  471. info->pass = pass;
  472. UT_LIST_ADD_FIRST(list, lock->debug_list, info);
  473. rw_lock_debug_mutex_exit();
  474. if ((pass == 0) && (lock_type != RW_LOCK_WAIT_EX)) {
  475. sync_thread_add_level(lock, lock->level);
  476. }
  477. }
  478. /**********************************************************************
  479. Removes a debug information struct for an rw-lock. */
  480. void
  481. rw_lock_remove_debug_info(
  482. /*======================*/
  483. rw_lock_t* lock, /* in: rw-lock */
  484. ulint pass, /* in: pass value */
  485. ulint lock_type) /* in: lock type */
  486. {
  487. rw_lock_debug_t* info;
  488. ut_ad(lock);
  489. if ((pass == 0) && (lock_type != RW_LOCK_WAIT_EX)) {
  490. sync_thread_reset_level(lock);
  491. }
  492. rw_lock_debug_mutex_enter();
  493. info = UT_LIST_GET_FIRST(lock->debug_list);
  494. while (info != NULL) {
  495. if ((pass == info->pass)
  496.     && ((pass != 0)
  497. || (info->thread_id == os_thread_get_curr_id()))
  498.     && (info->lock_type == lock_type)) {
  499.      /* Found! */
  500.      UT_LIST_REMOVE(list, lock->debug_list, info);
  501. rw_lock_debug_mutex_exit();
  502.      rw_lock_debug_free(info);
  503.      return;
  504. }
  505. info = UT_LIST_GET_NEXT(list, info);
  506. }
  507. ut_error;
  508. }
  509. /**********************************************************************
  510. Sets the rw-lock latching level field. */
  511. void
  512. rw_lock_set_level(
  513. /*==============*/
  514. rw_lock_t* lock, /* in: rw-lock */
  515. ulint level) /* in: level */
  516. {
  517. lock->level = level;
  518. }
  519. /**********************************************************************
  520. Checks if the thread has locked the rw-lock in the specified mode, with
  521. the pass value == 0. */
  522. ibool
  523. rw_lock_own(
  524. /*========*/
  525. /* out: TRUE if locked */
  526. rw_lock_t* lock, /* in: rw-lock */
  527. ulint lock_type) /* in: lock type */
  528. {
  529. rw_lock_debug_t* info;
  530. ut_ad(lock);
  531. ut_ad(rw_lock_validate(lock));
  532. #ifndef UNIV_SYNC_DEBUG
  533. ut_error;
  534. #endif
  535. mutex_enter(&(lock->mutex));
  536. info = UT_LIST_GET_FIRST(lock->debug_list);
  537. while (info != NULL) {
  538. if ((info->thread_id == os_thread_get_curr_id())
  539.     && (info->pass == 0)
  540.     && (info->lock_type == lock_type)) {
  541. mutex_exit(&(lock->mutex));
  542.      /* Found! */
  543.      return(TRUE);
  544. }
  545. info = UT_LIST_GET_NEXT(list, info);
  546. }
  547. mutex_exit(&(lock->mutex));
  548. return(FALSE);
  549. }
  550. /**********************************************************************
  551. Checks if somebody has locked the rw-lock in the specified mode. */
  552. ibool
  553. rw_lock_is_locked(
  554. /*==============*/
  555. /* out: TRUE if locked */
  556. rw_lock_t* lock, /* in: rw-lock */
  557. ulint lock_type) /* in: lock type: RW_LOCK_SHARED,
  558. RW_LOCK_EX */
  559. {
  560. ibool ret = FALSE;
  561. ut_ad(lock);
  562. ut_ad(rw_lock_validate(lock));
  563. mutex_enter(&(lock->mutex));
  564. if (lock_type == RW_LOCK_SHARED) {
  565. if (lock->reader_count > 0) {
  566. ret = TRUE;
  567. }
  568. } else if (lock_type == RW_LOCK_EX) {
  569. if (lock->writer == RW_LOCK_EX) {
  570. ret = TRUE;
  571. }
  572. } else {
  573. ut_error;
  574. }
  575. mutex_exit(&(lock->mutex));
  576. return(ret);
  577. }
  578. /*******************************************************************
  579. Prints debug info of currently locked rw-locks. */
  580. void
  581. rw_lock_list_print_info(void)
  582. /*=========================*/
  583. {
  584. #ifndef UNIV_SYNC_DEBUG
  585. printf(
  586.    "Sorry, cannot give rw-lock list info in non-debug version!n");
  587. #else
  588. rw_lock_t* lock;
  589. ulint count = 0;
  590. rw_lock_debug_t* info;
  591. mutex_enter(&rw_lock_list_mutex);
  592. printf("----------------------------------------------n");
  593. printf("RW-LOCK INFOn");
  594. lock = UT_LIST_GET_FIRST(rw_lock_list);
  595. while (lock != NULL) {
  596. count++;
  597. mutex_enter(&(lock->mutex));
  598. if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
  599.     || (rw_lock_get_reader_count(lock) != 0)
  600.     || (rw_lock_get_waiters(lock) != 0)) {
  601. printf("RW-LOCK: %lx ", (ulint)lock);
  602. if (rw_lock_get_waiters(lock)) {
  603. printf(" Waiters for the lock existn");
  604. } else {
  605. printf("n");
  606. }
  607.     
  608. info = UT_LIST_GET_FIRST(lock->debug_list);
  609. while (info != NULL) {
  610. rw_lock_debug_print(info);
  611. info = UT_LIST_GET_NEXT(list, info);
  612. }
  613. }
  614. mutex_exit(&(lock->mutex));
  615. lock = UT_LIST_GET_NEXT(list, lock);
  616. }
  617. printf("Total number of rw-locks %ldn", count);
  618. mutex_exit(&rw_lock_list_mutex);
  619. #endif
  620. }
  621. /*******************************************************************
  622. Prints debug info of an rw-lock. */
  623. void
  624. rw_lock_print(
  625. /*==========*/
  626. rw_lock_t* lock) /* in: rw-lock */
  627. {
  628. #ifndef UNIV_SYNC_DEBUG
  629. printf(
  630.    "Sorry, cannot give rw-lock info in non-debug version!n");
  631. #else
  632. ulint count = 0;
  633. rw_lock_debug_t* info;
  634. printf("----------------------------------------------n");
  635. printf("RW-LOCK INFOn");
  636. printf("RW-LOCK: %lx ", (ulint)lock);
  637. mutex_enter(&(lock->mutex));
  638. if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
  639.     || (rw_lock_get_reader_count(lock) != 0)
  640.     || (rw_lock_get_waiters(lock) != 0)) {
  641. if (rw_lock_get_waiters(lock)) {
  642. printf(" Waiters for the lock existn");
  643. } else {
  644. printf("n");
  645. }
  646.     
  647. info = UT_LIST_GET_FIRST(lock->debug_list);
  648. while (info != NULL) {
  649. rw_lock_debug_print(info);
  650. info = UT_LIST_GET_NEXT(list, info);
  651. }
  652. }
  653. mutex_exit(&(lock->mutex));
  654. #endif
  655. }
  656. /*************************************************************************
  657. Prints info of a debug struct. */
  658. void
  659. rw_lock_debug_print(
  660. /*================*/
  661. rw_lock_debug_t* info) /* in: debug struct */
  662. {
  663. ulint rwt;
  664. rwt    = info->lock_type;
  665. printf("Locked: thread %ld file %s line %ld  ",
  666.      info->thread_id, info->file_name, info->line);
  667. if (rwt == RW_LOCK_SHARED) {
  668. printf("S-LOCK");
  669. } else if (rwt == RW_LOCK_EX) {
  670. printf("X-LOCK");
  671. } else if (rwt == RW_LOCK_WAIT_EX) {
  672. printf("WAIT X-LOCK");
  673. } else {
  674. ut_error;
  675. }
  676. if (info->pass != 0) {
  677. printf(" pass value %lu", info->pass);
  678. }
  679. printf("n");
  680. }
  681. /*******************************************************************
  682. Returns the number of currently locked rw-locks. Works only in the debug
  683. version. */
  684. ulint
  685. rw_lock_n_locked(void)
  686. /*==================*/
  687. {
  688. #ifndef UNIV_SYNC_DEBUG
  689. printf(
  690.    "Sorry, cannot give rw-lock info in non-debug version!n");
  691. ut_error;
  692. return(0);
  693. #else
  694. rw_lock_t* lock;
  695. ulint count = 0;
  696. mutex_enter(&rw_lock_list_mutex);
  697. lock = UT_LIST_GET_FIRST(rw_lock_list);
  698. while (lock != NULL) {
  699. mutex_enter(rw_lock_get_mutex(lock));
  700. if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
  701. || (rw_lock_get_reader_count(lock) != 0)) {
  702. count++;
  703. }
  704. mutex_exit(rw_lock_get_mutex(lock));
  705. lock = UT_LIST_GET_NEXT(list, lock);
  706. }
  707. mutex_exit(&rw_lock_list_mutex);
  708. return(count);
  709. #endif
  710. }