Drizzled Public API Documentation

sync0rw.h

Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003 Copyright (C) 1995, 2010, Innobase Oy. All Rights Reserved.
00004 Copyright (C) 2008, Google Inc.
00005 
00006 Portions of this file contain modifications contributed and copyrighted by
00007 Google, Inc. Those modifications are gratefully acknowledged and are described
00008 briefly in the InnoDB documentation. The contributions by Google are
00009 incorporated with their permission, and subject to the conditions contained in
00010 the file COPYING.Google.
00011 
00012 This program is free software; you can redistribute it and/or modify it under
00013 the terms of the GNU General Public License as published by the Free Software
00014 Foundation; version 2 of the License.
00015 
00016 This program is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00018 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License along with
00021 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
00022 St, Fifth Floor, Boston, MA 02110-1301 USA
00023 
00024 *****************************************************************************/
00025 
00026 /**************************************************/
00033 #pragma once
00034 #ifndef sync0rw_h
00035 #define sync0rw_h
00036 
00037 #include "univ.i"
00038 #ifndef UNIV_HOTBACKUP
00039 #include "ut0lst.h"
00040 #include "sync0sync.h"
00041 #include "os0sync.h"
00042 
00043 /* The following undef is to prevent a name conflict with a macro
00044 in MySQL: */
00045 #undef rw_lock_t
00046 #endif /* !UNIV_HOTBACKUP */
00047 
00048 /* Latch types; these are used also in btr0btr.h: keep the numerical values
00049 smaller than 30 and the order of the numerical values like below! */
00050 #define RW_S_LATCH  1
00051 #define RW_X_LATCH  2
00052 #define RW_NO_LATCH 3
00053 
00054 #ifndef UNIV_HOTBACKUP
00055 /* We decrement lock_word by this amount for each x_lock. It is also the
00056 start value for the lock_word, meaning that it limits the maximum number
00057 of concurrent read locks before the rw_lock breaks. The current value of
00058 0x00100000 allows 1,048,575 concurrent readers and 2047 recursive writers.*/
00059 #define X_LOCK_DECR   0x00100000
00060 
00061 typedef struct rw_lock_struct   rw_lock_t;
00062 #ifdef UNIV_SYNC_DEBUG
00063 typedef struct rw_lock_debug_struct rw_lock_debug_t;
00064 #endif /* UNIV_SYNC_DEBUG */
00065 
00066 typedef UT_LIST_BASE_NODE_T(rw_lock_t)  rw_lock_list_t;
00067 
00068 extern rw_lock_list_t rw_lock_list;
00069 extern mutex_t    rw_lock_list_mutex;
00070 
00071 #ifdef UNIV_SYNC_DEBUG
00072 /* The global mutex which protects debug info lists of all rw-locks.
00073 To modify the debug info list of an rw-lock, this mutex has to be
00074 
00075 acquired in addition to the mutex protecting the lock. */
00076 extern mutex_t    rw_lock_debug_mutex;
00077 extern os_event_t rw_lock_debug_event;  
00080 extern ibool    rw_lock_debug_waiters;  
00082 #endif /* UNIV_SYNC_DEBUG */
00083 
00086 extern  ib_int64_t  rw_s_spin_wait_count;
00089 extern  ib_int64_t  rw_s_spin_round_count;
00092 extern  ib_int64_t  rw_s_exit_count;
00095 extern  ib_int64_t  rw_s_os_wait_count;
00098 extern  ib_int64_t  rw_x_spin_wait_count;
00101 extern  ib_int64_t  rw_x_spin_round_count;
00104 extern  ib_int64_t  rw_x_os_wait_count;
00107 extern  ib_int64_t  rw_x_exit_count;
00108 
00109 #ifdef UNIV_PFS_RWLOCK
00110 /* Following are rwlock keys used to register with MySQL
00111 performance schema */
00112 # ifdef UNIV_LOG_ARCHIVE
00113 extern  mysql_pfs_key_t archive_lock_key;
00114 # endif /* UNIV_LOG_ARCHIVE */
00115 extern  mysql_pfs_key_t btr_search_latch_key;
00116 extern  mysql_pfs_key_t buf_block_lock_key;
00117 # ifdef UNIV_SYNC_DEBUG
00118 extern  mysql_pfs_key_t buf_block_debug_latch_key;
00119 # endif /* UNIV_SYNC_DEBUG */
00120 extern  mysql_pfs_key_t dict_operation_lock_key;
00121 extern  mysql_pfs_key_t fil_space_latch_key;
00122 extern  mysql_pfs_key_t checkpoint_lock_key;
00123 extern  mysql_pfs_key_t trx_i_s_cache_lock_key;
00124 extern  mysql_pfs_key_t trx_purge_latch_key;
00125 extern  mysql_pfs_key_t index_tree_rw_lock_key;
00126 #endif /* UNIV_PFS_RWLOCK */
00127 
00128 
00129 #ifndef UNIV_PFS_RWLOCK
00130 /******************************************************************/
00137 # ifdef UNIV_DEBUG
00138 #  ifdef UNIV_SYNC_DEBUG
00139 #   define rw_lock_create(K, L, level)        \
00140   rw_lock_create_func((L), (level), #L, __FILE__, __LINE__)
00141 #  else /* UNIV_SYNC_DEBUG */
00142 #   define rw_lock_create(K, L, level)        \
00143   rw_lock_create_func((L), #L, __FILE__, __LINE__)
00144 #  endif/* UNIV_SYNC_DEBUG */
00145 # else /* UNIV_DEBUG */
00146 #  define rw_lock_create(K, L, level)       \
00147   rw_lock_create_func((L), __FILE__, __LINE__)
00148 # endif /* UNIV_DEBUG */
00149 
00150 /**************************************************************/
00154 # define rw_lock_s_lock(M)          \
00155   rw_lock_s_lock_func((M), 0, __FILE__, __LINE__)
00156 
00157 # define rw_lock_s_lock_gen(M, P)       \
00158   rw_lock_s_lock_func((M), (P), __FILE__, __LINE__)
00159 
00160 # define rw_lock_s_lock_nowait(M, F, L)       \
00161   rw_lock_s_lock_low((M), 0, (F), (L))
00162 
00163 # ifdef UNIV_SYNC_DEBUG
00164 #  define rw_lock_s_unlock_gen(L, P)  rw_lock_s_unlock_func(P, L)
00165 # else
00166 #  define rw_lock_s_unlock_gen(L, P)  rw_lock_s_unlock_func(L)
00167 # endif
00168 
00169 
00170 # define rw_lock_x_lock(M)          \
00171   rw_lock_x_lock_func((M), 0, __FILE__, __LINE__)
00172 
00173 # define rw_lock_x_lock_gen(M, P)       \
00174   rw_lock_x_lock_func((M), (P), __FILE__, __LINE__)
00175 
00176 # define rw_lock_x_lock_nowait(M)       \
00177   rw_lock_x_lock_func_nowait((M), __FILE__, __LINE__)
00178 
00179 # ifdef UNIV_SYNC_DEBUG
00180 #  define rw_lock_x_unlock_gen(L, P)  rw_lock_x_unlock_func(P, L)
00181 # else
00182 #  define rw_lock_x_unlock_gen(L, P)  rw_lock_x_unlock_func(L)
00183 # endif
00184 
00185 # define rw_lock_free(M)    rw_lock_free_func(M)
00186 
00187 #else /* !UNIV_PFS_RWLOCK */
00188 
00189 /* Following macros point to Performance Schema instrumented functions. */
00190 # ifdef UNIV_DEBUG
00191 #  ifdef UNIV_SYNC_DEBUG
00192 #   define rw_lock_create(K, L, level)        \
00193   pfs_rw_lock_create_func((K), (L), (level), #L, __FILE__, __LINE__)
00194 #  else /* UNIV_SYNC_DEBUG */
00195 #   define rw_lock_create(K, L, level)        \
00196   pfs_rw_lock_create_func((K), (L), #L, __FILE__, __LINE__)
00197 #  endif/* UNIV_SYNC_DEBUG */
00198 # else  /* UNIV_DEBUG */
00199 #  define rw_lock_create(K, L, level)       \
00200   pfs_rw_lock_create_func((K), (L), __FILE__, __LINE__)
00201 # endif /* UNIV_DEBUG */
00202 
00203 /******************************************************************
00204 NOTE! The following macros should be used in rw locking and
00205 unlocking, not the corresponding function. */
00206 
00207 # define rw_lock_s_lock(M)          \
00208   pfs_rw_lock_s_lock_func((M), 0, __FILE__, __LINE__)
00209 
00210 # define rw_lock_s_lock_gen(M, P)       \
00211   pfs_rw_lock_s_lock_func((M), (P), __FILE__, __LINE__)
00212 
00213 # define rw_lock_s_lock_nowait(M, F, L)       \
00214   pfs_rw_lock_s_lock_low((M), 0, (F), (L))
00215 
00216 # ifdef UNIV_SYNC_DEBUG
00217 #  define rw_lock_s_unlock_gen(L, P)  pfs_rw_lock_s_unlock_func(P, L)
00218 # else
00219 #  define rw_lock_s_unlock_gen(L, P)  pfs_rw_lock_s_unlock_func(L)
00220 # endif
00221 
00222 # define rw_lock_x_lock(M)          \
00223   pfs_rw_lock_x_lock_func((M), 0, __FILE__, __LINE__)
00224 
00225 # define rw_lock_x_lock_gen(M, P)       \
00226   pfs_rw_lock_x_lock_func((M), (P), __FILE__, __LINE__)
00227 
00228 # define rw_lock_x_lock_nowait(M)       \
00229   pfs_rw_lock_x_lock_func_nowait((M), __FILE__, __LINE__)
00230 
00231 # ifdef UNIV_SYNC_DEBUG
00232 #  define rw_lock_x_unlock_gen(L, P)  pfs_rw_lock_x_unlock_func(P, L)
00233 # else
00234 #  define rw_lock_x_unlock_gen(L, P)  pfs_rw_lock_x_unlock_func(L)
00235 # endif
00236 
00237 # define rw_lock_free(M)    pfs_rw_lock_free_func(M)
00238 
00239 #endif /* UNIV_PFS_RWLOCK */
00240 
00241 #define rw_lock_s_unlock(L)   rw_lock_s_unlock_gen(L, 0)
00242 #define rw_lock_x_unlock(L)   rw_lock_x_unlock_gen(L, 0)
00243 
00244 /******************************************************************/
00249 UNIV_INTERN
00250 void
00251 rw_lock_create_func(
00252 /*================*/
00253   rw_lock_t*  lock,   
00254 #ifdef UNIV_DEBUG
00255 # ifdef UNIV_SYNC_DEBUG
00256   ulint   level,    
00257 # endif /* UNIV_SYNC_DEBUG */
00258   const char* cmutex_name,  
00259 #endif /* UNIV_DEBUG */
00260   const char* cfile_name, 
00261   ulint   cline);   
00262 /******************************************************************/
00266 UNIV_INTERN
00267 void
00268 rw_lock_free_func(
00269 /*==============*/
00270   rw_lock_t*  lock);  
00271 #ifdef UNIV_DEBUG
00272 /******************************************************************/
00276 UNIV_INTERN
00277 ibool
00278 rw_lock_validate(
00279 /*=============*/
00280   rw_lock_t*  lock);  
00281 #endif /* UNIV_DEBUG */
00282 /******************************************************************/
00286 UNIV_INLINE
00287 ibool
00288 rw_lock_s_lock_low(
00289 /*===============*/
00290   rw_lock_t*  lock, 
00291   ulint   /*pass __attribute__((unused))*/,
00294   const char* file_name, 
00295   ulint   line);  
00296 /******************************************************************/
00303 UNIV_INLINE
00304 void
00305 rw_lock_s_lock_func(
00306 /*================*/
00307   rw_lock_t*  lock, 
00308   ulint   pass, 
00310   const char* file_name,
00311   ulint   line);  
00312 /******************************************************************/
00317 UNIV_INLINE
00318 ibool
00319 rw_lock_x_lock_func_nowait(
00320 /*=======================*/
00321   rw_lock_t*  lock, 
00322   const char* file_name,
00323   ulint   line);  
00324 /******************************************************************/
00326 UNIV_INLINE
00327 void
00328 rw_lock_s_unlock_func(
00329 /*==================*/
00330 #ifdef UNIV_SYNC_DEBUG
00331   ulint   pass, 
00333 #endif
00334   rw_lock_t*  lock);  
00336 /******************************************************************/
00345 UNIV_INTERN
00346 void
00347 rw_lock_x_lock_func(
00348 /*================*/
00349   rw_lock_t*  lock, 
00350   ulint   pass, 
00352   const char* file_name,
00353   ulint   line);  
00354 /******************************************************************/
00356 UNIV_INLINE
00357 void
00358 rw_lock_x_unlock_func(
00359 /*==================*/
00360 #ifdef UNIV_SYNC_DEBUG
00361   ulint   pass, 
00363 #endif
00364   rw_lock_t*  lock);  
00367 /******************************************************************/
00371 UNIV_INLINE
00372 void
00373 rw_lock_s_lock_direct(
00374 /*==================*/
00375   rw_lock_t*  lock,   
00376   const char* file_name,  
00377   ulint   line);    
00378 /******************************************************************/
00382 UNIV_INLINE
00383 void
00384 rw_lock_x_lock_direct(
00385 /*==================*/
00386   rw_lock_t*  lock,   
00387   const char* file_name,  
00388   ulint   line);    
00389 /******************************************************************/
00397 UNIV_INTERN
00398 void
00399 rw_lock_x_lock_move_ownership(
00400 /*==========================*/
00401   rw_lock_t*  lock);  
00403 /******************************************************************/
00406 UNIV_INLINE
00407 void
00408 rw_lock_s_unlock_direct(
00409 /*====================*/
00410   rw_lock_t*  lock);  
00411 /******************************************************************/
00414 UNIV_INLINE
00415 void
00416 rw_lock_x_unlock_direct(
00417 /*====================*/
00418   rw_lock_t*  lock);  
00419 /******************************************************************/
00423 UNIV_INLINE
00424 ulint
00425 rw_lock_get_x_lock_count(
00426 /*=====================*/
00427   const rw_lock_t*  lock);  
00428 /********************************************************************/
00431 UNIV_INLINE
00432 ulint
00433 rw_lock_get_waiters(
00434 /*================*/
00435   const rw_lock_t*  lock);  
00436 /******************************************************************/
00440 UNIV_INLINE
00441 ulint
00442 rw_lock_get_writer(
00443 /*===============*/
00444   const rw_lock_t*  lock);  
00445 /******************************************************************/
00448 UNIV_INLINE
00449 ulint
00450 rw_lock_get_reader_count(
00451 /*=====================*/
00452   const rw_lock_t*  lock);  
00453 /******************************************************************/
00457 UNIV_INLINE
00458 ibool
00459 rw_lock_lock_word_decr(
00460 /*===================*/
00461   rw_lock_t*  lock,   
00462   ulint   amount);  
00463 /******************************************************************/
00466 UNIV_INLINE
00467 lint
00468 rw_lock_lock_word_incr(
00469 /*===================*/
00470   rw_lock_t*  lock,   
00471   ulint   amount);  
00472 /******************************************************************/
00481 UNIV_INLINE
00482 void
00483 rw_lock_set_writer_id_and_recursion_flag(
00484 /*=====================================*/
00485   rw_lock_t*  lock,   
00486   ibool   recursive); 
00488 #ifdef UNIV_SYNC_DEBUG
00489 /******************************************************************/
00492 UNIV_INTERN
00493 ibool
00494 rw_lock_own(
00495 /*========*/
00496   rw_lock_t*  lock,   
00497   ulint   lock_type)  
00499   __attribute__((warn_unused_result));
00500 #endif /* UNIV_SYNC_DEBUG */
00501 /******************************************************************/
00503 UNIV_INTERN
00504 ibool
00505 rw_lock_is_locked(
00506 /*==============*/
00507   rw_lock_t*  lock,   
00508   ulint   lock_type); 
00510 #ifdef UNIV_SYNC_DEBUG
00511 /***************************************************************/
00513 UNIV_INTERN
00514 void
00515 rw_lock_print(
00516 /*==========*/
00517   rw_lock_t*  lock);  
00518 /***************************************************************/
00520 UNIV_INTERN
00521 void
00522 rw_lock_list_print_info(
00523 /*====================*/
00524   FILE* file);    
00525 /***************************************************************/
00529 UNIV_INTERN
00530 ulint
00531 rw_lock_n_locked(void);
00532 /*==================*/
00533 
00534 /*#####################################################################*/
00535 
00536 /******************************************************************/
00542 UNIV_INTERN
00543 void
00544 rw_lock_debug_mutex_enter(void);
00545 /*==========================*/
00546 /******************************************************************/
00548 UNIV_INTERN
00549 void
00550 rw_lock_debug_mutex_exit(void);
00551 /*==========================*/
00552 /*********************************************************************/
00554 UNIV_INTERN
00555 void
00556 rw_lock_debug_print(
00557 /*================*/
00558   rw_lock_debug_t*  info);  
00559 #endif /* UNIV_SYNC_DEBUG */
00560 
00561 /* NOTE! The structure appears here only for the compiler to know its size.
00562 Do not use its fields directly! */
00563 
00571 struct rw_lock_struct {
00572   volatile lint lock_word;
00574   volatile ulint  waiters;
00575   volatile ibool  recursive;
00587   volatile os_thread_id_t writer_thread;
00591   os_event_t  event;  
00592   os_event_t  wait_ex_event;
00595 #ifndef INNODB_RW_LOCKS_USE_ATOMICS
00596   mutex_t mutex;    
00597 #endif /* INNODB_RW_LOCKS_USE_ATOMICS */
00598 
00599   UT_LIST_NODE_T(rw_lock_t) list;
00602 #ifdef UNIV_SYNC_DEBUG
00603   UT_LIST_BASE_NODE_T(rw_lock_debug_t) debug_list;
00606   ulint level;    
00607 #endif /* UNIV_SYNC_DEBUG */
00608 #ifdef UNIV_PFS_RWLOCK
00609   struct PSI_rwlock *pfs_psi;
00610 #endif
00611   ulint count_os_wait;  
00612   const char* cfile_name;
00613         /* last s-lock file/line is not guaranteed to be correct */
00614   const char* last_s_file_name;
00615   const char* last_x_file_name;
00616   ibool   writer_is_wait_ex;
00623   unsigned  cline:14; 
00624   unsigned  last_s_line:14; 
00625   unsigned  last_x_line:14; 
00626 #ifdef UNIV_DEBUG
00627   ulint magic_n;  
00629 #define RW_LOCK_MAGIC_N 22643
00630 #endif /* UNIV_DEBUG */
00631 };
00632 
00633 #ifdef UNIV_SYNC_DEBUG
00634 
00635 struct  rw_lock_debug_struct {
00636 
00637   os_thread_id_t thread_id;  
00639   ulint pass;   
00640   ulint lock_type;  
00642   const char* file_name;
00643   ulint line;   
00644   UT_LIST_NODE_T(rw_lock_debug_t) list;
00647 };
00648 #endif /* UNIV_SYNC_DEBUG */
00649 
00650 /* For performance schema instrumentation, a new set of rwlock
00651 wrap functions are created if "UNIV_PFS_RWLOCK" is defined.
00652 The instrumentations are not planted directly into original
00653 functions, so that we keep the underlying function as they
00654 are. And in case, user wants to "take out" some rwlock from
00655 instrumentation even if performance schema (UNIV_PFS_RWLOCK)
00656 is defined, they can do so by reinstating APIs directly link to
00657 original underlying functions.
00658 The instrumented function names have prefix of "pfs_rw_lock_" vs.
00659 original name prefix of "rw_lock_". Following are list of functions
00660 that have been instrumented:
00661 
00662 rw_lock_create()
00663 rw_lock_x_lock()
00664 rw_lock_x_lock_gen()
00665 rw_lock_x_lock_nowait()
00666 rw_lock_x_unlock_gen()
00667 rw_lock_s_lock()
00668 rw_lock_s_lock_gen()
00669 rw_lock_s_lock_nowait()
00670 rw_lock_s_unlock_gen()
00671 rw_lock_free()
00672 
00673 Two function APIs rw_lock_x_unlock_direct() and rw_lock_s_unlock_direct()
00674 do not have any caller/user, they are not instrumented.
00675 */
00676 
00677 #ifdef UNIV_PFS_RWLOCK
00678 /******************************************************************/
00682 UNIV_INLINE
00683 void
00684 pfs_rw_lock_create_func(
00685 /*====================*/
00686   PSI_rwlock_key  key,    
00688   rw_lock_t*  lock,   
00689 #ifdef UNIV_DEBUG
00690 # ifdef UNIV_SYNC_DEBUG
00691   ulint   level,    
00692 # endif /* UNIV_SYNC_DEBUG */
00693   const char* cmutex_name,  
00694 #endif /* UNIV_DEBUG */
00695   const char* cfile_name, 
00696   ulint   cline);   
00698 /******************************************************************/
00702 UNIV_INLINE
00703 void
00704 pfs_rw_lock_x_lock_func(
00705 /*====================*/
00706   rw_lock_t*  lock, 
00707   ulint   pass, 
00709   const char* file_name,
00710   ulint   line);  
00711 /******************************************************************/
00716 UNIV_INLINE
00717 ibool
00718 pfs_rw_lock_x_lock_func_nowait(
00719 /*===========================*/
00720   rw_lock_t*  lock, 
00721   const char* file_name,
00722   ulint   line);  
00723 /******************************************************************/
00727 UNIV_INLINE
00728 void
00729 pfs_rw_lock_s_lock_func(
00730 /*====================*/
00731   rw_lock_t*  lock, 
00732   ulint   pass, 
00734   const char* file_name,
00735   ulint   line);  
00736 /******************************************************************/
00741 UNIV_INLINE
00742 ibool
00743 pfs_rw_lock_s_lock_low(
00744 /*===================*/
00745   rw_lock_t*  lock, 
00746   ulint   pass, 
00749   const char* file_name, 
00750   ulint   line);  
00751 /******************************************************************/
00755 UNIV_INLINE
00756 void
00757 pfs_rw_lock_x_lock_func(
00758 /*====================*/
00759   rw_lock_t*  lock, 
00760   ulint   pass, 
00762   const char* file_name,
00763   ulint   line);  
00764 /******************************************************************/
00768 UNIV_INLINE
00769 void
00770 pfs_rw_lock_s_unlock_func(
00771 /*======================*/
00772 #ifdef UNIV_SYNC_DEBUG
00773   ulint   pass, 
00776 #endif
00777   rw_lock_t*  lock);  
00778 /******************************************************************/
00782 UNIV_INLINE
00783 void
00784 pfs_rw_lock_x_unlock_func(
00785 /*======================*/
00786 #ifdef UNIV_SYNC_DEBUG
00787   ulint   pass, 
00790 #endif
00791   rw_lock_t*  lock);  
00792 /******************************************************************/
00796 UNIV_INLINE
00797 void
00798 pfs_rw_lock_free_func(
00799 /*==================*/
00800   rw_lock_t*  lock);  
00801 #endif  /* UNIV_PFS_RWLOCK */
00802 
00803 
00804 #ifndef UNIV_NONINL
00805 #include "sync0rw.ic"
00806 #endif
00807 #endif /* !UNIV_HOTBACKUP */
00808 
00809 #endif