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

MySQL数据库

开发平台:

Visual C++

  1. /******************************************************
  2. The read-write lock (for threads, not for database transactions)
  3. (c) 1995 Innobase Oy
  4. Created 9/11/1995 Heikki Tuuri
  5. *******************************************************/
  6. #ifndef sync0rw_h
  7. #define sync0rw_h
  8. #include "univ.i"
  9. #include "ut0lst.h"
  10. #include "sync0sync.h"
  11. #include "os0sync.h"
  12. /* The following undef is to prevent a name conflict with a macro
  13. in MySQL: */
  14. #undef rw_lock_t
  15. /* Latch types; these are used also in btr0btr.h: keep the numerical values
  16. smaller than 30 and the order of the numerical values like below! */
  17. #define RW_S_LATCH 1
  18. #define RW_X_LATCH 2
  19. #define RW_NO_LATCH 3
  20. typedef struct rw_lock_struct rw_lock_t;
  21. typedef struct rw_lock_debug_struct rw_lock_debug_t;
  22. typedef UT_LIST_BASE_NODE_T(rw_lock_t) rw_lock_list_t;
  23. extern rw_lock_list_t  rw_lock_list;
  24. extern mutex_t rw_lock_list_mutex;
  25. /* The global mutex which protects debug info lists of all rw-locks.
  26. To modify the debug info list of an rw-lock, this mutex has to be
  27. acquired in addition to the mutex protecting the lock. */
  28. extern mutex_t rw_lock_debug_mutex;
  29. extern os_event_t rw_lock_debug_event; /* If deadlock detection does
  30. not get immediately the mutex it
  31. may wait for this event */
  32. extern ibool rw_lock_debug_waiters; /* This is set to TRUE, if
  33. there may be waiters for the event */
  34. extern ulint rw_s_system_call_count;
  35. extern ulint rw_s_spin_wait_count;
  36. extern ulint rw_s_exit_count;
  37. extern ulint rw_x_system_call_count;
  38. extern ulint rw_x_spin_wait_count;
  39. extern ulint rw_x_exit_count;
  40. /**********************************************************************
  41. Creates, or rather, initializes an rw-lock object in a specified memory
  42. location (which must be appropriately aligned). The rw-lock is initialized
  43. to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free
  44. is necessary only if the memory block containing it is freed. */
  45. #define rw_lock_create(L) rw_lock_create_func((L), IB__FILE__, __LINE__)
  46. /*=====================*/
  47. /**********************************************************************
  48. Creates, or rather, initializes an rw-lock object in a specified memory
  49. location (which must be appropriately aligned). The rw-lock is initialized
  50. to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free
  51. is necessary only if the memory block containing it is freed. */
  52. void
  53. rw_lock_create_func(
  54. /*================*/
  55. rw_lock_t* lock, /* in: pointer to memory */
  56. char* cfile_name, /* in: file name where created */
  57. ulint cline); /* in: file line where created */
  58. /**********************************************************************
  59. Calling this function is obligatory only if the memory buffer containing
  60. the rw-lock is freed. Removes an rw-lock object from the global list. The
  61. rw-lock is checked to be in the non-locked state. */
  62. void
  63. rw_lock_free(
  64. /*=========*/
  65. rw_lock_t* lock); /* in: rw-lock */
  66. /**********************************************************************
  67. Checks that the rw-lock has been initialized and that there are no
  68. simultaneous shared and exclusive locks. */
  69. ibool
  70. rw_lock_validate(
  71. /*=============*/
  72. rw_lock_t* lock);
  73. /******************************************************************
  74. NOTE! The following macros should be used in rw s-locking, not the
  75. corresponding function. */
  76. #ifdef UNIV_SYNC_DEBUG
  77. #define rw_lock_s_lock(M)    rw_lock_s_lock_func(
  78.   (M), 0, IB__FILE__, __LINE__)
  79. #else
  80. #define rw_lock_s_lock(M)    rw_lock_s_lock_func(M)
  81. #endif
  82. /******************************************************************
  83. NOTE! The following macros should be used in rw s-locking, not the
  84. corresponding function. */
  85. #ifdef UNIV_SYNC_DEBUG
  86. #define rw_lock_s_lock_gen(M, P)    rw_lock_s_lock_func(
  87.   (M), (P), IB__FILE__, __LINE__)
  88. #else
  89. #define rw_lock_s_lock_gen(M, P)    rw_lock_s_lock_func(M)
  90. #endif
  91. /******************************************************************
  92. NOTE! The following macros should be used in rw s-locking, not the
  93. corresponding function. */
  94. #ifdef UNIV_SYNC_DEBUG
  95. #define rw_lock_s_lock_nowait(M)    rw_lock_s_lock_func_nowait(
  96.      (M), IB__FILE__, __LINE__)
  97. #else
  98. #define rw_lock_s_lock_nowait(M)    rw_lock_s_lock_func_nowait(M)
  99. #endif
  100. /**********************************************************************
  101. NOTE! Use the corresponding macro, not directly this function, except if
  102. you supply the file name and line number. Lock an rw-lock in shared mode
  103. for the current thread. If the rw-lock is locked in exclusive mode, or
  104. there is an exclusive lock request waiting, the function spins a preset
  105. time (controlled by SYNC_SPIN_ROUNDS), waiting for the lock, before
  106. suspending the thread. */
  107. UNIV_INLINE
  108. void
  109. rw_lock_s_lock_func(
  110. /*================*/
  111.         rw_lock_t*    lock   /* in: pointer to rw-lock */
  112. #ifdef UNIV_SYNC_DEBUG
  113. ,ulint pass, /* in: pass value; != 0, if the lock will
  114. be passed to another thread to unlock */
  115. char* file_name, /* in: file name where lock requested */
  116. ulint line /* in: line where requested */
  117. #endif
  118. );
  119. /**********************************************************************
  120. NOTE! Use the corresponding macro, not directly this function, except if
  121. you supply the file name and line number. Lock an rw-lock in shared mode
  122. for the current thread if the lock can be acquired immediately. */
  123. UNIV_INLINE
  124. ibool
  125. rw_lock_s_lock_func_nowait(
  126. /*=======================*/
  127. /* out: TRUE if success */
  128.         rw_lock_t*    lock   /* in: pointer to rw-lock */
  129. #ifdef UNIV_SYNC_DEBUG
  130. ,char* file_name, /* in: file name where lock requested */
  131. ulint line /* in: line where requested */
  132. #endif
  133. );
  134. /**********************************************************************
  135. NOTE! Use the corresponding macro, not directly this function! Lock an
  136. rw-lock in exclusive mode for the current thread if the lock can be
  137. obtained immediately. */
  138. UNIV_INLINE
  139. ibool
  140. rw_lock_x_lock_func_nowait(
  141. /*=======================*/
  142. /* out: TRUE if success */
  143.         rw_lock_t*    lock   /* in: pointer to rw-lock */
  144. #ifdef UNIV_SYNC_DEBUG
  145. ,char* file_name, /* in: file name where lock requested */
  146. ulint line /* in: line where requested */
  147. #endif
  148. );
  149. /**********************************************************************
  150. Releases a shared mode lock. */
  151. UNIV_INLINE
  152. void
  153. rw_lock_s_unlock_func(
  154. /*==================*/
  155. rw_lock_t* lock /* in: rw-lock */
  156. #ifdef UNIV_SYNC_DEBUG
  157. ,ulint pass /* in: pass value; != 0, if the lock may have
  158. been passed to another thread to unlock */
  159. #endif
  160. );
  161. /***********************************************************************
  162. Releases a shared mode lock. */
  163. #ifdef UNIV_SYNC_DEBUG
  164. #define rw_lock_s_unlock(L)    rw_lock_s_unlock_func(L, 0)
  165. #else
  166. #define rw_lock_s_unlock(L)    rw_lock_s_unlock_func(L)
  167. #endif
  168. /***********************************************************************
  169. Releases a shared mode lock. */
  170. #ifdef UNIV_SYNC_DEBUG
  171. #define rw_lock_s_unlock_gen(L, P)    rw_lock_s_unlock_func(L, P)
  172. #else
  173. #define rw_lock_s_unlock_gen(L, P)    rw_lock_s_unlock_func(L)
  174. #endif
  175. /******************************************************************
  176. NOTE! The following macro should be used in rw x-locking, not the
  177. corresponding function. */
  178. #ifdef UNIV_SYNC_DEBUG
  179. #define rw_lock_x_lock(M)    rw_lock_x_lock_func(
  180.   (M), 0, IB__FILE__, __LINE__)
  181. #else
  182. #define rw_lock_x_lock(M)    rw_lock_x_lock_func(M, 0)
  183. #endif
  184. /******************************************************************
  185. NOTE! The following macro should be used in rw x-locking, not the
  186. corresponding function. */
  187. #ifdef UNIV_SYNC_DEBUG
  188. #define rw_lock_x_lock_gen(M, P)    rw_lock_x_lock_func(
  189.   (M), (P), IB__FILE__, __LINE__)
  190. #else
  191. #define rw_lock_x_lock_gen(M, P)    rw_lock_x_lock_func(M, P)
  192. #endif
  193. /******************************************************************
  194. NOTE! The following macros should be used in rw x-locking, not the
  195. corresponding function. */
  196. #ifdef UNIV_SYNC_DEBUG
  197. #define rw_lock_x_lock_nowait(M)    rw_lock_x_lock_func_nowait(
  198.      (M), IB__FILE__, __LINE__)
  199. #else
  200. #define rw_lock_x_lock_nowait(M)    rw_lock_x_lock_func_nowait(M)
  201. #endif
  202. /**********************************************************************
  203. NOTE! Use the corresponding macro, not directly this function! Lock an
  204. rw-lock in exclusive mode for the current thread. If the rw-lock is locked
  205. in shared or exclusive mode, or there is an exclusive lock request waiting,
  206. the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting
  207. for the lock, before suspending the thread. If the same thread has an x-lock
  208. on the rw-lock, locking succeed, with the following exception: if pass != 0,
  209. only a single x-lock may be taken on the lock. NOTE: If the same thread has
  210. an s-lock, locking does not succeed! */
  211. void
  212. rw_lock_x_lock_func(
  213. /*================*/
  214.         rw_lock_t*    lock,   /* in: pointer to rw-lock */
  215. ulint pass /* in: pass value; != 0, if the lock will
  216. be passed to another thread to unlock */
  217. #ifdef UNIV_SYNC_DEBUG
  218. ,char* file_name, /* in: file name where lock requested */
  219. ulint line /* in: line where requested */
  220. #endif
  221. );
  222. /**********************************************************************
  223. Releases an exclusive mode lock. */
  224. UNIV_INLINE
  225. void
  226. rw_lock_x_unlock_func(
  227. /*==================*/
  228. rw_lock_t* lock /* in: rw-lock */
  229. #ifdef UNIV_SYNC_DEBUG
  230. ,ulint pass /* in: pass value; != 0, if the lock may have
  231. been passed to another thread to unlock */
  232. #endif
  233. );
  234. /***********************************************************************
  235. Releases an exclusive mode lock. */
  236. #ifdef UNIV_SYNC_DEBUG
  237. #define rw_lock_x_unlock(L)    rw_lock_x_unlock_func(L, 0)
  238. #else
  239. #define rw_lock_x_unlock(L)    rw_lock_x_unlock_func(L)
  240. #endif
  241. /***********************************************************************
  242. Releases an exclusive mode lock. */
  243. #ifdef UNIV_SYNC_DEBUG
  244. #define rw_lock_x_unlock_gen(L, P)    rw_lock_x_unlock_func(L, P)
  245. #else
  246. #define rw_lock_x_unlock_gen(L, P)    rw_lock_x_unlock_func(L)
  247. #endif
  248. /**********************************************************************
  249. Low-level function which locks an rw-lock in s-mode when we know that it
  250. is possible and none else is currently accessing the rw-lock structure.
  251. Then we can do the locking without reserving the mutex. */
  252. UNIV_INLINE
  253. void
  254. rw_lock_s_lock_direct(
  255. /*==================*/
  256.         rw_lock_t*    lock   /* in: pointer to rw-lock */
  257. #ifdef UNIV_SYNC_DEBUG
  258. ,char* file_name, /* in: file name where lock requested */
  259. ulint line /* in: line where requested */
  260. #endif
  261. );
  262. /**********************************************************************
  263. Low-level function which locks an rw-lock in x-mode when we know that it
  264. is not locked and none else is currently accessing the rw-lock structure.
  265. Then we can do the locking without reserving the mutex. */
  266. UNIV_INLINE
  267. void
  268. rw_lock_x_lock_direct(
  269. /*==================*/
  270.         rw_lock_t*    lock   /* in: pointer to rw-lock */
  271. #ifdef UNIV_SYNC_DEBUG
  272. ,char* file_name, /* in: file name where lock requested */
  273. ulint line /* in: line where requested */
  274. #endif
  275. );
  276. /**********************************************************************
  277. This function is used in the insert buffer to move the ownership of an
  278. x-latch on a buffer frame to the current thread. The x-latch was set by
  279. the buffer read operation and it protected the buffer frame while the
  280. read was done. The ownership is moved because we want that the current
  281. thread is able to acquire a second x-latch which is stored in an mtr.
  282. This, in turn, is needed to pass the debug checks of index page
  283. operations. */
  284. void
  285. rw_lock_x_lock_move_ownership(
  286. /*==========================*/
  287. rw_lock_t* lock); /* in: lock which was x-locked in the
  288. buffer read */
  289. /**********************************************************************
  290. Releases a shared mode lock when we know there are no waiters and none
  291. else will access the lock during the time this function is executed. */
  292. UNIV_INLINE
  293. void
  294. rw_lock_s_unlock_direct(
  295. /*====================*/
  296. rw_lock_t* lock); /* in: rw-lock */
  297. /**********************************************************************
  298. Releases an exclusive mode lock when we know there are no waiters, and
  299. none else will access the lock durint the time this function is executed. */
  300. UNIV_INLINE
  301. void
  302. rw_lock_x_unlock_direct(
  303. /*====================*/
  304. rw_lock_t* lock); /* in: rw-lock */
  305. /**********************************************************************
  306. Sets the rw-lock latching level field. */
  307. void
  308. rw_lock_set_level(
  309. /*==============*/
  310. rw_lock_t* lock, /* in: rw-lock */
  311. ulint level); /* in: level */
  312. /**********************************************************************
  313. Returns the value of writer_count for the lock. Does not reserve the lock
  314. mutex, so the caller must be sure it is not changed during the call. */
  315. UNIV_INLINE
  316. ulint
  317. rw_lock_get_x_lock_count(
  318. /*=====================*/
  319. /* out: value of writer_count */
  320. rw_lock_t* lock); /* in: rw-lock */
  321. /**********************************************************************
  322. Checks if the thread has locked the rw-lock in the specified mode, with
  323. the pass value == 0. */
  324. ibool
  325. rw_lock_own(
  326. /*========*/
  327. rw_lock_t* lock, /* in: rw-lock */
  328. ulint lock_type); /* in: lock type */
  329. /**********************************************************************
  330. Checks if somebody has locked the rw-lock in the specified mode. */
  331. ibool
  332. rw_lock_is_locked(
  333. /*==============*/
  334. rw_lock_t* lock, /* in: rw-lock */
  335. ulint lock_type); /* in: lock type: RW_LOCK_SHARED,
  336. RW_LOCK_EX */
  337. /*******************************************************************
  338. Prints debug info of an rw-lock. */
  339. void
  340. rw_lock_print(
  341. /*==========*/
  342. rw_lock_t* lock); /* in: rw-lock */
  343. /*******************************************************************
  344. Prints debug info of currently locked rw-locks. */
  345. void
  346. rw_lock_list_print_info(void);
  347. /*=========================*/
  348. /*******************************************************************
  349. Returns the number of currently locked rw-locks.
  350. Works only in the debug version. */
  351. ulint
  352. rw_lock_n_locked(void);
  353. /*==================*/
  354. /*#####################################################################*/
  355. /**********************************************************************
  356. Acquires the debug mutex. We cannot use the mutex defined in sync0sync,
  357. because the debug mutex is also acquired in sync0arr while holding the OS
  358. mutex protecting the sync array, and the ordinary mutex_enter might
  359. recursively call routines in sync0arr, leading to a deadlock on the OS
  360. mutex. */
  361. void
  362. rw_lock_debug_mutex_enter(void);
  363. /*==========================*/
  364. /**********************************************************************
  365. Releases the debug mutex. */
  366. void
  367. rw_lock_debug_mutex_exit(void);
  368. /*==========================*/
  369. /*************************************************************************
  370. Prints info of a debug struct. */
  371. void
  372. rw_lock_debug_print(
  373. /*================*/
  374. rw_lock_debug_t* info); /* in: debug struct */
  375. #define RW_CNAME_LEN 8
  376. /* NOTE! The structure appears here only for the compiler to know its size.
  377. Do not use its fields directly! The structure used in the spin lock
  378. implementation of a read-write lock. Several threads may have a shared lock
  379. simultaneously in this lock, but only one writer may have an exclusive lock,
  380. in which case no shared locks are allowed. To prevent starving of a writer
  381. blocked by readers, a writer may queue for the lock by setting the writer
  382. field. Then no new readers are allowed in. */
  383. struct rw_lock_struct {
  384. ulint reader_count; /* Number of readers who have locked this
  385. lock in the shared mode */
  386. ulint writer;  /* This field is set to RW_LOCK_EX if there
  387. is a writer owning the lock (in exclusive
  388. mode), RW_LOCK_WAIT_EX if a writer is
  389. queueing for the lock, and
  390. RW_LOCK_NOT_LOCKED, otherwise. */
  391. os_thread_id_t writer_thread;
  392. /* Thread id of a possible writer thread */
  393. ulint writer_count; /* Number of times the same thread has
  394. recursively locked the lock in the exclusive
  395. mode */
  396. mutex_t mutex; /* The mutex protecting rw_lock_struct */
  397. ulint pass;  /* Default value 0. This is set to some
  398. value != 0 given by the caller of an x-lock
  399. operation, if the x-lock is to be passed to
  400. another thread to unlock (which happens in
  401. asynchronous i/o). */
  402. ulint waiters; /* This ulint is set to 1 if there are
  403. waiters (readers or writers) in the global
  404. wait array, waiting for this rw_lock.
  405. Otherwise, = 0. */
  406. ibool writer_is_wait_ex;
  407. /* This is TRUE if the writer field is
  408. RW_LOCK_WAIT_EX; this field is located far
  409. from the memory update hotspot fields which
  410. are at the start of this struct, thus we can
  411. peek this field without causing much memory
  412. bus traffic */
  413. UT_LIST_NODE_T(rw_lock_t) list;
  414. /* All allocated rw locks are put into a
  415. list */
  416. UT_LIST_BASE_NODE_T(rw_lock_debug_t) debug_list;
  417. /* In the debug version: pointer to the debug
  418. info list of the lock */
  419. ulint level; /* Debug version: level in the global latching
  420. order; default SYNC_LEVEL_NONE */
  421. char cfile_name[RW_CNAME_LEN];
  422. /* File name where lock created */
  423. ulint cline; /* Line where created */
  424. ulint magic_n;
  425. };
  426. #define RW_LOCK_MAGIC_N 22643
  427. /* The structure for storing debug info of an rw-lock */
  428. struct rw_lock_debug_struct {
  429. os_thread_id_t thread_id;  /* The thread id of the thread which
  430. locked the rw-lock */
  431. ulint pass; /* Pass value given in the lock operation */
  432. ulint lock_type; /* Type of the lock: RW_LOCK_EX,
  433. RW_LOCK_SHARED, RW_LOCK_WAIT_EX */
  434. char* file_name; /* File name where the lock was obtained */
  435. ulint line; /* Line where the rw-lock was locked */
  436. UT_LIST_NODE_T(rw_lock_debug_t) list;
  437. /* Debug structs are linked in a two-way
  438. list */
  439. };
  440. #ifndef UNIV_NONINL
  441. #include "sync0rw.ic"
  442. #endif
  443. #endif