sync0rw.h
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:17k
- /******************************************************
- The read-write lock (for threads, not for database transactions)
- (c) 1995 Innobase Oy
- Created 9/11/1995 Heikki Tuuri
- *******************************************************/
- #ifndef sync0rw_h
- #define sync0rw_h
- #include "univ.i"
- #include "ut0lst.h"
- #include "sync0sync.h"
- #include "os0sync.h"
- /* The following undef is to prevent a name conflict with a macro
- in MySQL: */
- #undef rw_lock_t
- /* Latch types; these are used also in btr0btr.h: keep the numerical values
- smaller than 30 and the order of the numerical values like below! */
- #define RW_S_LATCH 1
- #define RW_X_LATCH 2
- #define RW_NO_LATCH 3
- typedef struct rw_lock_struct rw_lock_t;
- typedef struct rw_lock_debug_struct rw_lock_debug_t;
- typedef UT_LIST_BASE_NODE_T(rw_lock_t) rw_lock_list_t;
- extern rw_lock_list_t rw_lock_list;
- extern mutex_t rw_lock_list_mutex;
- /* The global mutex which protects debug info lists of all rw-locks.
- To modify the debug info list of an rw-lock, this mutex has to be
- acquired in addition to the mutex protecting the lock. */
- extern mutex_t rw_lock_debug_mutex;
- extern os_event_t rw_lock_debug_event; /* If deadlock detection does
- not get immediately the mutex it
- may wait for this event */
- extern ibool rw_lock_debug_waiters; /* This is set to TRUE, if
- there may be waiters for the event */
- extern ulint rw_s_system_call_count;
- extern ulint rw_s_spin_wait_count;
- extern ulint rw_s_exit_count;
- extern ulint rw_x_system_call_count;
- extern ulint rw_x_spin_wait_count;
- extern ulint rw_x_exit_count;
- /**********************************************************************
- Creates, or rather, initializes an rw-lock object in a specified memory
- location (which must be appropriately aligned). The rw-lock is initialized
- to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free
- is necessary only if the memory block containing it is freed. */
- #define rw_lock_create(L) rw_lock_create_func((L), IB__FILE__, __LINE__)
- /*=====================*/
- /**********************************************************************
- Creates, or rather, initializes an rw-lock object in a specified memory
- location (which must be appropriately aligned). The rw-lock is initialized
- to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free
- is necessary only if the memory block containing it is freed. */
- void
- rw_lock_create_func(
- /*================*/
- rw_lock_t* lock, /* in: pointer to memory */
- char* cfile_name, /* in: file name where created */
- ulint cline); /* in: file line where created */
- /**********************************************************************
- Calling this function is obligatory only if the memory buffer containing
- the rw-lock is freed. Removes an rw-lock object from the global list. The
- rw-lock is checked to be in the non-locked state. */
- void
- rw_lock_free(
- /*=========*/
- rw_lock_t* lock); /* in: rw-lock */
- /**********************************************************************
- Checks that the rw-lock has been initialized and that there are no
- simultaneous shared and exclusive locks. */
- ibool
- rw_lock_validate(
- /*=============*/
- rw_lock_t* lock);
- /******************************************************************
- NOTE! The following macros should be used in rw s-locking, not the
- corresponding function. */
- #ifdef UNIV_SYNC_DEBUG
- #define rw_lock_s_lock(M) rw_lock_s_lock_func(
- (M), 0, IB__FILE__, __LINE__)
- #else
- #define rw_lock_s_lock(M) rw_lock_s_lock_func(M)
- #endif
- /******************************************************************
- NOTE! The following macros should be used in rw s-locking, not the
- corresponding function. */
- #ifdef UNIV_SYNC_DEBUG
- #define rw_lock_s_lock_gen(M, P) rw_lock_s_lock_func(
- (M), (P), IB__FILE__, __LINE__)
- #else
- #define rw_lock_s_lock_gen(M, P) rw_lock_s_lock_func(M)
- #endif
- /******************************************************************
- NOTE! The following macros should be used in rw s-locking, not the
- corresponding function. */
- #ifdef UNIV_SYNC_DEBUG
- #define rw_lock_s_lock_nowait(M) rw_lock_s_lock_func_nowait(
- (M), IB__FILE__, __LINE__)
- #else
- #define rw_lock_s_lock_nowait(M) rw_lock_s_lock_func_nowait(M)
- #endif
- /**********************************************************************
- NOTE! Use the corresponding macro, not directly this function, except if
- you supply the file name and line number. Lock an rw-lock in shared mode
- for the current thread. If the rw-lock is locked in exclusive mode, or
- there is an exclusive lock request waiting, the function spins a preset
- time (controlled by SYNC_SPIN_ROUNDS), waiting for the lock, before
- suspending the thread. */
- UNIV_INLINE
- void
- rw_lock_s_lock_func(
- /*================*/
- rw_lock_t* lock /* in: pointer to rw-lock */
- #ifdef UNIV_SYNC_DEBUG
- ,ulint pass, /* in: pass value; != 0, if the lock will
- be passed to another thread to unlock */
- char* file_name, /* in: file name where lock requested */
- ulint line /* in: line where requested */
- #endif
- );
- /**********************************************************************
- NOTE! Use the corresponding macro, not directly this function, except if
- you supply the file name and line number. Lock an rw-lock in shared mode
- for the current thread if the lock can be acquired immediately. */
- UNIV_INLINE
- ibool
- rw_lock_s_lock_func_nowait(
- /*=======================*/
- /* out: TRUE if success */
- rw_lock_t* lock /* in: pointer to rw-lock */
- #ifdef UNIV_SYNC_DEBUG
- ,char* file_name, /* in: file name where lock requested */
- ulint line /* in: line where requested */
- #endif
- );
- /**********************************************************************
- NOTE! Use the corresponding macro, not directly this function! Lock an
- rw-lock in exclusive mode for the current thread if the lock can be
- obtained immediately. */
- UNIV_INLINE
- ibool
- rw_lock_x_lock_func_nowait(
- /*=======================*/
- /* out: TRUE if success */
- rw_lock_t* lock /* in: pointer to rw-lock */
- #ifdef UNIV_SYNC_DEBUG
- ,char* file_name, /* in: file name where lock requested */
- ulint line /* in: line where requested */
- #endif
- );
- /**********************************************************************
- Releases a shared mode lock. */
- UNIV_INLINE
- void
- rw_lock_s_unlock_func(
- /*==================*/
- rw_lock_t* lock /* in: rw-lock */
- #ifdef UNIV_SYNC_DEBUG
- ,ulint pass /* in: pass value; != 0, if the lock may have
- been passed to another thread to unlock */
- #endif
- );
- /***********************************************************************
- Releases a shared mode lock. */
- #ifdef UNIV_SYNC_DEBUG
- #define rw_lock_s_unlock(L) rw_lock_s_unlock_func(L, 0)
- #else
- #define rw_lock_s_unlock(L) rw_lock_s_unlock_func(L)
- #endif
- /***********************************************************************
- Releases a shared mode lock. */
- #ifdef UNIV_SYNC_DEBUG
- #define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(L, P)
- #else
- #define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(L)
- #endif
- /******************************************************************
- NOTE! The following macro should be used in rw x-locking, not the
- corresponding function. */
- #ifdef UNIV_SYNC_DEBUG
- #define rw_lock_x_lock(M) rw_lock_x_lock_func(
- (M), 0, IB__FILE__, __LINE__)
- #else
- #define rw_lock_x_lock(M) rw_lock_x_lock_func(M, 0)
- #endif
- /******************************************************************
- NOTE! The following macro should be used in rw x-locking, not the
- corresponding function. */
- #ifdef UNIV_SYNC_DEBUG
- #define rw_lock_x_lock_gen(M, P) rw_lock_x_lock_func(
- (M), (P), IB__FILE__, __LINE__)
- #else
- #define rw_lock_x_lock_gen(M, P) rw_lock_x_lock_func(M, P)
- #endif
- /******************************************************************
- NOTE! The following macros should be used in rw x-locking, not the
- corresponding function. */
- #ifdef UNIV_SYNC_DEBUG
- #define rw_lock_x_lock_nowait(M) rw_lock_x_lock_func_nowait(
- (M), IB__FILE__, __LINE__)
- #else
- #define rw_lock_x_lock_nowait(M) rw_lock_x_lock_func_nowait(M)
- #endif
- /**********************************************************************
- NOTE! Use the corresponding macro, not directly this function! Lock an
- rw-lock in exclusive mode for the current thread. If the rw-lock is locked
- in shared or exclusive mode, or there is an exclusive lock request waiting,
- the function spins a preset time (controlled by SYNC_SPIN_ROUNDS), waiting
- for the lock, before suspending the thread. If the same thread has an x-lock
- on the rw-lock, locking succeed, with the following exception: if pass != 0,
- only a single x-lock may be taken on the lock. NOTE: If the same thread has
- an s-lock, locking does not succeed! */
- void
- rw_lock_x_lock_func(
- /*================*/
- rw_lock_t* lock, /* in: pointer to rw-lock */
- ulint pass /* in: pass value; != 0, if the lock will
- be passed to another thread to unlock */
- #ifdef UNIV_SYNC_DEBUG
- ,char* file_name, /* in: file name where lock requested */
- ulint line /* in: line where requested */
- #endif
- );
- /**********************************************************************
- Releases an exclusive mode lock. */
- UNIV_INLINE
- void
- rw_lock_x_unlock_func(
- /*==================*/
- rw_lock_t* lock /* in: rw-lock */
- #ifdef UNIV_SYNC_DEBUG
- ,ulint pass /* in: pass value; != 0, if the lock may have
- been passed to another thread to unlock */
- #endif
- );
- /***********************************************************************
- Releases an exclusive mode lock. */
- #ifdef UNIV_SYNC_DEBUG
- #define rw_lock_x_unlock(L) rw_lock_x_unlock_func(L, 0)
- #else
- #define rw_lock_x_unlock(L) rw_lock_x_unlock_func(L)
- #endif
- /***********************************************************************
- Releases an exclusive mode lock. */
- #ifdef UNIV_SYNC_DEBUG
- #define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(L, P)
- #else
- #define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(L)
- #endif
- /**********************************************************************
- Low-level function which locks an rw-lock in s-mode when we know that it
- is possible and none else is currently accessing the rw-lock structure.
- Then we can do the locking without reserving the mutex. */
- UNIV_INLINE
- void
- rw_lock_s_lock_direct(
- /*==================*/
- rw_lock_t* lock /* in: pointer to rw-lock */
- #ifdef UNIV_SYNC_DEBUG
- ,char* file_name, /* in: file name where lock requested */
- ulint line /* in: line where requested */
- #endif
- );
- /**********************************************************************
- Low-level function which locks an rw-lock in x-mode when we know that it
- is not locked and none else is currently accessing the rw-lock structure.
- Then we can do the locking without reserving the mutex. */
- UNIV_INLINE
- void
- rw_lock_x_lock_direct(
- /*==================*/
- rw_lock_t* lock /* in: pointer to rw-lock */
- #ifdef UNIV_SYNC_DEBUG
- ,char* file_name, /* in: file name where lock requested */
- ulint line /* in: line where requested */
- #endif
- );
- /**********************************************************************
- This function is used in the insert buffer to move the ownership of an
- x-latch on a buffer frame to the current thread. The x-latch was set by
- the buffer read operation and it protected the buffer frame while the
- read was done. The ownership is moved because we want that the current
- thread is able to acquire a second x-latch which is stored in an mtr.
- This, in turn, is needed to pass the debug checks of index page
- operations. */
- void
- rw_lock_x_lock_move_ownership(
- /*==========================*/
- rw_lock_t* lock); /* in: lock which was x-locked in the
- buffer read */
- /**********************************************************************
- Releases a shared mode lock when we know there are no waiters and none
- else will access the lock during the time this function is executed. */
- UNIV_INLINE
- void
- rw_lock_s_unlock_direct(
- /*====================*/
- rw_lock_t* lock); /* in: rw-lock */
- /**********************************************************************
- Releases an exclusive mode lock when we know there are no waiters, and
- none else will access the lock durint the time this function is executed. */
- UNIV_INLINE
- void
- rw_lock_x_unlock_direct(
- /*====================*/
- rw_lock_t* lock); /* in: rw-lock */
- /**********************************************************************
- Sets the rw-lock latching level field. */
- void
- rw_lock_set_level(
- /*==============*/
- rw_lock_t* lock, /* in: rw-lock */
- ulint level); /* in: level */
- /**********************************************************************
- Returns the value of writer_count for the lock. Does not reserve the lock
- mutex, so the caller must be sure it is not changed during the call. */
- UNIV_INLINE
- ulint
- rw_lock_get_x_lock_count(
- /*=====================*/
- /* out: value of writer_count */
- rw_lock_t* lock); /* in: rw-lock */
- /**********************************************************************
- Checks if the thread has locked the rw-lock in the specified mode, with
- the pass value == 0. */
- ibool
- rw_lock_own(
- /*========*/
- rw_lock_t* lock, /* in: rw-lock */
- ulint lock_type); /* in: lock type */
- /**********************************************************************
- Checks if somebody has locked the rw-lock in the specified mode. */
- ibool
- rw_lock_is_locked(
- /*==============*/
- rw_lock_t* lock, /* in: rw-lock */
- ulint lock_type); /* in: lock type: RW_LOCK_SHARED,
- RW_LOCK_EX */
- /*******************************************************************
- Prints debug info of an rw-lock. */
- void
- rw_lock_print(
- /*==========*/
- rw_lock_t* lock); /* in: rw-lock */
- /*******************************************************************
- Prints debug info of currently locked rw-locks. */
- void
- rw_lock_list_print_info(void);
- /*=========================*/
- /*******************************************************************
- Returns the number of currently locked rw-locks.
- Works only in the debug version. */
- ulint
- rw_lock_n_locked(void);
- /*==================*/
- /*#####################################################################*/
- /**********************************************************************
- Acquires the debug mutex. We cannot use the mutex defined in sync0sync,
- because the debug mutex is also acquired in sync0arr while holding the OS
- mutex protecting the sync array, and the ordinary mutex_enter might
- recursively call routines in sync0arr, leading to a deadlock on the OS
- mutex. */
- void
- rw_lock_debug_mutex_enter(void);
- /*==========================*/
- /**********************************************************************
- Releases the debug mutex. */
- void
- rw_lock_debug_mutex_exit(void);
- /*==========================*/
- /*************************************************************************
- Prints info of a debug struct. */
- void
- rw_lock_debug_print(
- /*================*/
- rw_lock_debug_t* info); /* in: debug struct */
- #define RW_CNAME_LEN 8
- /* NOTE! The structure appears here only for the compiler to know its size.
- Do not use its fields directly! The structure used in the spin lock
- implementation of a read-write lock. Several threads may have a shared lock
- simultaneously in this lock, but only one writer may have an exclusive lock,
- in which case no shared locks are allowed. To prevent starving of a writer
- blocked by readers, a writer may queue for the lock by setting the writer
- field. Then no new readers are allowed in. */
- struct rw_lock_struct {
- ulint reader_count; /* Number of readers who have locked this
- lock in the shared mode */
- ulint writer; /* This field is set to RW_LOCK_EX if there
- is a writer owning the lock (in exclusive
- mode), RW_LOCK_WAIT_EX if a writer is
- queueing for the lock, and
- RW_LOCK_NOT_LOCKED, otherwise. */
- os_thread_id_t writer_thread;
- /* Thread id of a possible writer thread */
- ulint writer_count; /* Number of times the same thread has
- recursively locked the lock in the exclusive
- mode */
- mutex_t mutex; /* The mutex protecting rw_lock_struct */
- ulint pass; /* Default value 0. This is set to some
- value != 0 given by the caller of an x-lock
- operation, if the x-lock is to be passed to
- another thread to unlock (which happens in
- asynchronous i/o). */
- ulint waiters; /* This ulint is set to 1 if there are
- waiters (readers or writers) in the global
- wait array, waiting for this rw_lock.
- Otherwise, = 0. */
- ibool writer_is_wait_ex;
- /* This is TRUE if the writer field is
- RW_LOCK_WAIT_EX; this field is located far
- from the memory update hotspot fields which
- are at the start of this struct, thus we can
- peek this field without causing much memory
- bus traffic */
- UT_LIST_NODE_T(rw_lock_t) list;
- /* All allocated rw locks are put into a
- list */
- UT_LIST_BASE_NODE_T(rw_lock_debug_t) debug_list;
- /* In the debug version: pointer to the debug
- info list of the lock */
- ulint level; /* Debug version: level in the global latching
- order; default SYNC_LEVEL_NONE */
- char cfile_name[RW_CNAME_LEN];
- /* File name where lock created */
- ulint cline; /* Line where created */
- ulint magic_n;
- };
- #define RW_LOCK_MAGIC_N 22643
- /* The structure for storing debug info of an rw-lock */
- struct rw_lock_debug_struct {
- os_thread_id_t thread_id; /* The thread id of the thread which
- locked the rw-lock */
- ulint pass; /* Pass value given in the lock operation */
- ulint lock_type; /* Type of the lock: RW_LOCK_EX,
- RW_LOCK_SHARED, RW_LOCK_WAIT_EX */
- char* file_name; /* File name where the lock was obtained */
- ulint line; /* Line where the rw-lock was locked */
- UT_LIST_NODE_T(rw_lock_debug_t) list;
- /* Debug structs are linked in a two-way
- list */
- };
- #ifndef UNIV_NONINL
- #include "sync0rw.ic"
- #endif
- #endif