00001 /****************************************************** 00002 The read-write lock (for threads, not for database transactions) 00003 00004 (c) 1995 Innobase Oy 00005 00006 Created 9/11/1995 Heikki Tuuri 00007 *******************************************************/ 00008 00009 #ifndef sync0rw_h 00010 #define sync0rw_h 00011 00012 #include "univ.i" 00013 #include "ut0lst.h" 00014 #include "sync0sync.h" 00015 #include "os0sync.h" 00016 00017 /* The following undef is to prevent a name conflict with a macro 00018 in MySQL: */ 00019 #undef rw_lock_t 00020 00021 /* Latch types; these are used also in btr0btr.h: keep the numerical values 00022 smaller than 30 and the order of the numerical values like below! */ 00023 #define RW_S_LATCH 1 00024 #define RW_X_LATCH 2 00025 #define RW_NO_LATCH 3 00026 00027 typedef struct rw_lock_struct rw_lock_t; 00028 #ifdef UNIV_SYNC_DEBUG 00029 typedef struct rw_lock_debug_struct rw_lock_debug_t; 00030 #endif /* UNIV_SYNC_DEBUG */ 00031 00032 typedef UT_LIST_BASE_NODE_T(rw_lock_t) rw_lock_list_t; 00033 00034 extern rw_lock_list_t rw_lock_list; 00035 extern mutex_t rw_lock_list_mutex; 00036 00037 #ifdef UNIV_SYNC_DEBUG 00038 /* The global mutex which protects debug info lists of all rw-locks. 00039 To modify the debug info list of an rw-lock, this mutex has to be 00040 00041 acquired in addition to the mutex protecting the lock. */ 00042 extern mutex_t rw_lock_debug_mutex; 00043 extern os_event_t rw_lock_debug_event; /* If deadlock detection does 00044 not get immediately the mutex it 00045 may wait for this event */ 00046 extern ibool rw_lock_debug_waiters; /* This is set to TRUE, if 00047 there may be waiters for the event */ 00048 #endif /* UNIV_SYNC_DEBUG */ 00049 00050 extern ulint rw_s_system_call_count; 00051 extern ulint rw_s_spin_wait_count; 00052 extern ulint rw_s_exit_count; 00053 extern ulint rw_s_os_wait_count; 00054 extern ulint rw_x_system_call_count; 00055 extern ulint rw_x_spin_wait_count; 00056 extern ulint rw_x_os_wait_count; 00057 extern ulint rw_x_exit_count; 00058 00059 /********************************************************************** 00060 Creates, or rather, initializes an rw-lock object in a specified memory 00061 location (which must be appropriately aligned). The rw-lock is initialized 00062 to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free 00063 is necessary only if the memory block containing it is freed. */ 00064 #define rw_lock_create(L, level) rw_lock_create_func((L), (level), __FILE__, __LINE__, #L) 00065 00066 /*=====================*/ 00067 /********************************************************************** 00068 Creates, or rather, initializes an rw-lock object in a specified memory 00069 location (which must be appropriately aligned). The rw-lock is initialized 00070 to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free 00071 is necessary only if the memory block containing it is freed. */ 00072 00073 void 00074 rw_lock_create_func( 00075 /*================*/ 00076 rw_lock_t* lock, /* in: pointer to memory */ 00077 ulint level, /* in: level */ 00078 const char* cfile_name, /* in: file name where created */ 00079 ulint cline, /* in: file line where created */ 00080 const char* cmutex_name); /* in: mutex name */ 00081 /********************************************************************** 00082 Calling this function is obligatory only if the memory buffer containing 00083 the rw-lock is freed. Removes an rw-lock object from the global list. The 00084 rw-lock is checked to be in the non-locked state. */ 00085 00086 void 00087 rw_lock_free( 00088 /*=========*/ 00089 rw_lock_t* lock); /* in: rw-lock */ 00090 /********************************************************************** 00091 Checks that the rw-lock has been initialized and that there are no 00092 simultaneous shared and exclusive locks. */ 00093 00094 ibool 00095 rw_lock_validate( 00096 /*=============*/ 00097 rw_lock_t* lock); 00098 /****************************************************************** 00099 NOTE! The following macros should be used in rw s-locking, not the 00100 corresponding function. */ 00101 00102 #define rw_lock_s_lock(M) rw_lock_s_lock_func(\ 00103 (M), 0, __FILE__, __LINE__) 00104 /****************************************************************** 00105 NOTE! The following macros should be used in rw s-locking, not the 00106 corresponding function. */ 00107 00108 #define rw_lock_s_lock_gen(M, P) rw_lock_s_lock_func(\ 00109 (M), (P), __FILE__, __LINE__) 00110 /****************************************************************** 00111 NOTE! The following macros should be used in rw s-locking, not the 00112 corresponding function. */ 00113 00114 #define rw_lock_s_lock_nowait(M) rw_lock_s_lock_func_nowait(\ 00115 (M), __FILE__, __LINE__) 00116 /********************************************************************** 00117 NOTE! Use the corresponding macro, not directly this function, except if 00118 you supply the file name and line number. Lock an rw-lock in shared mode 00119 for the current thread. If the rw-lock is locked in exclusive mode, or 00120 there is an exclusive lock request waiting, the function spins a preset 00121 time (controlled by SYNC_SPIN_ROUNDS), waiting for the lock, before 00122 suspending the thread. */ 00123 UNIV_INLINE 00124 void 00125 rw_lock_s_lock_func( 00126 /*================*/ 00127 rw_lock_t* lock, /* in: pointer to rw-lock */ 00128 ulint pass, /* in: pass value; != 0, if the lock will 00129 be passed to another thread to unlock */ 00130 const char* file_name,/* in: file name where lock requested */ 00131 ulint line); /* in: line where requested */ 00132 /********************************************************************** 00133 NOTE! Use the corresponding macro, not directly this function, except if 00134 you supply the file name and line number. Lock an rw-lock in shared mode 00135 for the current thread if the lock can be acquired immediately. */ 00136 UNIV_INLINE 00137 ibool 00138 rw_lock_s_lock_func_nowait( 00139 /*=======================*/ 00140 /* out: TRUE if success */ 00141 rw_lock_t* lock, /* in: pointer to rw-lock */ 00142 const char* file_name,/* in: file name where lock requested */ 00143 ulint line); /* in: line where requested */ 00144 /********************************************************************** 00145 NOTE! Use the corresponding macro, not directly this function! Lock an 00146 rw-lock in exclusive mode for the current thread if the lock can be 00147 obtained immediately. */ 00148 UNIV_INLINE 00149 ibool 00150 rw_lock_x_lock_func_nowait( 00151 /*=======================*/ 00152 /* out: TRUE if success */ 00153 rw_lock_t* lock, /* in: pointer to rw-lock */ 00154 const char* file_name,/* in: file name where lock requested */ 00155 ulint line); /* in: line where requested */ 00156 /********************************************************************** 00157 Releases a shared mode lock. */ 00158 UNIV_INLINE 00159 void 00160 rw_lock_s_unlock_func( 00161 /*==================*/ 00162 rw_lock_t* lock /* in: rw-lock */ 00163 #ifdef UNIV_SYNC_DEBUG 00164 ,ulint pass /* in: pass value; != 0, if the lock may have 00165 been passed to another thread to unlock */ 00166 #endif 00167 ); 00168 /*********************************************************************** 00169 Releases a shared mode lock. */ 00170 00171 #ifdef UNIV_SYNC_DEBUG 00172 #define rw_lock_s_unlock(L) rw_lock_s_unlock_func(L, 0) 00173 #else 00174 #define rw_lock_s_unlock(L) rw_lock_s_unlock_func(L) 00175 #endif 00176 /*********************************************************************** 00177 Releases a shared mode lock. */ 00178 00179 #ifdef UNIV_SYNC_DEBUG 00180 #define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(L, P) 00181 #else 00182 #define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(L) 00183 #endif 00184 /****************************************************************** 00185 NOTE! The following macro should be used in rw x-locking, not the 00186 corresponding function. */ 00187 00188 #define rw_lock_x_lock(M) rw_lock_x_lock_func(\ 00189 (M), 0, __FILE__, __LINE__) 00190 /****************************************************************** 00191 NOTE! The following macro should be used in rw x-locking, not the 00192 corresponding function. */ 00193 00194 #define rw_lock_x_lock_gen(M, P) rw_lock_x_lock_func(\ 00195 (M), (P), __FILE__, __LINE__) 00196 /****************************************************************** 00197 NOTE! The following macros should be used in rw x-locking, not the 00198 corresponding function. */ 00199 00200 #define rw_lock_x_lock_nowait(M) rw_lock_x_lock_func_nowait(\ 00201 (M), __FILE__, __LINE__) 00202 /********************************************************************** 00203 NOTE! Use the corresponding macro, not directly this function! Lock an 00204 rw-lock in exclusive mode for the current thread. If the rw-lock is locked 00205 in shared or exclusive mode, or there is an exclusive lock request waiting, 00206 the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting 00207 for the lock, before suspending the thread. If the same thread has an x-lock 00208 on the rw-lock, locking succeed, with the following exception: if pass != 0, 00209 only a single x-lock may be taken on the lock. NOTE: If the same thread has 00210 an s-lock, locking does not succeed! */ 00211 00212 void 00213 rw_lock_x_lock_func( 00214 /*================*/ 00215 rw_lock_t* lock, /* in: pointer to rw-lock */ 00216 ulint pass, /* in: pass value; != 0, if the lock will 00217 be passed to another thread to unlock */ 00218 const char* file_name,/* in: file name where lock requested */ 00219 ulint line); /* in: line where requested */ 00220 /********************************************************************** 00221 Releases an exclusive mode lock. */ 00222 UNIV_INLINE 00223 void 00224 rw_lock_x_unlock_func( 00225 /*==================*/ 00226 rw_lock_t* lock /* in: rw-lock */ 00227 #ifdef UNIV_SYNC_DEBUG 00228 ,ulint pass /* in: pass value; != 0, if the lock may have 00229 been passed to another thread to unlock */ 00230 #endif 00231 ); 00232 /*********************************************************************** 00233 Releases an exclusive mode lock. */ 00234 00235 #ifdef UNIV_SYNC_DEBUG 00236 #define rw_lock_x_unlock(L) rw_lock_x_unlock_func(L, 0) 00237 #else 00238 #define rw_lock_x_unlock(L) rw_lock_x_unlock_func(L) 00239 #endif 00240 /*********************************************************************** 00241 Releases an exclusive mode lock. */ 00242 00243 #ifdef UNIV_SYNC_DEBUG 00244 #define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(L, P) 00245 #else 00246 #define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(L) 00247 #endif 00248 /********************************************************************** 00249 Low-level function which locks an rw-lock in s-mode when we know that it 00250 is possible and none else is currently accessing the rw-lock structure. 00251 Then we can do the locking without reserving the mutex. */ 00252 UNIV_INLINE 00253 void 00254 rw_lock_s_lock_direct( 00255 /*==================*/ 00256 rw_lock_t* lock, /* in: pointer to rw-lock */ 00257 const char* file_name, /* in: file name where requested */ 00258 ulint line /* in: line where lock requested */ 00259 ); 00260 /********************************************************************** 00261 Low-level function which locks an rw-lock in x-mode when we know that it 00262 is not locked and none else is currently accessing the rw-lock structure. 00263 Then we can do the locking without reserving the mutex. */ 00264 UNIV_INLINE 00265 void 00266 rw_lock_x_lock_direct( 00267 /*==================*/ 00268 rw_lock_t* lock, /* in: pointer to rw-lock */ 00269 const char* file_name, /* in: file name where requested */ 00270 ulint line /* in: line where lock requested */ 00271 ); 00272 /********************************************************************** 00273 This function is used in the insert buffer to move the ownership of an 00274 x-latch on a buffer frame to the current thread. The x-latch was set by 00275 the buffer read operation and it protected the buffer frame while the 00276 read was done. The ownership is moved because we want that the current 00277 thread is able to acquire a second x-latch which is stored in an mtr. 00278 This, in turn, is needed to pass the debug checks of index page 00279 operations. */ 00280 00281 void 00282 rw_lock_x_lock_move_ownership( 00283 /*==========================*/ 00284 rw_lock_t* lock); /* in: lock which was x-locked in the 00285 buffer read */ 00286 /********************************************************************** 00287 Releases a shared mode lock when we know there are no waiters and none 00288 else will access the lock during the time this function is executed. */ 00289 UNIV_INLINE 00290 void 00291 rw_lock_s_unlock_direct( 00292 /*====================*/ 00293 rw_lock_t* lock); /* in: rw-lock */ 00294 /********************************************************************** 00295 Releases an exclusive mode lock when we know there are no waiters, and 00296 none else will access the lock durint the time this function is executed. */ 00297 UNIV_INLINE 00298 void 00299 rw_lock_x_unlock_direct( 00300 /*====================*/ 00301 rw_lock_t* lock); /* in: rw-lock */ 00302 /********************************************************************** 00303 Returns the value of writer_count for the lock. Does not reserve the lock 00304 mutex, so the caller must be sure it is not changed during the call. */ 00305 UNIV_INLINE 00306 ulint 00307 rw_lock_get_x_lock_count( 00308 /*=====================*/ 00309 /* out: value of writer_count */ 00310 rw_lock_t* lock); /* in: rw-lock */ 00311 /************************************************************************ 00312 Accessor functions for rw lock. */ 00313 UNIV_INLINE 00314 ulint 00315 rw_lock_get_waiters( 00316 /*================*/ 00317 rw_lock_t* lock); 00318 UNIV_INLINE 00319 ulint 00320 rw_lock_get_writer( 00321 /*===============*/ 00322 rw_lock_t* lock); 00323 UNIV_INLINE 00324 ulint 00325 rw_lock_get_reader_count( 00326 /*=====================*/ 00327 rw_lock_t* lock); 00328 #ifdef UNIV_SYNC_DEBUG 00329 /********************************************************************** 00330 Checks if the thread has locked the rw-lock in the specified mode, with 00331 the pass value == 0. */ 00332 00333 ibool 00334 rw_lock_own( 00335 /*========*/ 00336 rw_lock_t* lock, /* in: rw-lock */ 00337 ulint lock_type); /* in: lock type: RW_LOCK_SHARED, 00338 RW_LOCK_EX */ 00339 #endif /* UNIV_SYNC_DEBUG */ 00340 /********************************************************************** 00341 Checks if somebody has locked the rw-lock in the specified mode. */ 00342 00343 ibool 00344 rw_lock_is_locked( 00345 /*==============*/ 00346 rw_lock_t* lock, /* in: rw-lock */ 00347 ulint lock_type); /* in: lock type: RW_LOCK_SHARED, 00348 RW_LOCK_EX */ 00349 #ifdef UNIV_SYNC_DEBUG 00350 /******************************************************************* 00351 Prints debug info of an rw-lock. */ 00352 00353 void 00354 rw_lock_print( 00355 /*==========*/ 00356 rw_lock_t* lock); /* in: rw-lock */ 00357 /******************************************************************* 00358 Prints debug info of currently locked rw-locks. */ 00359 00360 void 00361 rw_lock_list_print_info(void); 00362 /*=========================*/ 00363 /******************************************************************* 00364 Returns the number of currently locked rw-locks. 00365 Works only in the debug version. */ 00366 00367 ulint 00368 rw_lock_n_locked(void); 00369 /*==================*/ 00370 00371 /*#####################################################################*/ 00372 00373 /********************************************************************** 00374 Acquires the debug mutex. We cannot use the mutex defined in sync0sync, 00375 because the debug mutex is also acquired in sync0arr while holding the OS 00376 mutex protecting the sync array, and the ordinary mutex_enter might 00377 recursively call routines in sync0arr, leading to a deadlock on the OS 00378 mutex. */ 00379 00380 void 00381 rw_lock_debug_mutex_enter(void); 00382 /*==========================*/ 00383 /********************************************************************** 00384 Releases the debug mutex. */ 00385 00386 void 00387 rw_lock_debug_mutex_exit(void); 00388 /*==========================*/ 00389 /************************************************************************* 00390 Prints info of a debug struct. */ 00391 00392 void 00393 rw_lock_debug_print( 00394 /*================*/ 00395 rw_lock_debug_t* info); /* in: debug struct */ 00396 #endif /* UNIV_SYNC_DEBUG */ 00397 00398 /* NOTE! The structure appears here only for the compiler to know its size. 00399 Do not use its fields directly! The structure used in the spin lock 00400 implementation of a read-write lock. Several threads may have a shared lock 00401 simultaneously in this lock, but only one writer may have an exclusive lock, 00402 in which case no shared locks are allowed. To prevent starving of a writer 00403 blocked by readers, a writer may queue for the lock by setting the writer 00404 field. Then no new readers are allowed in. */ 00405 00406 struct rw_lock_struct { 00407 ulint reader_count; /* Number of readers who have locked this 00408 lock in the shared mode */ 00409 ulint writer; /* This field is set to RW_LOCK_EX if there 00410 is a writer owning the lock (in exclusive 00411 mode), RW_LOCK_WAIT_EX if a writer is 00412 queueing for the lock, and 00413 RW_LOCK_NOT_LOCKED, otherwise. */ 00414 os_thread_id_t writer_thread; 00415 /* Thread id of a possible writer thread */ 00416 ulint writer_count; /* Number of times the same thread has 00417 recursively locked the lock in the exclusive 00418 mode */ 00419 mutex_t mutex; /* The mutex protecting rw_lock_struct */ 00420 ulint pass; /* Default value 0. This is set to some 00421 value != 0 given by the caller of an x-lock 00422 operation, if the x-lock is to be passed to 00423 another thread to unlock (which happens in 00424 asynchronous i/o). */ 00425 ulint waiters; /* This ulint is set to 1 if there are 00426 waiters (readers or writers) in the global 00427 wait array, waiting for this rw_lock. 00428 Otherwise, == 0. */ 00429 ibool writer_is_wait_ex; 00430 /* This is TRUE if the writer field is 00431 RW_LOCK_WAIT_EX; this field is located far 00432 from the memory update hotspot fields which 00433 are at the start of this struct, thus we can 00434 peek this field without causing much memory 00435 bus traffic */ 00436 UT_LIST_NODE_T(rw_lock_t) list; 00437 /* All allocated rw locks are put into a 00438 list */ 00439 #ifdef UNIV_SYNC_DEBUG 00440 UT_LIST_BASE_NODE_T(rw_lock_debug_t) debug_list; 00441 /* In the debug version: pointer to the debug 00442 info list of the lock */ 00443 #endif /* UNIV_SYNC_DEBUG */ 00444 00445 ulint level; /* Level in the global latching order. */ 00446 const char* cfile_name;/* File name where lock created */ 00447 ulint cline; /* Line where created */ 00448 const char* last_s_file_name;/* File name where last s-locked */ 00449 const char* last_x_file_name;/* File name where last x-locked */ 00450 ulint last_s_line; /* Line number where last time s-locked */ 00451 ulint last_x_line; /* Line number where last time x-locked */ 00452 ulint magic_n; 00453 }; 00454 00455 #define RW_LOCK_MAGIC_N 22643 00456 00457 #ifdef UNIV_SYNC_DEBUG 00458 /* The structure for storing debug info of an rw-lock */ 00459 struct rw_lock_debug_struct { 00460 00461 os_thread_id_t thread_id; /* The thread id of the thread which 00462 locked the rw-lock */ 00463 ulint pass; /* Pass value given in the lock operation */ 00464 ulint lock_type; /* Type of the lock: RW_LOCK_EX, 00465 RW_LOCK_SHARED, RW_LOCK_WAIT_EX */ 00466 const char* file_name;/* File name where the lock was obtained */ 00467 ulint line; /* Line where the rw-lock was locked */ 00468 UT_LIST_NODE_T(rw_lock_debug_t) list; 00469 /* Debug structs are linked in a two-way 00470 list */ 00471 }; 00472 #endif /* UNIV_SYNC_DEBUG */ 00473 00474 #ifndef UNIV_NONINL 00475 #include "sync0rw.ic" 00476 #endif 00477 00478 #endif
1.4.7

