sync0rw.ic
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:13k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /******************************************************
  2. The read-write lock (for threads)
  3. (c) 1995 Innobase Oy
  4. Created 9/11/1995 Heikki Tuuri
  5. *******************************************************/
  6. /**********************************************************************
  7. Lock an rw-lock in shared mode for the current thread. If the rw-lock is
  8. locked in exclusive mode, or there is an exclusive lock request waiting,
  9. the function spins a preset time (controlled by SYNC_SPIN_ROUNDS),
  10. waiting for the lock before suspending the thread. */
  11. void
  12. rw_lock_s_lock_spin(
  13. /*================*/
  14.         rw_lock_t*    lock,   /* in: pointer to rw-lock */
  15. ulint pass, /* in: pass value; != 0, if the lock will
  16. be passed to another thread to unlock */
  17. const char* file_name,/* in: file name where lock requested */
  18. ulint line); /* in: line where requested */
  19. #ifdef UNIV_SYNC_DEBUG
  20. /**********************************************************************
  21. Inserts the debug information for an rw-lock. */
  22. void
  23. rw_lock_add_debug_info(
  24. /*===================*/
  25. rw_lock_t* lock, /* in: rw-lock */
  26. ulint pass, /* in: pass value */
  27. ulint lock_type, /* in: lock type */
  28. const char* file_name, /* in: file where requested */
  29. ulint line); /* in: line where requested */
  30. /**********************************************************************
  31. Removes a debug information struct for an rw-lock. */
  32. void
  33. rw_lock_remove_debug_info(
  34. /*======================*/
  35. rw_lock_t* lock, /* in: rw-lock */
  36. ulint pass, /* in: pass value */
  37. ulint lock_type); /* in: lock type */
  38. #endif /* UNIV_SYNC_DEBUG */
  39. /************************************************************************
  40. Accessor functions for rw lock. */
  41. UNIV_INLINE
  42. ulint
  43. rw_lock_get_waiters(
  44. /*================*/
  45. rw_lock_t* lock)
  46. {
  47. return(lock->waiters);
  48. }
  49. UNIV_INLINE
  50. void
  51. rw_lock_set_waiters(
  52. /*================*/
  53. rw_lock_t* lock,
  54. ulint flag)
  55. {
  56. lock->waiters = flag;
  57. }
  58. UNIV_INLINE
  59. ulint
  60. rw_lock_get_writer(
  61. /*===============*/
  62. rw_lock_t* lock)
  63. {
  64. return(lock->writer);
  65. }
  66. UNIV_INLINE
  67. void
  68. rw_lock_set_writer(
  69. /*===============*/
  70. rw_lock_t* lock,
  71. ulint flag)
  72. {
  73. lock->writer = flag;
  74. }
  75. UNIV_INLINE
  76. ulint
  77. rw_lock_get_reader_count(
  78. /*=====================*/
  79. rw_lock_t* lock)
  80. {
  81. return(lock->reader_count);
  82. }
  83. UNIV_INLINE
  84. void
  85. rw_lock_set_reader_count(
  86. /*=====================*/
  87. rw_lock_t* lock,
  88. ulint count)
  89. {
  90. lock->reader_count = count;
  91. }
  92. UNIV_INLINE
  93. mutex_t*
  94. rw_lock_get_mutex(
  95. /*==============*/
  96. rw_lock_t* lock)
  97. {
  98. return(&(lock->mutex));
  99. }
  100. /**********************************************************************
  101. Returns the value of writer_count for the lock. Does not reserve the lock
  102. mutex, so the caller must be sure it is not changed during the call. */
  103. UNIV_INLINE
  104. ulint
  105. rw_lock_get_x_lock_count(
  106. /*=====================*/
  107. /* out: value of writer_count */
  108. rw_lock_t* lock) /* in: rw-lock */
  109. {
  110. return(lock->writer_count);
  111. }
  112. /**********************************************************************
  113. Low-level function which tries to lock an rw-lock in s-mode. Performs no
  114. spinning. */
  115. UNIV_INLINE
  116. ibool
  117. rw_lock_s_lock_low(
  118. /*===============*/
  119. /* out: TRUE if success */
  120.         rw_lock_t*    lock,   /* in: pointer to rw-lock */
  121. ulint pass __attribute__((unused)),
  122.                                 /* in: pass value; != 0, if the lock will be
  123. passed to another thread to unlock */
  124. const char* file_name, /* in: file name where lock requested */
  125. ulint line) /* in: line where requested */
  126. {
  127. #ifdef UNIV_SYNC_DEBUG
  128. ut_ad(mutex_own(rw_lock_get_mutex(lock)));
  129. #endif /* UNIV_SYNC_DEBUG */
  130. /* Check if the writer field is free */
  131. if (lock->writer == RW_LOCK_NOT_LOCKED) {
  132. /* Set the shared lock by incrementing the reader count */
  133. lock->reader_count++;
  134. #ifdef UNIV_SYNC_DEBUG
  135. rw_lock_add_debug_info(lock, pass, RW_LOCK_SHARED, file_name,
  136. line);
  137. #endif
  138. lock->last_s_file_name = file_name;
  139. lock->last_s_line = line;
  140. return(TRUE); /* locking succeeded */
  141. }
  142. return(FALSE); /* locking did not succeed */
  143. }
  144. /**********************************************************************
  145. Low-level function which locks an rw-lock in s-mode when we know that it
  146. is possible and none else is currently accessing the rw-lock structure.
  147. Then we can do the locking without reserving the mutex. */
  148. UNIV_INLINE
  149. void
  150. rw_lock_s_lock_direct(
  151. /*==================*/
  152. rw_lock_t* lock, /* in: pointer to rw-lock */
  153. const char* file_name, /* in: file name where requested */
  154. ulint line) /* in: line where lock requested */
  155. {
  156. ut_ad(lock->writer == RW_LOCK_NOT_LOCKED);
  157. ut_ad(rw_lock_get_reader_count(lock) == 0);
  158. /* Set the shared lock by incrementing the reader count */
  159. lock->reader_count++;
  160. lock->last_s_file_name = file_name;
  161. lock->last_s_line = line;
  162. #ifdef UNIV_SYNC_DEBUG
  163. rw_lock_add_debug_info(lock, 0, RW_LOCK_SHARED, file_name, line);
  164. #endif
  165. }
  166. /**********************************************************************
  167. Low-level function which locks an rw-lock in x-mode when we know that it
  168. is not locked and none else is currently accessing the rw-lock structure.
  169. Then we can do the locking without reserving the mutex. */
  170. UNIV_INLINE
  171. void
  172. rw_lock_x_lock_direct(
  173. /*==================*/
  174. rw_lock_t* lock, /* in: pointer to rw-lock */
  175. const char* file_name, /* in: file name where requested */
  176. ulint line) /* in: line where lock requested */
  177. {
  178.         ut_ad(rw_lock_validate(lock));
  179. ut_ad(rw_lock_get_reader_count(lock) == 0);
  180. ut_ad(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED);
  181. rw_lock_set_writer(lock, RW_LOCK_EX);
  182. lock->writer_thread = os_thread_get_curr_id();
  183. lock->writer_count++;
  184. lock->pass = 0;
  185. lock->last_x_file_name = file_name;
  186. lock->last_x_line = line;
  187. #ifdef UNIV_SYNC_DEBUG
  188. rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line);
  189. #endif
  190. }
  191. /**********************************************************************
  192. NOTE! Use the corresponding macro, not directly this function! Lock an
  193. rw-lock in shared mode for the current thread. If the rw-lock is locked
  194. in exclusive mode, or there is an exclusive lock request waiting, the
  195. function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting for
  196. the lock, before suspending the thread. */
  197. UNIV_INLINE
  198. void
  199. rw_lock_s_lock_func(
  200. /*================*/
  201.         rw_lock_t*    lock,   /* in: pointer to rw-lock */
  202. ulint pass, /* in: pass value; != 0, if the lock will
  203. be passed to another thread to unlock */
  204. const char* file_name,/* in: file name where lock requested */
  205. ulint line) /* in: line where requested */
  206. {
  207. /* NOTE: As we do not know the thread ids for threads which have
  208. s-locked a latch, and s-lockers will be served only after waiting
  209. x-lock requests have been fulfilled, then if this thread already
  210. owns an s-lock here, it may end up in a deadlock with another thread
  211. which requests an x-lock here. Therefore, we will forbid recursive
  212. s-locking of a latch: the following assert will warn the programmer
  213. of the possibility of a tjis kind of deadlock. If we want to implement
  214. safe recursive s-locking, we should keep in a list the thread ids of
  215. the threads which have s-locked a latch. This would use some CPU
  216. time. */
  217. #ifdef UNIV_SYNC_DEBUG
  218. ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */
  219. #endif /* UNIV_SYNC_DEBUG */
  220. mutex_enter(rw_lock_get_mutex(lock));
  221. if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) {
  222. mutex_exit(rw_lock_get_mutex(lock));
  223. return; /* Success */
  224. } else {
  225. /* Did not succeed, try spin wait */
  226. mutex_exit(rw_lock_get_mutex(lock));
  227. rw_lock_s_lock_spin(lock, pass, file_name, line);
  228. return;
  229. }
  230. }
  231. /**********************************************************************
  232. NOTE! Use the corresponding macro, not directly this function! Lock an
  233. rw-lock in shared mode for the current thread if the lock can be acquired
  234. immediately. */
  235. UNIV_INLINE
  236. ibool
  237. rw_lock_s_lock_func_nowait(
  238. /*=======================*/
  239. /* out: TRUE if success */
  240.         rw_lock_t*    lock,   /* in: pointer to rw-lock */
  241. const char* file_name,/* in: file name where lock requested */
  242. ulint line) /* in: line where requested */
  243. {
  244. ibool success = FALSE;
  245. mutex_enter(rw_lock_get_mutex(lock));
  246. if (lock->writer == RW_LOCK_NOT_LOCKED) {
  247. /* Set the shared lock by incrementing the reader count */
  248. lock->reader_count++;
  249. #ifdef UNIV_SYNC_DEBUG
  250. rw_lock_add_debug_info(lock, 0, RW_LOCK_SHARED, file_name,
  251. line);
  252. #endif
  253. lock->last_s_file_name = file_name;
  254. lock->last_s_line = line;
  255. success = TRUE;
  256. }
  257. mutex_exit(rw_lock_get_mutex(lock));
  258. return(success);
  259. }
  260. /**********************************************************************
  261. NOTE! Use the corresponding macro, not directly this function! Lock an
  262. rw-lock in exclusive mode for the current thread if the lock can be
  263. obtained immediately. */
  264. UNIV_INLINE
  265. ibool
  266. rw_lock_x_lock_func_nowait(
  267. /*=======================*/
  268. /* out: TRUE if success */
  269.         rw_lock_t*    lock,   /* in: pointer to rw-lock */
  270. const char* file_name,/* in: file name where lock requested */
  271. ulint line) /* in: line where requested */
  272. {
  273. ibool success = FALSE;
  274. mutex_enter(rw_lock_get_mutex(lock));
  275. if ((rw_lock_get_reader_count(lock) == 0)
  276.      && ((rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED)
  277.        || ((rw_lock_get_writer(lock) == RW_LOCK_EX)
  278.            && (lock->pass == 0)
  279.            && os_thread_eq(lock->writer_thread,
  280. os_thread_get_curr_id())))) {
  281. rw_lock_set_writer(lock, RW_LOCK_EX);
  282. lock->writer_thread = os_thread_get_curr_id();
  283. lock->writer_count++;
  284. lock->pass = 0;
  285. #ifdef UNIV_SYNC_DEBUG
  286. rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line);
  287. #endif
  288. lock->last_x_file_name = file_name;
  289. lock->last_x_line = line;
  290. success = TRUE;
  291. }
  292. mutex_exit(rw_lock_get_mutex(lock));
  293.         ut_ad(rw_lock_validate(lock));
  294. return(success);
  295. }
  296. /**********************************************************************
  297. Releases a shared mode lock. */
  298. UNIV_INLINE
  299. void
  300. rw_lock_s_unlock_func(
  301. /*==================*/
  302. rw_lock_t* lock /* in: rw-lock */
  303. #ifdef UNIV_SYNC_DEBUG
  304. ,ulint pass /* in: pass value; != 0, if the lock may have
  305. been passed to another thread to unlock */
  306. #endif
  307. )
  308. {
  309. mutex_t* mutex = &(lock->mutex);
  310. ibool sg  = FALSE;
  311.         /* Acquire the mutex protecting the rw-lock fields */
  312. mutex_enter(mutex);
  313. /* Reset the shared lock by decrementing the reader count */
  314. ut_a(lock->reader_count > 0);
  315. lock->reader_count--;
  316. #ifdef UNIV_SYNC_DEBUG
  317. rw_lock_remove_debug_info(lock, pass, RW_LOCK_SHARED);
  318. #endif
  319. /* If there may be waiters and this was the last s-lock,
  320. signal the object */
  321. if (lock->waiters && (lock->reader_count == 0)) {
  322.         sg = TRUE;
  323. rw_lock_set_waiters(lock, 0);
  324. }
  325. mutex_exit(mutex);
  326. if (sg == TRUE) {
  327. sync_array_signal_object(sync_primary_wait_array, lock);
  328. }
  329.         ut_ad(rw_lock_validate(lock));
  330. #ifdef UNIV_SYNC_PERF_STAT
  331. rw_s_exit_count++;
  332. #endif
  333. }
  334. /**********************************************************************
  335. Releases a shared mode lock when we know there are no waiters and none
  336. else will access the lock during the time this function is executed. */
  337. UNIV_INLINE
  338. void
  339. rw_lock_s_unlock_direct(
  340. /*====================*/
  341. rw_lock_t* lock) /* in: rw-lock */
  342. {
  343. /* Reset the shared lock by decrementing the reader count */
  344. ut_ad(lock->reader_count > 0);
  345. lock->reader_count--;
  346. #ifdef UNIV_SYNC_DEBUG
  347. rw_lock_remove_debug_info(lock, 0, RW_LOCK_SHARED);
  348. #endif
  349. ut_ad(!lock->waiters);
  350.         ut_ad(rw_lock_validate(lock));
  351. #ifdef UNIV_SYNC_PERF_STAT
  352. rw_s_exit_count++;
  353. #endif
  354. }
  355. /**********************************************************************
  356. Releases an exclusive mode lock. */
  357. UNIV_INLINE
  358. void
  359. rw_lock_x_unlock_func(
  360. /*==================*/
  361. rw_lock_t* lock /* in: rw-lock */
  362. #ifdef UNIV_SYNC_DEBUG
  363. ,ulint pass /* in: pass value; != 0, if the lock may have
  364. been passed to another thread to unlock */
  365. #endif
  366. )
  367. {
  368. ibool sg  = FALSE;
  369.         /* Acquire the mutex protecting the rw-lock fields */
  370. mutex_enter(&(lock->mutex));
  371. /* Reset the exclusive lock if this thread no longer has an x-mode
  372. lock */
  373. ut_ad(lock->writer_count > 0);
  374. lock->writer_count--;
  375. if (lock->writer_count == 0) {
  376. rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
  377. }
  378. #ifdef UNIV_SYNC_DEBUG
  379. rw_lock_remove_debug_info(lock, pass, RW_LOCK_EX);
  380. #endif
  381. /* If there may be waiters, signal the lock */
  382. if (lock->waiters && (lock->writer_count == 0)) {
  383.         sg = TRUE;
  384. rw_lock_set_waiters(lock, 0);
  385. }
  386. mutex_exit(&(lock->mutex));
  387. if (sg == TRUE) {
  388. sync_array_signal_object(sync_primary_wait_array, lock);
  389. }
  390.         ut_ad(rw_lock_validate(lock));
  391. #ifdef UNIV_SYNC_PERF_STAT
  392. rw_x_exit_count++;
  393. #endif
  394. }
  395. /**********************************************************************
  396. Releases an exclusive mode lock when we know there are no waiters, and
  397. none else will access the lock durint the time this function is executed. */
  398. UNIV_INLINE
  399. void
  400. rw_lock_x_unlock_direct(
  401. /*====================*/
  402. rw_lock_t* lock) /* in: rw-lock */
  403. {
  404. /* Reset the exclusive lock if this thread no longer has an x-mode
  405. lock */
  406. ut_ad(lock->writer_count > 0);
  407. lock->writer_count--;
  408. if (lock->writer_count == 0) {
  409. rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
  410. }
  411. #ifdef UNIV_SYNC_DEBUG
  412. rw_lock_remove_debug_info(lock, 0, RW_LOCK_EX);
  413. #endif
  414. ut_ad(!lock->waiters);
  415.         ut_ad(rw_lock_validate(lock));
  416. #ifdef UNIV_SYNC_PERF_STAT
  417. rw_x_exit_count++;
  418. #endif
  419. }