mirror of
https://github.com/MariaDB/server.git
synced 2025-11-28 17:36:30 +03:00
real sync with patches rev12
This commit is contained in:
@@ -3595,13 +3595,15 @@ buf_print_io(
|
|||||||
buf_pool_mutex_enter();
|
buf_pool_mutex_enter();
|
||||||
|
|
||||||
fprintf(file,
|
fprintf(file,
|
||||||
"Buffer pool size %lu\n"
|
"Buffer pool size %lu\n"
|
||||||
"Free buffers %lu\n"
|
"Buffer pool size, bytes %lu\n"
|
||||||
"Database pages %lu\n"
|
"Free buffers %lu\n"
|
||||||
"Modified db pages %lu\n"
|
"Database pages %lu\n"
|
||||||
|
"Modified db pages %lu\n"
|
||||||
"Pending reads %lu\n"
|
"Pending reads %lu\n"
|
||||||
"Pending writes: LRU %lu, flush list %lu, single page %lu\n",
|
"Pending writes: LRU %lu, flush list %lu, single page %lu\n",
|
||||||
(ulong) size,
|
(ulong) size,
|
||||||
|
(ulong) size * UNIV_PAGE_SIZE,
|
||||||
(ulong) UT_LIST_GET_LEN(buf_pool->free),
|
(ulong) UT_LIST_GET_LEN(buf_pool->free),
|
||||||
(ulong) UT_LIST_GET_LEN(buf_pool->LRU),
|
(ulong) UT_LIST_GET_LEN(buf_pool->LRU),
|
||||||
(ulong) UT_LIST_GET_LEN(buf_pool->flush_list),
|
(ulong) UT_LIST_GET_LEN(buf_pool->flush_list),
|
||||||
|
|||||||
@@ -187,6 +187,10 @@ buf_read_ahead_random(
|
|||||||
ulint i;
|
ulint i;
|
||||||
ulint buf_read_ahead_random_area;
|
ulint buf_read_ahead_random_area;
|
||||||
|
|
||||||
|
if (!(srv_read_ahead & 1)) {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
if (srv_startup_is_before_trx_rollback_phase) {
|
if (srv_startup_is_before_trx_rollback_phase) {
|
||||||
/* No read-ahead to avoid thread deadlocks */
|
/* No read-ahead to avoid thread deadlocks */
|
||||||
return(0);
|
return(0);
|
||||||
@@ -412,6 +416,10 @@ buf_read_ahead_linear(
|
|||||||
const ulint buf_read_ahead_linear_area
|
const ulint buf_read_ahead_linear_area
|
||||||
= BUF_READ_AHEAD_LINEAR_AREA;
|
= BUF_READ_AHEAD_LINEAR_AREA;
|
||||||
|
|
||||||
|
if (!(srv_read_ahead & 2)) {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(srv_startup_is_before_trx_rollback_phase)) {
|
if (UNIV_UNLIKELY(srv_startup_is_before_trx_rollback_phase)) {
|
||||||
/* No read-ahead to avoid thread deadlocks */
|
/* No read-ahead to avoid thread deadlocks */
|
||||||
return(0);
|
return(0);
|
||||||
|
|||||||
@@ -4816,3 +4816,30 @@ fil_page_get_type(
|
|||||||
|
|
||||||
return(mach_read_from_2(page + FIL_PAGE_TYPE));
|
return(mach_read_from_2(page + FIL_PAGE_TYPE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Return local hash table informations. */
|
||||||
|
|
||||||
|
ulint
|
||||||
|
fil_system_hash_cells(void)
|
||||||
|
/*=======================*/
|
||||||
|
{
|
||||||
|
if (fil_system) {
|
||||||
|
return (fil_system->spaces->n_cells
|
||||||
|
+ fil_system->name_hash->n_cells);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ulint
|
||||||
|
fil_system_hash_nodes(void)
|
||||||
|
/*=======================*/
|
||||||
|
{
|
||||||
|
if (fil_system) {
|
||||||
|
return (UT_LIST_GET_LEN(fil_system->space_list)
|
||||||
|
* (sizeof(fil_space_t) + MEM_BLOCK_HEADER_SIZE));
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ static long innobase_mirrored_log_groups, innobase_log_files_in_group,
|
|||||||
innobase_force_recovery, innobase_open_files,
|
innobase_force_recovery, innobase_open_files,
|
||||||
innobase_autoinc_lock_mode;
|
innobase_autoinc_lock_mode;
|
||||||
|
|
||||||
|
static unsigned long innobase_read_io_threads, innobase_write_io_threads;
|
||||||
static long long innobase_buffer_pool_size, innobase_log_file_size;
|
static long long innobase_buffer_pool_size, innobase_log_file_size;
|
||||||
|
|
||||||
/* The default values for the following char* start-up parameters
|
/* The default values for the following char* start-up parameters
|
||||||
@@ -2066,6 +2067,8 @@ innobase_init(
|
|||||||
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
|
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
|
||||||
|
|
||||||
srv_n_file_io_threads = (ulint) innobase_file_io_threads;
|
srv_n_file_io_threads = (ulint) innobase_file_io_threads;
|
||||||
|
srv_n_read_io_threads = (ulint) innobase_read_io_threads;
|
||||||
|
srv_n_write_io_threads = (ulint) innobase_write_io_threads;
|
||||||
|
|
||||||
srv_force_recovery = (ulint) innobase_force_recovery;
|
srv_force_recovery = (ulint) innobase_force_recovery;
|
||||||
|
|
||||||
@@ -9406,6 +9409,16 @@ static MYSQL_SYSVAR_BOOL(locks_unsafe_for_binlog, innobase_locks_unsafe_for_binl
|
|||||||
"Force InnoDB to not use next-key locking, to use only row-level locking.",
|
"Force InnoDB to not use next-key locking, to use only row-level locking.",
|
||||||
NULL, NULL, FALSE);
|
NULL, NULL, FALSE);
|
||||||
|
|
||||||
|
static MYSQL_SYSVAR_ULONG(show_verbose_locks, srv_show_verbose_locks,
|
||||||
|
PLUGIN_VAR_OPCMDARG,
|
||||||
|
"Whether to show records locked in SHOW INNODB STATUS.",
|
||||||
|
NULL, NULL, 0, 0, 1, 0);
|
||||||
|
|
||||||
|
static MYSQL_SYSVAR_ULONG(show_locks_held, srv_show_locks_held,
|
||||||
|
PLUGIN_VAR_RQCMDARG,
|
||||||
|
"Number of locks held to print for each InnoDB transaction in SHOW INNODB STATUS.",
|
||||||
|
NULL, NULL, 10, 0, 1000, 0);
|
||||||
|
|
||||||
#ifdef UNIV_LOG_ARCHIVE
|
#ifdef UNIV_LOG_ARCHIVE
|
||||||
static MYSQL_SYSVAR_STR(log_arch_dir, innobase_log_arch_dir,
|
static MYSQL_SYSVAR_STR(log_arch_dir, innobase_log_arch_dir,
|
||||||
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
||||||
@@ -9556,7 +9569,32 @@ static MYSQL_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode,
|
|||||||
|
|
||||||
static MYSQL_SYSVAR_STR(version, innodb_version_str,
|
static MYSQL_SYSVAR_STR(version, innodb_version_str,
|
||||||
PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY,
|
PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY,
|
||||||
"InnoDB version", NULL, NULL, INNODB_VERSION_STR);
|
"Percona-InnoDB-plugin version", NULL, NULL, INNODB_VERSION_STR);
|
||||||
|
|
||||||
|
static MYSQL_SYSVAR_ULONG(io_capacity, srv_io_capacity,
|
||||||
|
PLUGIN_VAR_RQCMDARG,
|
||||||
|
"Number of IO operations per second the server can do. Tunes background IO rate.",
|
||||||
|
NULL, NULL, 100, 100, 999999999, 0);
|
||||||
|
|
||||||
|
static MYSQL_SYSVAR_ULONG(read_ahead, srv_read_ahead,
|
||||||
|
PLUGIN_VAR_RQCMDARG,
|
||||||
|
"Enable/Diasable read aheads bit0:random bit1:linear",
|
||||||
|
NULL, NULL, 3, 0, 3, 0);
|
||||||
|
|
||||||
|
static MYSQL_SYSVAR_ULONG(adaptive_checkpoint, srv_adaptive_checkpoint,
|
||||||
|
PLUGIN_VAR_RQCMDARG,
|
||||||
|
"Enable/Disable flushing along modified age 0:disable 1:enable",
|
||||||
|
NULL, NULL, 0, 0, 1, 0);
|
||||||
|
|
||||||
|
static MYSQL_SYSVAR_ULONG(read_io_threads, innobase_read_io_threads,
|
||||||
|
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
||||||
|
"Number of background read I/O threads in InnoDB.",
|
||||||
|
NULL, NULL, 1, 1, 64, 0);
|
||||||
|
|
||||||
|
static MYSQL_SYSVAR_ULONG(write_io_threads, innobase_write_io_threads,
|
||||||
|
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
||||||
|
"Number of background write I/O threads in InnoDB.",
|
||||||
|
NULL, NULL, 1, 1, 64, 0);
|
||||||
|
|
||||||
static struct st_mysql_sys_var* innobase_system_variables[]= {
|
static struct st_mysql_sys_var* innobase_system_variables[]= {
|
||||||
MYSQL_SYSVAR(additional_mem_pool_size),
|
MYSQL_SYSVAR(additional_mem_pool_size),
|
||||||
@@ -9603,7 +9641,14 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
|
|||||||
MYSQL_SYSVAR(thread_concurrency),
|
MYSQL_SYSVAR(thread_concurrency),
|
||||||
MYSQL_SYSVAR(thread_sleep_delay),
|
MYSQL_SYSVAR(thread_sleep_delay),
|
||||||
MYSQL_SYSVAR(autoinc_lock_mode),
|
MYSQL_SYSVAR(autoinc_lock_mode),
|
||||||
|
MYSQL_SYSVAR(show_verbose_locks),
|
||||||
|
MYSQL_SYSVAR(show_locks_held),
|
||||||
MYSQL_SYSVAR(version),
|
MYSQL_SYSVAR(version),
|
||||||
|
MYSQL_SYSVAR(io_capacity),
|
||||||
|
MYSQL_SYSVAR(read_ahead),
|
||||||
|
MYSQL_SYSVAR(adaptive_checkpoint),
|
||||||
|
MYSQL_SYSVAR(read_io_threads),
|
||||||
|
MYSQL_SYSVAR(write_io_threads),
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -24,5 +24,8 @@ struct innodb_enhancement {
|
|||||||
const char *link;
|
const char *link;
|
||||||
}innodb_enhancements[] = {
|
}innodb_enhancements[] = {
|
||||||
{"innodb_show_enhancements","I_S.PERCONA_INNODB_ENHANCEMENTS","","http://www.percona.com/docs/wiki/percona-innodb-plugin:innodb_show_enhancements"},
|
{"innodb_show_enhancements","I_S.PERCONA_INNODB_ENHANCEMENTS","","http://www.percona.com/docs/wiki/percona-innodb-plugin:innodb_show_enhancements"},
|
||||||
{NULL, NULL, NULL, NULL, NULL, NULL}
|
{"innodb_show_status","Improvements to SHOW INNODB STATUS","Memory information and lock info fixes","http://www.percona.com/docs/wiki/percona-innodb-plugin:innodb_show_status"},
|
||||||
|
{"innodb_io","Improvements to InnoDB IO","","http://www.percona.com/docs/wiki/percona-innodb-plugin:innodb_io"},
|
||||||
|
{"innodb_rw_lock","InnoDB RW-lock fixes","Useful for 8+ cores SMP systems","http://www.percona.com/docs/wiki/percona-innodb-plugin:innodb_rw_lock"},
|
||||||
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -696,6 +696,16 @@ fil_page_get_type(
|
|||||||
return value not defined */
|
return value not defined */
|
||||||
const byte* page); /* in: file page */
|
const byte* page); /* in: file page */
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Return local hash table informations. */
|
||||||
|
|
||||||
|
ulint
|
||||||
|
fil_system_hash_cells(void);
|
||||||
|
/*========================*/
|
||||||
|
|
||||||
|
ulint
|
||||||
|
fil_system_hash_nodes(void);
|
||||||
|
/*========================*/
|
||||||
|
|
||||||
typedef struct fil_space_struct fil_space_t;
|
typedef struct fil_space_struct fil_space_t;
|
||||||
|
|
||||||
|
|||||||
@@ -561,8 +561,10 @@ os_aio_init(
|
|||||||
/*========*/
|
/*========*/
|
||||||
ulint n, /* in: maximum number of pending aio operations
|
ulint n, /* in: maximum number of pending aio operations
|
||||||
allowed; n must be divisible by n_segments */
|
allowed; n must be divisible by n_segments */
|
||||||
ulint n_segments, /* in: combined number of segments in the four
|
// ulint n_segments, /* in: combined number of segments in the four
|
||||||
first aio arrays; must be >= 4 */
|
// first aio arrays; must be >= 4 */
|
||||||
|
ulint n_read_threads, /* n_segments == 2 + n_read_threads + n_write_threads */
|
||||||
|
ulint n_write_threads, /**/
|
||||||
ulint n_slots_sync); /* in: number of slots in the sync aio array */
|
ulint n_slots_sync); /* in: number of slots in the sync aio array */
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
Requests an asynchronous i/o operation. */
|
Requests an asynchronous i/o operation. */
|
||||||
|
|||||||
@@ -90,6 +90,9 @@ extern ulint srv_log_file_size;
|
|||||||
extern ulint srv_log_buffer_size;
|
extern ulint srv_log_buffer_size;
|
||||||
extern ulong srv_flush_log_at_trx_commit;
|
extern ulong srv_flush_log_at_trx_commit;
|
||||||
|
|
||||||
|
extern ulint srv_show_locks_held;
|
||||||
|
extern ulint srv_show_verbose_locks;
|
||||||
|
|
||||||
/* The sort order table of the MySQL latin1_swedish_ci character set
|
/* The sort order table of the MySQL latin1_swedish_ci character set
|
||||||
collation */
|
collation */
|
||||||
extern const byte* srv_latin1_ordering;
|
extern const byte* srv_latin1_ordering;
|
||||||
@@ -100,6 +103,8 @@ extern ulint srv_mem_pool_size;
|
|||||||
extern ulint srv_lock_table_size;
|
extern ulint srv_lock_table_size;
|
||||||
|
|
||||||
extern ulint srv_n_file_io_threads;
|
extern ulint srv_n_file_io_threads;
|
||||||
|
extern ulint srv_n_read_io_threads;
|
||||||
|
extern ulint srv_n_write_io_threads;
|
||||||
|
|
||||||
#ifdef UNIV_LOG_ARCHIVE
|
#ifdef UNIV_LOG_ARCHIVE
|
||||||
extern ibool srv_log_archive_on;
|
extern ibool srv_log_archive_on;
|
||||||
@@ -144,6 +149,11 @@ extern ulong srv_max_buf_pool_modified_pct;
|
|||||||
extern ulong srv_max_purge_lag;
|
extern ulong srv_max_purge_lag;
|
||||||
|
|
||||||
extern ulong srv_replication_delay;
|
extern ulong srv_replication_delay;
|
||||||
|
|
||||||
|
extern ulint srv_io_capacity;
|
||||||
|
extern ulint srv_read_ahead;
|
||||||
|
extern ulint srv_adaptive_checkpoint;
|
||||||
|
|
||||||
/*-------------------------------------------*/
|
/*-------------------------------------------*/
|
||||||
|
|
||||||
extern ulint srv_n_rows_inserted;
|
extern ulint srv_n_rows_inserted;
|
||||||
|
|||||||
@@ -328,7 +328,17 @@ rw_lock_get_x_lock_count(
|
|||||||
Accessor functions for rw lock. */
|
Accessor functions for rw lock. */
|
||||||
UNIV_INLINE
|
UNIV_INLINE
|
||||||
ulint
|
ulint
|
||||||
rw_lock_get_waiters(
|
rw_lock_get_s_waiters(
|
||||||
|
/*==================*/
|
||||||
|
rw_lock_t* lock);
|
||||||
|
UNIV_INLINE
|
||||||
|
ulint
|
||||||
|
rw_lock_get_x_waiters(
|
||||||
|
/*==================*/
|
||||||
|
rw_lock_t* lock);
|
||||||
|
UNIV_INLINE
|
||||||
|
ulint
|
||||||
|
rw_lock_get_wx_waiters(
|
||||||
/*================*/
|
/*================*/
|
||||||
rw_lock_t* lock);
|
rw_lock_t* lock);
|
||||||
UNIV_INLINE
|
UNIV_INLINE
|
||||||
@@ -412,6 +422,11 @@ rw_lock_debug_print(
|
|||||||
rw_lock_debug_t* info); /* in: debug struct */
|
rw_lock_debug_t* info); /* in: debug struct */
|
||||||
#endif /* UNIV_SYNC_DEBUG */
|
#endif /* UNIV_SYNC_DEBUG */
|
||||||
|
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
/* This value means NOT_LOCKED */
|
||||||
|
#define RW_LOCK_BIAS 0x00100000
|
||||||
|
#endif
|
||||||
|
|
||||||
/* NOTE! The structure appears here only for the compiler to know its size.
|
/* 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
|
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
|
implementation of a read-write lock. Several threads may have a shared lock
|
||||||
@@ -421,9 +436,9 @@ blocked by readers, a writer may queue for the lock by setting the writer
|
|||||||
field. Then no new readers are allowed in. */
|
field. Then no new readers are allowed in. */
|
||||||
|
|
||||||
struct rw_lock_struct {
|
struct rw_lock_struct {
|
||||||
os_event_t event; /* Used by sync0arr.c for thread queueing */
|
/* Used by sync0arr.c for thread queueing */
|
||||||
|
os_event_t s_event; /* Used for s_lock */
|
||||||
#ifdef __WIN__
|
os_event_t x_event; /* Used for x_lock */
|
||||||
os_event_t wait_ex_event; /* This windows specific event is
|
os_event_t wait_ex_event; /* This windows specific event is
|
||||||
used by the thread which has set the
|
used by the thread which has set the
|
||||||
lock state to RW_LOCK_WAIT_EX. The
|
lock state to RW_LOCK_WAIT_EX. The
|
||||||
@@ -431,30 +446,34 @@ struct rw_lock_struct {
|
|||||||
thread will be the next one to proceed
|
thread will be the next one to proceed
|
||||||
once the current the event gets
|
once the current the event gets
|
||||||
signalled. See LEMMA 2 in sync0sync.c */
|
signalled. See LEMMA 2 in sync0sync.c */
|
||||||
|
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
volatile lint lock_word; /* Used by using atomic builtin */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ulint reader_count; /* Number of readers who have locked this
|
volatile ulint reader_count; /* Number of readers who have locked this
|
||||||
lock in the shared mode */
|
lock in the shared mode */
|
||||||
ulint writer; /* This field is set to RW_LOCK_EX if there
|
volatile ulint writer; /* This field is set to RW_LOCK_EX if there
|
||||||
is a writer owning the lock (in exclusive
|
is a writer owning the lock (in exclusive
|
||||||
mode), RW_LOCK_WAIT_EX if a writer is
|
mode), RW_LOCK_WAIT_EX if a writer is
|
||||||
queueing for the lock, and
|
queueing for the lock, and
|
||||||
RW_LOCK_NOT_LOCKED, otherwise. */
|
RW_LOCK_NOT_LOCKED, otherwise. */
|
||||||
os_thread_id_t writer_thread;
|
volatile os_thread_id_t writer_thread;
|
||||||
/* Thread id of a possible writer thread */
|
/* Thread id of a possible writer thread */
|
||||||
ulint writer_count; /* Number of times the same thread has
|
volatile ulint writer_count; /* Number of times the same thread has
|
||||||
recursively locked the lock in the exclusive
|
recursively locked the lock in the exclusive
|
||||||
mode */
|
mode */
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_t mutex; /* The mutex protecting rw_lock_struct */
|
mutex_t mutex; /* The mutex protecting rw_lock_struct */
|
||||||
|
#endif
|
||||||
ulint pass; /* Default value 0. This is set to some
|
ulint pass; /* Default value 0. This is set to some
|
||||||
value != 0 given by the caller of an x-lock
|
value != 0 given by the caller of an x-lock
|
||||||
operation, if the x-lock is to be passed to
|
operation, if the x-lock is to be passed to
|
||||||
another thread to unlock (which happens in
|
another thread to unlock (which happens in
|
||||||
asynchronous i/o). */
|
asynchronous i/o). */
|
||||||
ulint waiters; /* This ulint is set to 1 if there are
|
volatile ulint s_waiters; /* 1: there are waiters (s_lock) */
|
||||||
waiters (readers or writers) in the global
|
volatile ulint x_waiters; /* 1: there are waiters (x_lock) */
|
||||||
wait array, waiting for this rw_lock.
|
volatile ulint wait_ex_waiters; /* 1: there are waiters (wait_ex) */
|
||||||
Otherwise, == 0. */
|
|
||||||
UT_LIST_NODE_T(rw_lock_t) list;
|
UT_LIST_NODE_T(rw_lock_t) list;
|
||||||
/* All allocated rw locks are put into a
|
/* All allocated rw locks are put into a
|
||||||
list */
|
list */
|
||||||
@@ -467,7 +486,7 @@ struct rw_lock_struct {
|
|||||||
const char* cfile_name;/* File name where lock created */
|
const char* cfile_name;/* File name where lock created */
|
||||||
const char* last_s_file_name;/* File name where last s-locked */
|
const char* last_s_file_name;/* File name where last s-locked */
|
||||||
const char* last_x_file_name;/* File name where last x-locked */
|
const char* last_x_file_name;/* File name where last x-locked */
|
||||||
ibool writer_is_wait_ex;
|
volatile ibool writer_is_wait_ex;
|
||||||
/* This is TRUE if the writer field is
|
/* This is TRUE if the writer field is
|
||||||
RW_LOCK_WAIT_EX; this field is located far
|
RW_LOCK_WAIT_EX; this field is located far
|
||||||
from the memory update hotspot fields which
|
from the memory update hotspot fields which
|
||||||
|
|||||||
@@ -47,20 +47,52 @@ rw_lock_remove_debug_info(
|
|||||||
Accessor functions for rw lock. */
|
Accessor functions for rw lock. */
|
||||||
UNIV_INLINE
|
UNIV_INLINE
|
||||||
ulint
|
ulint
|
||||||
rw_lock_get_waiters(
|
rw_lock_get_s_waiters(
|
||||||
/*================*/
|
/*================*/
|
||||||
rw_lock_t* lock)
|
rw_lock_t* lock)
|
||||||
{
|
{
|
||||||
return(lock->waiters);
|
return(lock->s_waiters);
|
||||||
|
}
|
||||||
|
UNIV_INLINE
|
||||||
|
ulint
|
||||||
|
rw_lock_get_x_waiters(
|
||||||
|
/*================*/
|
||||||
|
rw_lock_t* lock)
|
||||||
|
{
|
||||||
|
return(lock->x_waiters);
|
||||||
|
}
|
||||||
|
UNIV_INLINE
|
||||||
|
ulint
|
||||||
|
rw_lock_get_wx_waiters(
|
||||||
|
/*================*/
|
||||||
|
rw_lock_t* lock)
|
||||||
|
{
|
||||||
|
return(lock->wait_ex_waiters);
|
||||||
}
|
}
|
||||||
UNIV_INLINE
|
UNIV_INLINE
|
||||||
void
|
void
|
||||||
rw_lock_set_waiters(
|
rw_lock_set_s_waiters(
|
||||||
/*================*/
|
|
||||||
rw_lock_t* lock,
|
rw_lock_t* lock,
|
||||||
ulint flag)
|
ulint flag)
|
||||||
{
|
{
|
||||||
lock->waiters = flag;
|
lock->s_waiters = flag;
|
||||||
|
}
|
||||||
|
UNIV_INLINE
|
||||||
|
void
|
||||||
|
rw_lock_set_x_waiters(
|
||||||
|
rw_lock_t* lock,
|
||||||
|
ulint flag)
|
||||||
|
{
|
||||||
|
lock->x_waiters = flag;
|
||||||
|
}
|
||||||
|
UNIV_INLINE
|
||||||
|
void
|
||||||
|
rw_lock_set_wx_waiters(
|
||||||
|
/*================*/
|
||||||
|
rw_lock_t* lock,
|
||||||
|
ulint flag)
|
||||||
|
{
|
||||||
|
lock->wait_ex_waiters = flag;
|
||||||
}
|
}
|
||||||
UNIV_INLINE
|
UNIV_INLINE
|
||||||
ulint
|
ulint
|
||||||
@@ -68,7 +100,19 @@ rw_lock_get_writer(
|
|||||||
/*===============*/
|
/*===============*/
|
||||||
rw_lock_t* lock)
|
rw_lock_t* lock)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
if (lock->writer == RW_LOCK_NOT_LOCKED) {
|
||||||
|
return(RW_LOCK_NOT_LOCKED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lock->writer_is_wait_ex) {
|
||||||
|
return(RW_LOCK_WAIT_EX);
|
||||||
|
} else {
|
||||||
|
return(RW_LOCK_EX);
|
||||||
|
}
|
||||||
|
#else
|
||||||
return(lock->writer);
|
return(lock->writer);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
UNIV_INLINE
|
UNIV_INLINE
|
||||||
void
|
void
|
||||||
@@ -96,6 +140,7 @@ rw_lock_set_reader_count(
|
|||||||
{
|
{
|
||||||
lock->reader_count = count;
|
lock->reader_count = count;
|
||||||
}
|
}
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
UNIV_INLINE
|
UNIV_INLINE
|
||||||
mutex_t*
|
mutex_t*
|
||||||
rw_lock_get_mutex(
|
rw_lock_get_mutex(
|
||||||
@@ -104,6 +149,7 @@ rw_lock_get_mutex(
|
|||||||
{
|
{
|
||||||
return(&(lock->mutex));
|
return(&(lock->mutex));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
Returns the value of writer_count for the lock. Does not reserve the lock
|
Returns the value of writer_count for the lock. Does not reserve the lock
|
||||||
@@ -133,13 +179,27 @@ rw_lock_s_lock_low(
|
|||||||
const char* file_name, /* in: file name where lock requested */
|
const char* file_name, /* in: file name where lock requested */
|
||||||
ulint line) /* in: line where requested */
|
ulint line) /* in: line where requested */
|
||||||
{
|
{
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
ut_ad(mutex_own(rw_lock_get_mutex(lock)));
|
ut_ad(mutex_own(rw_lock_get_mutex(lock)));
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Check if the writer field is free */
|
/* Check if the writer field is free */
|
||||||
|
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
if (UNIV_LIKELY(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED)) {
|
||||||
|
/* try s-lock */
|
||||||
|
if(__sync_sub_and_fetch(&(lock->lock_word),1) <= 0) {
|
||||||
|
/* fail */
|
||||||
|
__sync_fetch_and_add(&(lock->lock_word),1);
|
||||||
|
return(FALSE); /* locking did not succeed */
|
||||||
|
}
|
||||||
|
/* success */
|
||||||
|
__sync_fetch_and_add(&(lock->reader_count),1);
|
||||||
|
#else
|
||||||
if (UNIV_LIKELY(lock->writer == RW_LOCK_NOT_LOCKED)) {
|
if (UNIV_LIKELY(lock->writer == RW_LOCK_NOT_LOCKED)) {
|
||||||
/* Set the shared lock by incrementing the reader count */
|
/* Set the shared lock by incrementing the reader count */
|
||||||
lock->reader_count++;
|
lock->reader_count++;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef UNIV_SYNC_DEBUG
|
#ifdef UNIV_SYNC_DEBUG
|
||||||
rw_lock_add_debug_info(lock, pass, RW_LOCK_SHARED, file_name,
|
rw_lock_add_debug_info(lock, pass, RW_LOCK_SHARED, file_name,
|
||||||
@@ -166,11 +226,15 @@ rw_lock_s_lock_direct(
|
|||||||
const char* file_name, /* in: file name where requested */
|
const char* file_name, /* in: file name where requested */
|
||||||
ulint line) /* in: line where lock requested */
|
ulint line) /* in: line where lock requested */
|
||||||
{
|
{
|
||||||
ut_ad(lock->writer == RW_LOCK_NOT_LOCKED);
|
ut_ad(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED);
|
||||||
ut_ad(rw_lock_get_reader_count(lock) == 0);
|
ut_ad(rw_lock_get_reader_count(lock) == 0);
|
||||||
|
|
||||||
/* Set the shared lock by incrementing the reader count */
|
/* Set the shared lock by incrementing the reader count */
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
__sync_fetch_and_add(&(lock->reader_count),1);
|
||||||
|
#else
|
||||||
lock->reader_count++;
|
lock->reader_count++;
|
||||||
|
#endif
|
||||||
|
|
||||||
lock->last_s_file_name = file_name;
|
lock->last_s_file_name = file_name;
|
||||||
lock->last_s_line = line;
|
lock->last_s_line = line;
|
||||||
@@ -198,7 +262,11 @@ rw_lock_x_lock_direct(
|
|||||||
|
|
||||||
rw_lock_set_writer(lock, RW_LOCK_EX);
|
rw_lock_set_writer(lock, RW_LOCK_EX);
|
||||||
lock->writer_thread = os_thread_get_curr_id();
|
lock->writer_thread = os_thread_get_curr_id();
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
__sync_fetch_and_add(&(lock->writer_count),1);
|
||||||
|
#else
|
||||||
lock->writer_count++;
|
lock->writer_count++;
|
||||||
|
#endif
|
||||||
lock->pass = 0;
|
lock->pass = 0;
|
||||||
|
|
||||||
lock->last_x_file_name = file_name;
|
lock->last_x_file_name = file_name;
|
||||||
@@ -240,15 +308,21 @@ rw_lock_s_lock_func(
|
|||||||
ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */
|
ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */
|
||||||
#endif /* UNIV_SYNC_DEBUG */
|
#endif /* UNIV_SYNC_DEBUG */
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_enter(rw_lock_get_mutex(lock));
|
mutex_enter(rw_lock_get_mutex(lock));
|
||||||
|
#endif
|
||||||
|
|
||||||
if (UNIV_LIKELY(rw_lock_s_lock_low(lock, pass, file_name, line))) {
|
if (UNIV_LIKELY(rw_lock_s_lock_low(lock, pass, file_name, line))) {
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_exit(rw_lock_get_mutex(lock));
|
mutex_exit(rw_lock_get_mutex(lock));
|
||||||
|
#endif
|
||||||
|
|
||||||
return; /* Success */
|
return; /* Success */
|
||||||
} else {
|
} else {
|
||||||
/* Did not succeed, try spin wait */
|
/* Did not succeed, try spin wait */
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_exit(rw_lock_get_mutex(lock));
|
mutex_exit(rw_lock_get_mutex(lock));
|
||||||
|
#endif
|
||||||
|
|
||||||
rw_lock_s_lock_spin(lock, pass, file_name, line);
|
rw_lock_s_lock_spin(lock, pass, file_name, line);
|
||||||
|
|
||||||
@@ -271,11 +345,23 @@ rw_lock_s_lock_func_nowait(
|
|||||||
{
|
{
|
||||||
ibool success = FALSE;
|
ibool success = FALSE;
|
||||||
|
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
|
||||||
|
/* try s-lock */
|
||||||
|
if(__sync_sub_and_fetch(&(lock->lock_word),1) <= 0) {
|
||||||
|
/* fail */
|
||||||
|
__sync_fetch_and_add(&(lock->lock_word),1);
|
||||||
|
return(FALSE); /* locking did not succeed */
|
||||||
|
}
|
||||||
|
/* success */
|
||||||
|
__sync_fetch_and_add(&(lock->reader_count),1);
|
||||||
|
#else
|
||||||
mutex_enter(rw_lock_get_mutex(lock));
|
mutex_enter(rw_lock_get_mutex(lock));
|
||||||
|
|
||||||
if (lock->writer == RW_LOCK_NOT_LOCKED) {
|
if (lock->writer == RW_LOCK_NOT_LOCKED) {
|
||||||
/* Set the shared lock by incrementing the reader count */
|
/* Set the shared lock by incrementing the reader count */
|
||||||
lock->reader_count++;
|
lock->reader_count++;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef UNIV_SYNC_DEBUG
|
#ifdef UNIV_SYNC_DEBUG
|
||||||
rw_lock_add_debug_info(lock, 0, RW_LOCK_SHARED, file_name,
|
rw_lock_add_debug_info(lock, 0, RW_LOCK_SHARED, file_name,
|
||||||
@@ -288,7 +374,9 @@ rw_lock_s_lock_func_nowait(
|
|||||||
success = TRUE;
|
success = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_exit(rw_lock_get_mutex(lock));
|
mutex_exit(rw_lock_get_mutex(lock));
|
||||||
|
#endif
|
||||||
|
|
||||||
return(success);
|
return(success);
|
||||||
}
|
}
|
||||||
@@ -308,6 +396,55 @@ rw_lock_x_lock_func_nowait(
|
|||||||
{
|
{
|
||||||
ibool success = FALSE;
|
ibool success = FALSE;
|
||||||
os_thread_id_t curr_thread = os_thread_get_curr_id();
|
os_thread_id_t curr_thread = os_thread_get_curr_id();
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
if ((lock->lock_word == RW_LOCK_BIAS)
|
||||||
|
&& rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
|
||||||
|
/* try x-lock */
|
||||||
|
if(__sync_sub_and_fetch(&(lock->lock_word),
|
||||||
|
RW_LOCK_BIAS) == 0) {
|
||||||
|
/* success */
|
||||||
|
/* try to lock writer */
|
||||||
|
if(__sync_lock_test_and_set(&(lock->writer),RW_LOCK_EX)
|
||||||
|
== RW_LOCK_NOT_LOCKED) {
|
||||||
|
/* success */
|
||||||
|
lock->writer_thread = curr_thread;
|
||||||
|
lock->pass = 0;
|
||||||
|
lock->writer_is_wait_ex = FALSE;
|
||||||
|
/* next function may work as memory barrier */
|
||||||
|
relock:
|
||||||
|
__sync_fetch_and_add(&(lock->writer_count),1);
|
||||||
|
|
||||||
|
#ifdef UNIV_SYNC_DEBUG
|
||||||
|
rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lock->last_x_file_name = file_name;
|
||||||
|
lock->last_x_line = line;
|
||||||
|
|
||||||
|
ut_ad(rw_lock_validate(lock));
|
||||||
|
|
||||||
|
return(TRUE);
|
||||||
|
} else {
|
||||||
|
/* x-unlock */
|
||||||
|
__sync_fetch_and_add(&(lock->lock_word),
|
||||||
|
RW_LOCK_BIAS);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* fail (x-lock) */
|
||||||
|
__sync_fetch_and_add(&(lock->lock_word),RW_LOCK_BIAS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lock->pass == 0
|
||||||
|
&& os_thread_eq(lock->writer_thread, curr_thread)
|
||||||
|
&& rw_lock_get_writer(lock) == RW_LOCK_EX) {
|
||||||
|
goto relock;
|
||||||
|
}
|
||||||
|
|
||||||
|
ut_ad(rw_lock_validate(lock));
|
||||||
|
|
||||||
|
return(FALSE);
|
||||||
|
#else
|
||||||
mutex_enter(rw_lock_get_mutex(lock));
|
mutex_enter(rw_lock_get_mutex(lock));
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(rw_lock_get_reader_count(lock) != 0)) {
|
if (UNIV_UNLIKELY(rw_lock_get_reader_count(lock) != 0)) {
|
||||||
@@ -338,6 +475,7 @@ relock:
|
|||||||
ut_ad(rw_lock_validate(lock));
|
ut_ad(rw_lock_validate(lock));
|
||||||
|
|
||||||
return(success);
|
return(success);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
@@ -353,16 +491,33 @@ rw_lock_s_unlock_func(
|
|||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_t* mutex = &(lock->mutex);
|
mutex_t* mutex = &(lock->mutex);
|
||||||
ibool sg = FALSE;
|
#endif
|
||||||
|
ibool x_sg = FALSE;
|
||||||
|
ibool wx_sg = FALSE;
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
ibool last = FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
/* Acquire the mutex protecting the rw-lock fields */
|
/* Acquire the mutex protecting the rw-lock fields */
|
||||||
mutex_enter(mutex);
|
mutex_enter(mutex);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Reset the shared lock by decrementing the reader count */
|
/* Reset the shared lock by decrementing the reader count */
|
||||||
|
|
||||||
ut_a(lock->reader_count > 0);
|
ut_a(lock->reader_count > 0);
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
/* unlock lock_word */
|
||||||
|
__sync_fetch_and_add(&(lock->lock_word),1);
|
||||||
|
|
||||||
|
if(__sync_sub_and_fetch(&(lock->reader_count),1) == 0) {
|
||||||
|
last = TRUE;
|
||||||
|
}
|
||||||
|
#else
|
||||||
lock->reader_count--;
|
lock->reader_count--;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef UNIV_SYNC_DEBUG
|
#ifdef UNIV_SYNC_DEBUG
|
||||||
rw_lock_remove_debug_info(lock, pass, RW_LOCK_SHARED);
|
rw_lock_remove_debug_info(lock, pass, RW_LOCK_SHARED);
|
||||||
@@ -371,20 +526,36 @@ rw_lock_s_unlock_func(
|
|||||||
/* If there may be waiters and this was the last s-lock,
|
/* If there may be waiters and this was the last s-lock,
|
||||||
signal the object */
|
signal the object */
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(lock->waiters)
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
if (UNIV_UNLIKELY(last && lock->wait_ex_waiters)) {
|
||||||
|
#else
|
||||||
|
if (UNIV_UNLIKELY(lock->wait_ex_waiters)
|
||||||
&& lock->reader_count == 0) {
|
&& lock->reader_count == 0) {
|
||||||
sg = TRUE;
|
#endif
|
||||||
|
wx_sg = TRUE;
|
||||||
|
|
||||||
rw_lock_set_waiters(lock, 0);
|
rw_lock_set_wx_waiters(lock, 0);
|
||||||
|
}
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
else if (UNIV_UNLIKELY(last && lock->x_waiters)) {
|
||||||
|
#else
|
||||||
|
else if (UNIV_UNLIKELY(lock->x_waiters)
|
||||||
|
&& lock->reader_count == 0) {
|
||||||
|
#endif
|
||||||
|
x_sg = TRUE;
|
||||||
|
|
||||||
|
rw_lock_set_x_waiters(lock, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_exit(mutex);
|
mutex_exit(mutex);
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(sg)) {
|
|
||||||
#ifdef __WIN__
|
|
||||||
os_event_set(lock->wait_ex_event);
|
|
||||||
#endif
|
#endif
|
||||||
os_event_set(lock->event);
|
|
||||||
|
if (UNIV_UNLIKELY(wx_sg)) {
|
||||||
|
os_event_set(lock->wait_ex_event);
|
||||||
|
sync_array_object_signalled(sync_primary_wait_array);
|
||||||
|
} else if (UNIV_UNLIKELY(x_sg)) {
|
||||||
|
os_event_set(lock->x_event);
|
||||||
sync_array_object_signalled(sync_primary_wait_array);
|
sync_array_object_signalled(sync_primary_wait_array);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,13 +579,19 @@ rw_lock_s_unlock_direct(
|
|||||||
|
|
||||||
ut_ad(lock->reader_count > 0);
|
ut_ad(lock->reader_count > 0);
|
||||||
|
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
__sync_sub_and_fetch(&(lock->reader_count),1);
|
||||||
|
#else
|
||||||
lock->reader_count--;
|
lock->reader_count--;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef UNIV_SYNC_DEBUG
|
#ifdef UNIV_SYNC_DEBUG
|
||||||
rw_lock_remove_debug_info(lock, 0, RW_LOCK_SHARED);
|
rw_lock_remove_debug_info(lock, 0, RW_LOCK_SHARED);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ut_ad(!lock->waiters);
|
ut_ad(!lock->s_waiters);
|
||||||
|
ut_ad(!lock->x_waiters);
|
||||||
|
ut_ad(!lock->wait_ex_waiters);
|
||||||
ut_ad(rw_lock_validate(lock));
|
ut_ad(rw_lock_validate(lock));
|
||||||
#ifdef UNIV_SYNC_PERF_STAT
|
#ifdef UNIV_SYNC_PERF_STAT
|
||||||
rw_s_exit_count++;
|
rw_s_exit_count++;
|
||||||
@@ -434,41 +611,81 @@ rw_lock_x_unlock_func(
|
|||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ibool sg = FALSE;
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
ibool last = FALSE;
|
||||||
|
#endif
|
||||||
|
ibool s_sg = FALSE;
|
||||||
|
ibool x_sg = FALSE;
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
/* Acquire the mutex protecting the rw-lock fields */
|
/* Acquire the mutex protecting the rw-lock fields */
|
||||||
mutex_enter(&(lock->mutex));
|
mutex_enter(&(lock->mutex));
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Reset the exclusive lock if this thread no longer has an x-mode
|
/* Reset the exclusive lock if this thread no longer has an x-mode
|
||||||
lock */
|
lock */
|
||||||
|
|
||||||
ut_ad(lock->writer_count > 0);
|
ut_ad(lock->writer_count > 0);
|
||||||
|
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
if(__sync_sub_and_fetch(&(lock->writer_count),1) == 0) {
|
||||||
|
last = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last) {
|
||||||
|
/* unlock lock_word */
|
||||||
|
__sync_fetch_and_add(&(lock->lock_word),RW_LOCK_BIAS);
|
||||||
|
|
||||||
|
/* FIXME: It is a value of bad manners for pthread.
|
||||||
|
But we shouldn't keep an ID of not-owner. */
|
||||||
|
lock->writer_thread = -1;
|
||||||
|
|
||||||
|
/* atomic operation may be safer about memory order. */
|
||||||
|
rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
|
||||||
|
__sync_synchronize();
|
||||||
|
}
|
||||||
|
#else
|
||||||
lock->writer_count--;
|
lock->writer_count--;
|
||||||
|
|
||||||
if (lock->writer_count == 0) {
|
if (lock->writer_count == 0) {
|
||||||
rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
|
rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef UNIV_SYNC_DEBUG
|
#ifdef UNIV_SYNC_DEBUG
|
||||||
rw_lock_remove_debug_info(lock, pass, RW_LOCK_EX);
|
rw_lock_remove_debug_info(lock, pass, RW_LOCK_EX);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If there may be waiters, signal the lock */
|
/* If there may be waiters, signal the lock */
|
||||||
if (UNIV_UNLIKELY(lock->waiters)
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
&& lock->writer_count == 0) {
|
if (last) {
|
||||||
|
#else
|
||||||
sg = TRUE;
|
if (lock->writer_count == 0) {
|
||||||
rw_lock_set_waiters(lock, 0);
|
#endif
|
||||||
|
if(lock->s_waiters){
|
||||||
|
s_sg = TRUE;
|
||||||
|
rw_lock_set_s_waiters(lock, 0);
|
||||||
|
}
|
||||||
|
if(lock->x_waiters){
|
||||||
|
x_sg = TRUE;
|
||||||
|
rw_lock_set_x_waiters(lock, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_exit(&(lock->mutex));
|
mutex_exit(&(lock->mutex));
|
||||||
|
#endif
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(sg)) {
|
if (UNIV_UNLIKELY(s_sg)) {
|
||||||
|
os_event_set(lock->s_event);
|
||||||
|
sync_array_object_signalled(sync_primary_wait_array);
|
||||||
|
}
|
||||||
|
if (UNIV_UNLIKELY(x_sg)) {
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
|
/* I doubt the necessity of it. */
|
||||||
os_event_set(lock->wait_ex_event);
|
os_event_set(lock->wait_ex_event);
|
||||||
#endif
|
#endif
|
||||||
os_event_set(lock->event);
|
os_event_set(lock->x_event);
|
||||||
sync_array_object_signalled(sync_primary_wait_array);
|
sync_array_object_signalled(sync_primary_wait_array);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -493,9 +710,13 @@ rw_lock_x_unlock_direct(
|
|||||||
|
|
||||||
ut_ad(lock->writer_count > 0);
|
ut_ad(lock->writer_count > 0);
|
||||||
|
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
if(__sync_sub_and_fetch(&(lock->writer_count),1) == 0) {
|
||||||
|
#else
|
||||||
lock->writer_count--;
|
lock->writer_count--;
|
||||||
|
|
||||||
if (lock->writer_count == 0) {
|
if (lock->writer_count == 0) {
|
||||||
|
#endif
|
||||||
rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
|
rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -503,7 +724,9 @@ rw_lock_x_unlock_direct(
|
|||||||
rw_lock_remove_debug_info(lock, 0, RW_LOCK_EX);
|
rw_lock_remove_debug_info(lock, 0, RW_LOCK_EX);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ut_ad(!lock->waiters);
|
ut_ad(!lock->s_waiters);
|
||||||
|
ut_ad(!lock->x_waiters);
|
||||||
|
ut_ad(!lock->wait_ex_waiters);
|
||||||
ut_ad(rw_lock_validate(lock));
|
ut_ad(rw_lock_validate(lock));
|
||||||
|
|
||||||
#ifdef UNIV_SYNC_PERF_STAT
|
#ifdef UNIV_SYNC_PERF_STAT
|
||||||
|
|||||||
@@ -60,6 +60,17 @@ thr_local_get_in_ibuf_field(void);
|
|||||||
/*=============================*/
|
/*=============================*/
|
||||||
/* out: pointer to the in_ibuf field */
|
/* out: pointer to the in_ibuf field */
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Return local hash table informations. */
|
||||||
|
|
||||||
|
ulint
|
||||||
|
thr_local_hash_cells(void);
|
||||||
|
/*=======================*/
|
||||||
|
|
||||||
|
ulint
|
||||||
|
thr_local_hash_nodes(void);
|
||||||
|
/*=======================*/
|
||||||
|
|
||||||
#ifndef UNIV_NONINL
|
#ifndef UNIV_NONINL
|
||||||
#include "thr0loc.ic"
|
#include "thr0loc.ic"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ Created 1/20/1994 Heikki Tuuri
|
|||||||
#define INNODB_VERSION_MAJOR 1
|
#define INNODB_VERSION_MAJOR 1
|
||||||
#define INNODB_VERSION_MINOR 0
|
#define INNODB_VERSION_MINOR 0
|
||||||
#define INNODB_VERSION_BUGFIX 2
|
#define INNODB_VERSION_BUGFIX 2
|
||||||
|
#define PERCONA_INNODB_VERSION 1
|
||||||
|
|
||||||
/* The following is the InnoDB version as shown in
|
/* The following is the InnoDB version as shown in
|
||||||
SELECT plugin_version FROM information_schema.plugins;
|
SELECT plugin_version FROM information_schema.plugins;
|
||||||
@@ -23,13 +24,14 @@ component, i.e. we show M.N.P as M.N */
|
|||||||
(INNODB_VERSION_MAJOR << 8 | INNODB_VERSION_MINOR)
|
(INNODB_VERSION_MAJOR << 8 | INNODB_VERSION_MINOR)
|
||||||
|
|
||||||
/* auxiliary macros to help creating the version as string */
|
/* auxiliary macros to help creating the version as string */
|
||||||
#define __INNODB_VERSION(a, b, c) (#a "." #b "." #c)
|
#define __INNODB_VERSION(a, b, c, d) (#a "." #b "." #c "-" #d)
|
||||||
#define _INNODB_VERSION(a, b, c) __INNODB_VERSION(a, b, c)
|
#define _INNODB_VERSION(a, b, c, d) __INNODB_VERSION(a, b, c, d)
|
||||||
|
|
||||||
#define INNODB_VERSION_STR \
|
#define INNODB_VERSION_STR \
|
||||||
_INNODB_VERSION(INNODB_VERSION_MAJOR, \
|
_INNODB_VERSION(INNODB_VERSION_MAJOR, \
|
||||||
INNODB_VERSION_MINOR, \
|
INNODB_VERSION_MINOR, \
|
||||||
INNODB_VERSION_BUGFIX)
|
INNODB_VERSION_BUGFIX, \
|
||||||
|
PERCONA_INNODB_VERSION)
|
||||||
|
|
||||||
#ifdef MYSQL_DYNAMIC_PLUGIN
|
#ifdef MYSQL_DYNAMIC_PLUGIN
|
||||||
/* In the dynamic plugin, redefine some externally visible symbols
|
/* In the dynamic plugin, redefine some externally visible symbols
|
||||||
|
|||||||
@@ -4294,32 +4294,32 @@ lock_rec_print(
|
|||||||
|
|
||||||
putc('\n', file);
|
putc('\n', file);
|
||||||
|
|
||||||
block = buf_page_try_get(space, page_no, &mtr);
|
if ( srv_show_verbose_locks ) {
|
||||||
|
block = buf_page_try_get(space, page_no, &mtr);
|
||||||
|
if (block) {
|
||||||
|
for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
|
||||||
|
|
||||||
if (block) {
|
if (lock_rec_get_nth_bit(lock, i)) {
|
||||||
for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
|
|
||||||
|
|
||||||
if (lock_rec_get_nth_bit(lock, i)) {
|
const rec_t* rec
|
||||||
|
= page_find_rec_with_heap_no(
|
||||||
|
buf_block_get_frame(block), i);
|
||||||
|
offsets = rec_get_offsets(
|
||||||
|
rec, lock->index, offsets,
|
||||||
|
ULINT_UNDEFINED, &heap);
|
||||||
|
|
||||||
const rec_t* rec
|
fprintf(file, "Record lock, heap no %lu ",
|
||||||
= page_find_rec_with_heap_no(
|
(ulong) i);
|
||||||
buf_block_get_frame(block), i);
|
rec_print_new(file, rec, offsets);
|
||||||
offsets = rec_get_offsets(
|
putc('\n', file);
|
||||||
rec, lock->index, offsets,
|
}
|
||||||
ULINT_UNDEFINED, &heap);
|
}
|
||||||
|
} else {
|
||||||
fprintf(file, "Record lock, heap no %lu ",
|
for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
|
||||||
(ulong) i);
|
fprintf(file, "Record lock, heap no %lu\n", (ulong) i);
|
||||||
rec_print_new(file, rec, offsets);
|
|
||||||
putc('\n', file);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
|
|
||||||
fprintf(file, "Record lock, heap no %lu\n", (ulong) i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mtr_commit(&mtr);
|
mtr_commit(&mtr);
|
||||||
if (UNIV_LIKELY_NULL(heap)) {
|
if (UNIV_LIKELY_NULL(heap)) {
|
||||||
mem_heap_free(heap);
|
mem_heap_free(heap);
|
||||||
@@ -4498,7 +4498,7 @@ loop:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!srv_print_innodb_lock_monitor) {
|
if (!srv_print_innodb_lock_monitor && !srv_show_locks_held) {
|
||||||
nth_trx++;
|
nth_trx++;
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
@@ -4557,8 +4557,8 @@ loop:
|
|||||||
|
|
||||||
nth_lock++;
|
nth_lock++;
|
||||||
|
|
||||||
if (nth_lock >= 10) {
|
if (nth_lock >= srv_show_locks_held) {
|
||||||
fputs("10 LOCKS PRINTED FOR THIS TRX:"
|
fputs("TOO LOCKS PRINTED FOR THIS TRX:"
|
||||||
" SUPPRESSING FURTHER PRINTS\n",
|
" SUPPRESSING FURTHER PRINTS\n",
|
||||||
file);
|
file);
|
||||||
|
|
||||||
|
|||||||
@@ -3258,6 +3258,15 @@ log_print(
|
|||||||
log_sys->flushed_to_disk_lsn,
|
log_sys->flushed_to_disk_lsn,
|
||||||
log_sys->last_checkpoint_lsn);
|
log_sys->last_checkpoint_lsn);
|
||||||
|
|
||||||
|
fprintf(file,
|
||||||
|
"Max checkpoint age %lu\n"
|
||||||
|
"Modified age %lu\n"
|
||||||
|
"Checkpoint age %lu\n",
|
||||||
|
(ulong) log_sys->max_checkpoint_age,
|
||||||
|
(ulong) (log_sys->lsn -
|
||||||
|
log_buf_pool_get_oldest_modification()),
|
||||||
|
(ulong) (log_sys->lsn - log_sys->last_checkpoint_lsn));
|
||||||
|
|
||||||
current_time = time(NULL);
|
current_time = time(NULL);
|
||||||
|
|
||||||
time_elapsed = 0.001 + difftime(current_time,
|
time_elapsed = 0.001 + difftime(current_time,
|
||||||
|
|||||||
30
os/os0file.c
30
os/os0file.c
@@ -2920,8 +2920,10 @@ os_aio_init(
|
|||||||
/*========*/
|
/*========*/
|
||||||
ulint n, /* in: maximum number of pending aio operations
|
ulint n, /* in: maximum number of pending aio operations
|
||||||
allowed; n must be divisible by n_segments */
|
allowed; n must be divisible by n_segments */
|
||||||
ulint n_segments, /* in: combined number of segments in the four
|
// ulint n_segments, /* in: combined number of segments in the four
|
||||||
first aio arrays; must be >= 4 */
|
// first aio arrays; must be >= 4 */
|
||||||
|
ulint n_read_threads, /* n_segments == 2 + n_read_threads + n_write_threads*/
|
||||||
|
ulint n_write_threads, /**/
|
||||||
ulint n_slots_sync) /* in: number of slots in the sync aio array */
|
ulint n_slots_sync) /* in: number of slots in the sync aio array */
|
||||||
{
|
{
|
||||||
ulint n_read_segs;
|
ulint n_read_segs;
|
||||||
@@ -2929,6 +2931,8 @@ os_aio_init(
|
|||||||
ulint n_per_seg;
|
ulint n_per_seg;
|
||||||
ulint i;
|
ulint i;
|
||||||
|
|
||||||
|
ulint n_segments = 2 + n_read_threads + n_write_threads;
|
||||||
|
|
||||||
ut_ad(n % n_segments == 0);
|
ut_ad(n % n_segments == 0);
|
||||||
ut_ad(n_segments >= 4);
|
ut_ad(n_segments >= 4);
|
||||||
|
|
||||||
@@ -2939,8 +2943,8 @@ os_aio_init(
|
|||||||
}
|
}
|
||||||
|
|
||||||
n_per_seg = n / n_segments;
|
n_per_seg = n / n_segments;
|
||||||
n_write_segs = (n_segments - 2) / 2;
|
n_write_segs = n_write_threads;
|
||||||
n_read_segs = n_segments - 2 - n_write_segs;
|
n_read_segs = n_read_threads;
|
||||||
|
|
||||||
/* fprintf(stderr, "Array n per seg %lu\n", n_per_seg); */
|
/* fprintf(stderr, "Array n per seg %lu\n", n_per_seg); */
|
||||||
|
|
||||||
@@ -3140,6 +3144,13 @@ os_aio_array_reserve_slot(
|
|||||||
OVERLAPPED* control;
|
OVERLAPPED* control;
|
||||||
#endif
|
#endif
|
||||||
ulint i;
|
ulint i;
|
||||||
|
ulint prim_segment;
|
||||||
|
ulint n;
|
||||||
|
|
||||||
|
n = array->n_slots / array->n_segments;
|
||||||
|
/* 64 blocks' striping ( aligning max(BUF_READ_AHEAD_AREA) ) */
|
||||||
|
prim_segment = ( offset >> (UNIV_PAGE_SIZE_SHIFT + 6) ) % (array->n_segments);
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
os_mutex_enter(array->mutex);
|
os_mutex_enter(array->mutex);
|
||||||
|
|
||||||
@@ -3158,6 +3169,16 @@ loop:
|
|||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = prim_segment * n; i < array->n_slots; i++) {
|
||||||
|
slot = os_aio_array_get_nth_slot(array, i);
|
||||||
|
|
||||||
|
if (slot->reserved == FALSE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slot->reserved == TRUE){
|
||||||
|
/* Not found after the intended segment. So we should search before. */
|
||||||
for (i = 0;; i++) {
|
for (i = 0;; i++) {
|
||||||
slot = os_aio_array_get_nth_slot(array, i);
|
slot = os_aio_array_get_nth_slot(array, i);
|
||||||
|
|
||||||
@@ -3165,6 +3186,7 @@ loop:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
array->n_reserved++;
|
array->n_reserved++;
|
||||||
|
|
||||||
|
|||||||
204
srv/srv0srv.c
204
srv/srv0srv.c
@@ -132,6 +132,10 @@ UNIV_INTERN ulint srv_log_file_size = ULINT_MAX;
|
|||||||
UNIV_INTERN ulint srv_log_buffer_size = ULINT_MAX;
|
UNIV_INTERN ulint srv_log_buffer_size = ULINT_MAX;
|
||||||
UNIV_INTERN ulong srv_flush_log_at_trx_commit = 1;
|
UNIV_INTERN ulong srv_flush_log_at_trx_commit = 1;
|
||||||
|
|
||||||
|
UNIV_INTERN ulint srv_show_locks_held = 10;
|
||||||
|
UNIV_INTERN ulint srv_show_verbose_locks = 0;
|
||||||
|
|
||||||
|
|
||||||
/* The sort order table of the MySQL latin1_swedish_ci character set
|
/* The sort order table of the MySQL latin1_swedish_ci character set
|
||||||
collation */
|
collation */
|
||||||
UNIV_INTERN const byte* srv_latin1_ordering;
|
UNIV_INTERN const byte* srv_latin1_ordering;
|
||||||
@@ -147,6 +151,8 @@ UNIV_INTERN ulint srv_mem_pool_size = ULINT_MAX;
|
|||||||
UNIV_INTERN ulint srv_lock_table_size = ULINT_MAX;
|
UNIV_INTERN ulint srv_lock_table_size = ULINT_MAX;
|
||||||
|
|
||||||
UNIV_INTERN ulint srv_n_file_io_threads = ULINT_MAX;
|
UNIV_INTERN ulint srv_n_file_io_threads = ULINT_MAX;
|
||||||
|
ulint srv_n_read_io_threads = 1;
|
||||||
|
ulint srv_n_write_io_threads = 1;
|
||||||
|
|
||||||
#ifdef UNIV_LOG_ARCHIVE
|
#ifdef UNIV_LOG_ARCHIVE
|
||||||
UNIV_INTERN ibool srv_log_archive_on = FALSE;
|
UNIV_INTERN ibool srv_log_archive_on = FALSE;
|
||||||
@@ -311,6 +317,15 @@ UNIV_INTERN int srv_query_thread_priority = 0;
|
|||||||
|
|
||||||
UNIV_INTERN ulong srv_replication_delay = 0;
|
UNIV_INTERN ulong srv_replication_delay = 0;
|
||||||
|
|
||||||
|
ulint srv_io_capacity = 100;
|
||||||
|
|
||||||
|
/* Returns the number of IO operations that is X percent of the capacity.
|
||||||
|
PCT_IO(5) -> returns the number of IO operations that is 5% of the max
|
||||||
|
where max is srv_io_capacity. */
|
||||||
|
#define PCT_IO(pct) ((ulint) (srv_io_capacity * ((double) pct / 100.0)))
|
||||||
|
|
||||||
|
ulint srv_read_ahead = 3; /* 1: random 2: linear 3: Both */
|
||||||
|
ulint srv_adaptive_checkpoint = 0; /* 0:disable 1:enable */
|
||||||
/*-------------------------------------------*/
|
/*-------------------------------------------*/
|
||||||
UNIV_INTERN ulong srv_n_spin_wait_rounds = 20;
|
UNIV_INTERN ulong srv_n_spin_wait_rounds = 20;
|
||||||
UNIV_INTERN ulong srv_n_free_tickets_to_enter = 500;
|
UNIV_INTERN ulong srv_n_free_tickets_to_enter = 500;
|
||||||
@@ -1614,6 +1629,14 @@ srv_printf_innodb_monitor(
|
|||||||
time_t current_time;
|
time_t current_time;
|
||||||
ulint n_reserved;
|
ulint n_reserved;
|
||||||
|
|
||||||
|
ulint btr_search_sys_subtotal;
|
||||||
|
ulint lock_sys_subtotal;
|
||||||
|
ulint recv_sys_subtotal;
|
||||||
|
ulint io_counter_subtotal;
|
||||||
|
|
||||||
|
ulint i;
|
||||||
|
trx_t* trx;
|
||||||
|
|
||||||
mutex_enter(&srv_innodb_monitor_mutex);
|
mutex_enter(&srv_innodb_monitor_mutex);
|
||||||
|
|
||||||
current_time = time(NULL);
|
current_time = time(NULL);
|
||||||
@@ -1657,24 +1680,6 @@ srv_printf_innodb_monitor(
|
|||||||
|
|
||||||
mutex_exit(&dict_foreign_err_mutex);
|
mutex_exit(&dict_foreign_err_mutex);
|
||||||
|
|
||||||
lock_print_info_summary(file);
|
|
||||||
if (trx_start) {
|
|
||||||
long t = ftell(file);
|
|
||||||
if (t < 0) {
|
|
||||||
*trx_start = ULINT_UNDEFINED;
|
|
||||||
} else {
|
|
||||||
*trx_start = (ulint) t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lock_print_info_all_transactions(file);
|
|
||||||
if (trx_end) {
|
|
||||||
long t = ftell(file);
|
|
||||||
if (t < 0) {
|
|
||||||
*trx_end = ULINT_UNDEFINED;
|
|
||||||
} else {
|
|
||||||
*trx_end = (ulint) t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fputs("--------\n"
|
fputs("--------\n"
|
||||||
"FILE I/O\n"
|
"FILE I/O\n"
|
||||||
"--------\n", file);
|
"--------\n", file);
|
||||||
@@ -1705,10 +1710,84 @@ srv_printf_innodb_monitor(
|
|||||||
"BUFFER POOL AND MEMORY\n"
|
"BUFFER POOL AND MEMORY\n"
|
||||||
"----------------------\n", file);
|
"----------------------\n", file);
|
||||||
fprintf(file,
|
fprintf(file,
|
||||||
"Total memory allocated " ULINTPF
|
"Total memory allocated " ULINTPF
|
||||||
"; in additional pool allocated " ULINTPF "\n",
|
"; in additional pool allocated " ULINTPF "\n",
|
||||||
ut_total_allocated_memory,
|
ut_total_allocated_memory,
|
||||||
mem_pool_get_reserved(mem_comm_pool));
|
mem_pool_get_reserved(mem_comm_pool));
|
||||||
|
/* Calcurate reserved memories */
|
||||||
|
if (btr_search_sys && btr_search_sys->hash_index->heap) {
|
||||||
|
btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index->heap);
|
||||||
|
} else {
|
||||||
|
btr_search_sys_subtotal = 0;
|
||||||
|
for (i=0; i < btr_search_sys->hash_index->n_mutexes; i++) {
|
||||||
|
btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index->heaps[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lock_sys_subtotal = 0;
|
||||||
|
if (trx_sys) {
|
||||||
|
mutex_enter(&kernel_mutex);
|
||||||
|
trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
|
||||||
|
while (trx) {
|
||||||
|
lock_sys_subtotal += ((trx->lock_heap) ? mem_heap_get_size(trx->lock_heap) : 0);
|
||||||
|
trx = UT_LIST_GET_NEXT(mysql_trx_list, trx);
|
||||||
|
}
|
||||||
|
mutex_exit(&kernel_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
recv_sys_subtotal = ((recv_sys && recv_sys->addr_hash)
|
||||||
|
? mem_heap_get_size(recv_sys->heap) : 0);
|
||||||
|
|
||||||
|
fprintf(file,
|
||||||
|
"Internal hash tables (constant factor + variable factor)\n"
|
||||||
|
" Adaptive hash index %lu \t(%lu + %lu)\n"
|
||||||
|
" Page hash %lu\n"
|
||||||
|
" Dictionary cache %lu \t(%lu + %lu)\n"
|
||||||
|
" File system %lu \t(%lu + %lu)\n"
|
||||||
|
" Lock system %lu \t(%lu + %lu)\n"
|
||||||
|
" Recovery system %lu \t(%lu + %lu)\n"
|
||||||
|
" Threads %lu \t(%lu + %lu)\n",
|
||||||
|
|
||||||
|
(ulong) (btr_search_sys
|
||||||
|
? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0)
|
||||||
|
+ btr_search_sys_subtotal,
|
||||||
|
(ulong) (btr_search_sys
|
||||||
|
? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0),
|
||||||
|
(ulong) btr_search_sys_subtotal,
|
||||||
|
|
||||||
|
(ulong) (buf_pool->page_hash->n_cells * sizeof(hash_cell_t)),
|
||||||
|
|
||||||
|
(ulong) (dict_sys ? ((dict_sys->table_hash->n_cells
|
||||||
|
+ dict_sys->table_id_hash->n_cells
|
||||||
|
) * sizeof(hash_cell_t)
|
||||||
|
+ dict_sys->size) : 0),
|
||||||
|
(ulong) (dict_sys ? ((dict_sys->table_hash->n_cells
|
||||||
|
+ dict_sys->table_id_hash->n_cells
|
||||||
|
) * sizeof(hash_cell_t)) : 0),
|
||||||
|
(ulong) (dict_sys ? (dict_sys->size) : 0),
|
||||||
|
|
||||||
|
(ulong) (fil_system_hash_cells() * sizeof(hash_cell_t)
|
||||||
|
+ fil_system_hash_nodes()),
|
||||||
|
(ulong) (fil_system_hash_cells() * sizeof(hash_cell_t)),
|
||||||
|
(ulong) fil_system_hash_nodes(),
|
||||||
|
|
||||||
|
(ulong) ((lock_sys ? (lock_sys->rec_hash->n_cells * sizeof(hash_cell_t)) : 0)
|
||||||
|
+ lock_sys_subtotal),
|
||||||
|
(ulong) (lock_sys ? (lock_sys->rec_hash->n_cells * sizeof(hash_cell_t)) : 0),
|
||||||
|
(ulong) lock_sys_subtotal,
|
||||||
|
|
||||||
|
(ulong) (((recv_sys && recv_sys->addr_hash)
|
||||||
|
? (recv_sys->addr_hash->n_cells * sizeof(hash_cell_t)) : 0)
|
||||||
|
+ recv_sys_subtotal),
|
||||||
|
(ulong) ((recv_sys && recv_sys->addr_hash)
|
||||||
|
? (recv_sys->addr_hash->n_cells * sizeof(hash_cell_t)) : 0),
|
||||||
|
(ulong) recv_sys_subtotal,
|
||||||
|
|
||||||
|
(ulong) (thr_local_hash_cells() * sizeof(hash_cell_t)
|
||||||
|
+ thr_local_hash_nodes()),
|
||||||
|
(ulong) (thr_local_hash_cells() * sizeof(hash_cell_t)),
|
||||||
|
(ulong) thr_local_hash_nodes());
|
||||||
|
|
||||||
fprintf(file, "Dictionary memory allocated " ULINTPF "\n",
|
fprintf(file, "Dictionary memory allocated " ULINTPF "\n",
|
||||||
dict_sys->size);
|
dict_sys->size);
|
||||||
|
|
||||||
@@ -1767,6 +1846,25 @@ srv_printf_innodb_monitor(
|
|||||||
srv_n_rows_deleted_old = srv_n_rows_deleted;
|
srv_n_rows_deleted_old = srv_n_rows_deleted;
|
||||||
srv_n_rows_read_old = srv_n_rows_read;
|
srv_n_rows_read_old = srv_n_rows_read;
|
||||||
|
|
||||||
|
lock_print_info_summary(file);
|
||||||
|
if (trx_start) {
|
||||||
|
long t = ftell(file);
|
||||||
|
if (t < 0) {
|
||||||
|
*trx_start = ULINT_UNDEFINED;
|
||||||
|
} else {
|
||||||
|
*trx_start = (ulint) t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lock_print_info_all_transactions(file);
|
||||||
|
if (trx_end) {
|
||||||
|
long t = ftell(file);
|
||||||
|
if (t < 0) {
|
||||||
|
*trx_end = ULINT_UNDEFINED;
|
||||||
|
} else {
|
||||||
|
*trx_end = (ulint) t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fputs("----------------------------\n"
|
fputs("----------------------------\n"
|
||||||
"END OF INNODB MONITOR OUTPUT\n"
|
"END OF INNODB MONITOR OUTPUT\n"
|
||||||
"============================\n", file);
|
"============================\n", file);
|
||||||
@@ -2203,6 +2301,8 @@ srv_master_thread(
|
|||||||
ibool skip_sleep = FALSE;
|
ibool skip_sleep = FALSE;
|
||||||
ulint i;
|
ulint i;
|
||||||
|
|
||||||
|
ib_uint64_t oldest_lsn;
|
||||||
|
|
||||||
#ifdef UNIV_DEBUG_THREAD_CREATION
|
#ifdef UNIV_DEBUG_THREAD_CREATION
|
||||||
fprintf(stderr, "Master thread starts, id %lu\n",
|
fprintf(stderr, "Master thread starts, id %lu\n",
|
||||||
os_thread_pf(os_thread_get_curr_id()));
|
os_thread_pf(os_thread_get_curr_id()));
|
||||||
@@ -2290,10 +2390,10 @@ loop:
|
|||||||
+ log_sys->n_pending_writes;
|
+ log_sys->n_pending_writes;
|
||||||
n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
|
n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
|
||||||
+ buf_pool->n_pages_written;
|
+ buf_pool->n_pages_written;
|
||||||
if (n_pend_ios < 3 && (n_ios - n_ios_old < 5)) {
|
if (n_pend_ios < 3 && (n_ios - n_ios_old < PCT_IO(5))) {
|
||||||
srv_main_thread_op_info = "doing insert buffer merge";
|
srv_main_thread_op_info = "doing insert buffer merge";
|
||||||
ibuf_contract_for_n_pages(
|
ibuf_contract_for_n_pages(
|
||||||
TRUE, srv_insert_buffer_batch_size / 4);
|
TRUE, PCT_IO((srv_insert_buffer_batch_size / 4)));
|
||||||
|
|
||||||
srv_main_thread_op_info = "flushing log";
|
srv_main_thread_op_info = "flushing log";
|
||||||
|
|
||||||
@@ -2306,7 +2406,7 @@ loop:
|
|||||||
/* Try to keep the number of modified pages in the
|
/* Try to keep the number of modified pages in the
|
||||||
buffer pool under the limit wished by the user */
|
buffer pool under the limit wished by the user */
|
||||||
|
|
||||||
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100,
|
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, PCT_IO(100),
|
||||||
IB_ULONGLONG_MAX);
|
IB_ULONGLONG_MAX);
|
||||||
|
|
||||||
/* If we had to do the flush, it may have taken
|
/* If we had to do the flush, it may have taken
|
||||||
@@ -2315,6 +2415,44 @@ loop:
|
|||||||
iteration of this loop. */
|
iteration of this loop. */
|
||||||
|
|
||||||
skip_sleep = TRUE;
|
skip_sleep = TRUE;
|
||||||
|
} else if (srv_adaptive_checkpoint) {
|
||||||
|
|
||||||
|
/* Try to keep modified age not to exceed
|
||||||
|
max_checkpoint_age * 7/8 line */
|
||||||
|
|
||||||
|
mutex_enter(&(log_sys->mutex));
|
||||||
|
|
||||||
|
oldest_lsn = buf_pool_get_oldest_modification();
|
||||||
|
if (oldest_lsn == 0) {
|
||||||
|
|
||||||
|
mutex_exit(&(log_sys->mutex));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if ((log_sys->lsn - oldest_lsn)
|
||||||
|
> (log_sys->max_checkpoint_age) - ((log_sys->max_checkpoint_age) / 4)) {
|
||||||
|
|
||||||
|
/* 2nd defence line (max_checkpoint_age * 3/4) */
|
||||||
|
|
||||||
|
mutex_exit(&(log_sys->mutex));
|
||||||
|
|
||||||
|
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, PCT_IO(100),
|
||||||
|
IB_ULONGLONG_MAX);
|
||||||
|
skip_sleep = TRUE;
|
||||||
|
} else if ((log_sys->lsn - oldest_lsn)
|
||||||
|
> (log_sys->max_checkpoint_age)/2 ) {
|
||||||
|
|
||||||
|
/* 1st defence line (max_checkpoint_age * 1/2) */
|
||||||
|
|
||||||
|
mutex_exit(&(log_sys->mutex));
|
||||||
|
|
||||||
|
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, PCT_IO(10),
|
||||||
|
IB_ULONGLONG_MAX);
|
||||||
|
skip_sleep = TRUE;
|
||||||
|
} else {
|
||||||
|
mutex_exit(&(log_sys->mutex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (srv_activity_count == old_activity_count) {
|
if (srv_activity_count == old_activity_count) {
|
||||||
@@ -2341,10 +2479,10 @@ loop:
|
|||||||
n_pend_ios = buf_get_n_pending_ios() + log_sys->n_pending_writes;
|
n_pend_ios = buf_get_n_pending_ios() + log_sys->n_pending_writes;
|
||||||
n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
|
n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
|
||||||
+ buf_pool->n_pages_written;
|
+ buf_pool->n_pages_written;
|
||||||
if (n_pend_ios < 3 && (n_ios - n_ios_very_old < 200)) {
|
if (n_pend_ios < 3 && (n_ios - n_ios_very_old < PCT_IO(200))) {
|
||||||
|
|
||||||
srv_main_thread_op_info = "flushing buffer pool pages";
|
srv_main_thread_op_info = "flushing buffer pool pages";
|
||||||
buf_flush_batch(BUF_FLUSH_LIST, 100, IB_ULONGLONG_MAX);
|
buf_flush_batch(BUF_FLUSH_LIST, PCT_IO(100), IB_ULONGLONG_MAX);
|
||||||
|
|
||||||
srv_main_thread_op_info = "flushing log";
|
srv_main_thread_op_info = "flushing log";
|
||||||
log_buffer_flush_to_disk();
|
log_buffer_flush_to_disk();
|
||||||
@@ -2354,7 +2492,7 @@ loop:
|
|||||||
even if the server were active */
|
even if the server were active */
|
||||||
|
|
||||||
srv_main_thread_op_info = "doing insert buffer merge";
|
srv_main_thread_op_info = "doing insert buffer merge";
|
||||||
ibuf_contract_for_n_pages(TRUE, srv_insert_buffer_batch_size / 4);
|
ibuf_contract_for_n_pages(TRUE, PCT_IO((srv_insert_buffer_batch_size / 4)));
|
||||||
|
|
||||||
srv_main_thread_op_info = "flushing log";
|
srv_main_thread_op_info = "flushing log";
|
||||||
log_buffer_flush_to_disk();
|
log_buffer_flush_to_disk();
|
||||||
@@ -2394,14 +2532,14 @@ loop:
|
|||||||
(> 70 %), we assume we can afford reserving the disk(s) for
|
(> 70 %), we assume we can afford reserving the disk(s) for
|
||||||
the time it requires to flush 100 pages */
|
the time it requires to flush 100 pages */
|
||||||
|
|
||||||
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100,
|
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, PCT_IO(100),
|
||||||
IB_ULONGLONG_MAX);
|
IB_ULONGLONG_MAX);
|
||||||
} else {
|
} else {
|
||||||
/* Otherwise, we only flush a small number of pages so that
|
/* Otherwise, we only flush a small number of pages so that
|
||||||
we do not unnecessarily use much disk i/o capacity from
|
we do not unnecessarily use much disk i/o capacity from
|
||||||
other work */
|
other work */
|
||||||
|
|
||||||
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 10,
|
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, PCT_IO(10),
|
||||||
IB_ULONGLONG_MAX);
|
IB_ULONGLONG_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2489,7 +2627,7 @@ background_loop:
|
|||||||
n_bytes_merged = 0;
|
n_bytes_merged = 0;
|
||||||
} else {
|
} else {
|
||||||
n_bytes_merged = ibuf_contract_for_n_pages(
|
n_bytes_merged = ibuf_contract_for_n_pages(
|
||||||
TRUE, srv_insert_buffer_batch_size);
|
TRUE, PCT_IO((srv_insert_buffer_batch_size * 5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
srv_main_thread_op_info = "reserving kernel mutex";
|
srv_main_thread_op_info = "reserving kernel mutex";
|
||||||
@@ -2505,7 +2643,7 @@ flush_loop:
|
|||||||
srv_main_thread_op_info = "flushing buffer pool pages";
|
srv_main_thread_op_info = "flushing buffer pool pages";
|
||||||
|
|
||||||
if (srv_fast_shutdown < 2) {
|
if (srv_fast_shutdown < 2) {
|
||||||
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100,
|
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, PCT_IO(100),
|
||||||
IB_ULONGLONG_MAX);
|
IB_ULONGLONG_MAX);
|
||||||
} else {
|
} else {
|
||||||
/* In the fastest shutdown we do not flush the buffer pool
|
/* In the fastest shutdown we do not flush the buffer pool
|
||||||
|
|||||||
@@ -1204,24 +1204,28 @@ innobase_start_or_create_for_mysql(void)
|
|||||||
return(DB_ERROR);
|
return(DB_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* over write innodb_file_io_threads */
|
||||||
|
srv_n_file_io_threads = 2 + srv_n_read_io_threads + srv_n_write_io_threads;
|
||||||
|
|
||||||
/* Restrict the maximum number of file i/o threads */
|
/* Restrict the maximum number of file i/o threads */
|
||||||
if (srv_n_file_io_threads > SRV_MAX_N_IO_THREADS) {
|
if (srv_n_file_io_threads > SRV_MAX_N_IO_THREADS) {
|
||||||
|
|
||||||
srv_n_file_io_threads = SRV_MAX_N_IO_THREADS;
|
srv_n_file_io_threads = SRV_MAX_N_IO_THREADS;
|
||||||
|
srv_n_read_io_threads = srv_n_write_io_threads = (SRV_MAX_N_IO_THREADS - 2) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!os_aio_use_native_aio) {
|
if (!os_aio_use_native_aio) {
|
||||||
/* In simulated aio we currently have use only for 4 threads */
|
/* In simulated aio we currently have use only for 4 threads */
|
||||||
srv_n_file_io_threads = 4;
|
/*srv_n_file_io_threads = 4;*/
|
||||||
|
|
||||||
os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD
|
os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD
|
||||||
* srv_n_file_io_threads,
|
* srv_n_file_io_threads,
|
||||||
srv_n_file_io_threads,
|
srv_n_read_io_threads, srv_n_write_io_threads,
|
||||||
SRV_MAX_N_PENDING_SYNC_IOS);
|
SRV_MAX_N_PENDING_SYNC_IOS * 8);
|
||||||
} else {
|
} else {
|
||||||
os_aio_init(SRV_N_PENDING_IOS_PER_THREAD
|
os_aio_init(SRV_N_PENDING_IOS_PER_THREAD
|
||||||
* srv_n_file_io_threads,
|
* srv_n_file_io_threads,
|
||||||
srv_n_file_io_threads,
|
srv_n_read_io_threads, srv_n_write_io_threads,
|
||||||
SRV_MAX_N_PENDING_SYNC_IOS);
|
SRV_MAX_N_PENDING_SYNC_IOS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -307,13 +307,13 @@ sync_cell_event_reset(
|
|||||||
{
|
{
|
||||||
if (type == SYNC_MUTEX) {
|
if (type == SYNC_MUTEX) {
|
||||||
return(os_event_reset(((mutex_t *) object)->event));
|
return(os_event_reset(((mutex_t *) object)->event));
|
||||||
#ifdef __WIN__
|
|
||||||
} else if (type == RW_LOCK_WAIT_EX) {
|
} else if (type == RW_LOCK_WAIT_EX) {
|
||||||
return(os_event_reset(
|
return(os_event_reset(
|
||||||
((rw_lock_t *) object)->wait_ex_event));
|
((rw_lock_t *) object)->wait_ex_event));
|
||||||
#endif
|
} else if (type == RW_LOCK_SHARED) {
|
||||||
} else {
|
return(os_event_reset(((rw_lock_t *) object)->s_event));
|
||||||
return(os_event_reset(((rw_lock_t *) object)->event));
|
} else { /* RW_LOCK_EX */
|
||||||
|
return(os_event_reset(((rw_lock_t *) object)->x_event));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,15 +413,12 @@ sync_array_wait_event(
|
|||||||
|
|
||||||
if (cell->request_type == SYNC_MUTEX) {
|
if (cell->request_type == SYNC_MUTEX) {
|
||||||
event = ((mutex_t*) cell->wait_object)->event;
|
event = ((mutex_t*) cell->wait_object)->event;
|
||||||
#ifdef __WIN__
|
|
||||||
/* On windows if the thread about to wait is the one which
|
|
||||||
has set the state of the rw_lock to RW_LOCK_WAIT_EX, then
|
|
||||||
it waits on a special event i.e.: wait_ex_event. */
|
|
||||||
} else if (cell->request_type == RW_LOCK_WAIT_EX) {
|
} else if (cell->request_type == RW_LOCK_WAIT_EX) {
|
||||||
event = ((rw_lock_t*) cell->wait_object)->wait_ex_event;
|
event = ((rw_lock_t*) cell->wait_object)->wait_ex_event;
|
||||||
#endif
|
} else if (cell->request_type == RW_LOCK_SHARED) {
|
||||||
|
event = ((rw_lock_t*) cell->wait_object)->s_event;
|
||||||
} else {
|
} else {
|
||||||
event = ((rw_lock_t*) cell->wait_object)->event;
|
event = ((rw_lock_t*) cell->wait_object)->x_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
cell->waiting = TRUE;
|
cell->waiting = TRUE;
|
||||||
@@ -462,6 +459,7 @@ sync_array_cell_print(
|
|||||||
mutex_t* mutex;
|
mutex_t* mutex;
|
||||||
rw_lock_t* rwlock;
|
rw_lock_t* rwlock;
|
||||||
ulint type;
|
ulint type;
|
||||||
|
ulint writer;
|
||||||
|
|
||||||
type = cell->request_type;
|
type = cell->request_type;
|
||||||
|
|
||||||
@@ -491,12 +489,10 @@ sync_array_cell_print(
|
|||||||
(ulong) mutex->waiters);
|
(ulong) mutex->waiters);
|
||||||
|
|
||||||
} else if (type == RW_LOCK_EX
|
} else if (type == RW_LOCK_EX
|
||||||
#ifdef __WIN__
|
|
||||||
|| type == RW_LOCK_WAIT_EX
|
|| type == RW_LOCK_WAIT_EX
|
||||||
#endif
|
|
||||||
|| type == RW_LOCK_SHARED) {
|
|| type == RW_LOCK_SHARED) {
|
||||||
|
|
||||||
fputs(type == RW_LOCK_EX ? "X-lock on" : "S-lock on", file);
|
fputs(type == RW_LOCK_SHARED ? "S-lock on" : "X-lock on", file);
|
||||||
|
|
||||||
rwlock = cell->old_wait_rw_lock;
|
rwlock = cell->old_wait_rw_lock;
|
||||||
|
|
||||||
@@ -504,22 +500,24 @@ sync_array_cell_print(
|
|||||||
" RW-latch at %p created in file %s line %lu\n",
|
" RW-latch at %p created in file %s line %lu\n",
|
||||||
(void*) rwlock, rwlock->cfile_name,
|
(void*) rwlock, rwlock->cfile_name,
|
||||||
(ulong) rwlock->cline);
|
(ulong) rwlock->cline);
|
||||||
if (rwlock->writer != RW_LOCK_NOT_LOCKED) {
|
writer = rw_lock_get_writer(rwlock);
|
||||||
|
if (writer != RW_LOCK_NOT_LOCKED) {
|
||||||
fprintf(file,
|
fprintf(file,
|
||||||
"a writer (thread id %lu) has"
|
"a writer (thread id %lu) has"
|
||||||
" reserved it in mode %s",
|
" reserved it in mode %s",
|
||||||
(ulong) os_thread_pf(rwlock->writer_thread),
|
(ulong) os_thread_pf(rwlock->writer_thread),
|
||||||
rwlock->writer == RW_LOCK_EX
|
writer == RW_LOCK_EX
|
||||||
? " exclusive\n"
|
? " exclusive\n"
|
||||||
: " wait exclusive\n");
|
: " wait exclusive\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(file,
|
fprintf(file,
|
||||||
"number of readers %lu, waiters flag %lu\n"
|
"number of readers %lu, s_waiters flag %lu, x_waiters flag %lu\n"
|
||||||
"Last time read locked in file %s line %lu\n"
|
"Last time read locked in file %s line %lu\n"
|
||||||
"Last time write locked in file %s line %lu\n",
|
"Last time write locked in file %s line %lu\n",
|
||||||
(ulong) rwlock->reader_count,
|
(ulong) rwlock->reader_count,
|
||||||
(ulong) rwlock->waiters,
|
(ulong) rwlock->s_waiters,
|
||||||
|
(ulong) (rwlock->x_waiters || rwlock->wait_ex_waiters),
|
||||||
rwlock->last_s_file_name,
|
rwlock->last_s_file_name,
|
||||||
(ulong) rwlock->last_s_line,
|
(ulong) rwlock->last_s_line,
|
||||||
rwlock->last_x_file_name,
|
rwlock->last_x_file_name,
|
||||||
@@ -844,11 +842,15 @@ sync_array_object_signalled(
|
|||||||
/*========================*/
|
/*========================*/
|
||||||
sync_array_t* arr) /* in: wait array */
|
sync_array_t* arr) /* in: wait array */
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
__sync_fetch_and_add(&(arr->sg_count),1);
|
||||||
|
#else
|
||||||
sync_array_enter(arr);
|
sync_array_enter(arr);
|
||||||
|
|
||||||
arr->sg_count++;
|
arr->sg_count++;
|
||||||
|
|
||||||
sync_array_exit(arr);
|
sync_array_exit(arr);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
@@ -889,19 +891,23 @@ sync_arr_wake_threads_if_sema_free(void)
|
|||||||
|
|
||||||
mutex = cell->wait_object;
|
mutex = cell->wait_object;
|
||||||
os_event_set(mutex->event);
|
os_event_set(mutex->event);
|
||||||
#ifdef __WIN__
|
|
||||||
} else if (cell->request_type
|
} else if (cell->request_type
|
||||||
== RW_LOCK_WAIT_EX) {
|
== RW_LOCK_WAIT_EX) {
|
||||||
rw_lock_t* lock;
|
rw_lock_t* lock;
|
||||||
|
|
||||||
lock = cell->wait_object;
|
lock = cell->wait_object;
|
||||||
os_event_set(lock->wait_ex_event);
|
os_event_set(lock->wait_ex_event);
|
||||||
#endif
|
} else if (cell->request_type
|
||||||
} else {
|
== RW_LOCK_SHARED) {
|
||||||
rw_lock_t* lock;
|
rw_lock_t* lock;
|
||||||
|
|
||||||
lock = cell->wait_object;
|
lock = cell->wait_object;
|
||||||
os_event_set(lock->event);
|
os_event_set(lock->s_event);
|
||||||
|
} else {
|
||||||
|
rw_lock_t* lock;
|
||||||
|
|
||||||
|
lock = cell->wait_object;
|
||||||
|
os_event_set(lock->x_event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
284
sync/sync0rw.c
284
sync/sync0rw.c
@@ -119,6 +119,7 @@ rw_lock_create_func(
|
|||||||
/* If this is the very first time a synchronization object is
|
/* If this is the very first time a synchronization object is
|
||||||
created, then the following call initializes the sync system. */
|
created, then the following call initializes the sync system. */
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_create(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK);
|
mutex_create(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK);
|
||||||
|
|
||||||
lock->mutex.cfile_name = cfile_name;
|
lock->mutex.cfile_name = cfile_name;
|
||||||
@@ -128,8 +129,14 @@ rw_lock_create_func(
|
|||||||
lock->mutex.cmutex_name = cmutex_name;
|
lock->mutex.cmutex_name = cmutex_name;
|
||||||
lock->mutex.mutex_type = 1;
|
lock->mutex.mutex_type = 1;
|
||||||
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
|
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
|
||||||
|
#endif /* !HAVE_GCC_ATOMIC_BUILTINS */
|
||||||
|
|
||||||
rw_lock_set_waiters(lock, 0);
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
lock->lock_word = RW_LOCK_BIAS;
|
||||||
|
#endif
|
||||||
|
rw_lock_set_s_waiters(lock, 0);
|
||||||
|
rw_lock_set_x_waiters(lock, 0);
|
||||||
|
rw_lock_set_wx_waiters(lock, 0);
|
||||||
rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
|
rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
|
||||||
lock->writer_count = 0;
|
lock->writer_count = 0;
|
||||||
rw_lock_set_reader_count(lock, 0);
|
rw_lock_set_reader_count(lock, 0);
|
||||||
@@ -151,11 +158,9 @@ rw_lock_create_func(
|
|||||||
lock->last_x_file_name = "not yet reserved";
|
lock->last_x_file_name = "not yet reserved";
|
||||||
lock->last_s_line = 0;
|
lock->last_s_line = 0;
|
||||||
lock->last_x_line = 0;
|
lock->last_x_line = 0;
|
||||||
lock->event = os_event_create(NULL);
|
lock->s_event = os_event_create(NULL);
|
||||||
|
lock->x_event = os_event_create(NULL);
|
||||||
#ifdef __WIN__
|
|
||||||
lock->wait_ex_event = os_event_create(NULL);
|
lock->wait_ex_event = os_event_create(NULL);
|
||||||
#endif
|
|
||||||
|
|
||||||
mutex_enter(&rw_lock_list_mutex);
|
mutex_enter(&rw_lock_list_mutex);
|
||||||
|
|
||||||
@@ -181,19 +186,21 @@ rw_lock_free(
|
|||||||
{
|
{
|
||||||
ut_ad(rw_lock_validate(lock));
|
ut_ad(rw_lock_validate(lock));
|
||||||
ut_a(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED);
|
ut_a(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED);
|
||||||
ut_a(rw_lock_get_waiters(lock) == 0);
|
ut_a(rw_lock_get_s_waiters(lock) == 0);
|
||||||
|
ut_a(rw_lock_get_x_waiters(lock) == 0);
|
||||||
|
ut_a(rw_lock_get_wx_waiters(lock) == 0);
|
||||||
ut_a(rw_lock_get_reader_count(lock) == 0);
|
ut_a(rw_lock_get_reader_count(lock) == 0);
|
||||||
|
|
||||||
lock->magic_n = 0;
|
lock->magic_n = 0;
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_free(rw_lock_get_mutex(lock));
|
mutex_free(rw_lock_get_mutex(lock));
|
||||||
|
#endif
|
||||||
|
|
||||||
mutex_enter(&rw_lock_list_mutex);
|
mutex_enter(&rw_lock_list_mutex);
|
||||||
os_event_free(lock->event);
|
os_event_free(lock->s_event);
|
||||||
|
os_event_free(lock->x_event);
|
||||||
#ifdef __WIN__
|
|
||||||
os_event_free(lock->wait_ex_event);
|
os_event_free(lock->wait_ex_event);
|
||||||
#endif
|
|
||||||
|
|
||||||
if (UT_LIST_GET_PREV(list, lock)) {
|
if (UT_LIST_GET_PREV(list, lock)) {
|
||||||
ut_a(UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N);
|
ut_a(UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N);
|
||||||
@@ -211,6 +218,8 @@ rw_lock_free(
|
|||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
Checks that the rw-lock has been initialized and that there are no
|
Checks that the rw-lock has been initialized and that there are no
|
||||||
simultaneous shared and exclusive locks. */
|
simultaneous shared and exclusive locks. */
|
||||||
|
/* MEMO: If HAVE_GCC_ATOMIC_BUILTINS, we should use this function statically. */
|
||||||
|
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
ibool
|
ibool
|
||||||
rw_lock_validate(
|
rw_lock_validate(
|
||||||
@@ -219,7 +228,9 @@ rw_lock_validate(
|
|||||||
{
|
{
|
||||||
ut_a(lock);
|
ut_a(lock);
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_enter(rw_lock_get_mutex(lock));
|
mutex_enter(rw_lock_get_mutex(lock));
|
||||||
|
#endif
|
||||||
|
|
||||||
ut_a(lock->magic_n == RW_LOCK_MAGIC_N);
|
ut_a(lock->magic_n == RW_LOCK_MAGIC_N);
|
||||||
ut_a((rw_lock_get_reader_count(lock) == 0)
|
ut_a((rw_lock_get_reader_count(lock) == 0)
|
||||||
@@ -227,11 +238,17 @@ rw_lock_validate(
|
|||||||
ut_a((rw_lock_get_writer(lock) == RW_LOCK_EX)
|
ut_a((rw_lock_get_writer(lock) == RW_LOCK_EX)
|
||||||
|| (rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX)
|
|| (rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX)
|
||||||
|| (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED));
|
|| (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED));
|
||||||
ut_a((rw_lock_get_waiters(lock) == 0)
|
ut_a((rw_lock_get_s_waiters(lock) == 0)
|
||||||
|| (rw_lock_get_waiters(lock) == 1));
|
|| (rw_lock_get_s_waiters(lock) == 1));
|
||||||
|
ut_a((rw_lock_get_x_waiters(lock) == 0)
|
||||||
|
|| (rw_lock_get_x_waiters(lock) == 1));
|
||||||
|
ut_a((rw_lock_get_wx_waiters(lock) == 0)
|
||||||
|
|| (rw_lock_get_wx_waiters(lock) == 1));
|
||||||
ut_a((lock->writer != RW_LOCK_EX) || (lock->writer_count > 0));
|
ut_a((lock->writer != RW_LOCK_EX) || (lock->writer_count > 0));
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_exit(rw_lock_get_mutex(lock));
|
mutex_exit(rw_lock_get_mutex(lock));
|
||||||
|
#endif
|
||||||
|
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
}
|
}
|
||||||
@@ -258,13 +275,14 @@ rw_lock_s_lock_spin(
|
|||||||
ut_ad(rw_lock_validate(lock));
|
ut_ad(rw_lock_validate(lock));
|
||||||
|
|
||||||
lock_loop:
|
lock_loop:
|
||||||
|
i = 0;
|
||||||
|
spin_loop:
|
||||||
rw_s_spin_wait_count++;
|
rw_s_spin_wait_count++;
|
||||||
|
|
||||||
/* Spin waiting for the writer field to become free */
|
/* Spin waiting for the writer field to become free */
|
||||||
i = 0;
|
|
||||||
|
|
||||||
while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED
|
while (i < SYNC_SPIN_ROUNDS
|
||||||
&& i < SYNC_SPIN_ROUNDS) {
|
&& rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) {
|
||||||
if (srv_spin_wait_delay) {
|
if (srv_spin_wait_delay) {
|
||||||
ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
|
ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
|
||||||
}
|
}
|
||||||
@@ -285,15 +303,27 @@ lock_loop:
|
|||||||
lock->cfile_name, (ulong) lock->cline, (ulong) i);
|
lock->cfile_name, (ulong) lock->cline, (ulong) i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_enter(rw_lock_get_mutex(lock));
|
mutex_enter(rw_lock_get_mutex(lock));
|
||||||
|
#endif
|
||||||
|
|
||||||
/* We try once again to obtain the lock */
|
/* We try once again to obtain the lock */
|
||||||
|
|
||||||
if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) {
|
if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) {
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_exit(rw_lock_get_mutex(lock));
|
mutex_exit(rw_lock_get_mutex(lock));
|
||||||
|
#endif
|
||||||
|
|
||||||
return; /* Success */
|
return; /* Success */
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
/* like sync0sync.c doing */
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (i < SYNC_SPIN_ROUNDS) {
|
||||||
|
goto spin_loop;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* If we get here, locking did not succeed, we may
|
/* If we get here, locking did not succeed, we may
|
||||||
suspend the thread to wait in the wait array */
|
suspend the thread to wait in the wait array */
|
||||||
|
|
||||||
@@ -304,9 +334,19 @@ lock_loop:
|
|||||||
file_name, line,
|
file_name, line,
|
||||||
&index);
|
&index);
|
||||||
|
|
||||||
rw_lock_set_waiters(lock, 1);
|
rw_lock_set_s_waiters(lock, 1);
|
||||||
|
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
/* like sync0sync.c doing */
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) {
|
||||||
|
sync_array_free_cell(sync_primary_wait_array, index);
|
||||||
|
return; /* Success */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
mutex_exit(rw_lock_get_mutex(lock));
|
mutex_exit(rw_lock_get_mutex(lock));
|
||||||
|
#endif
|
||||||
|
|
||||||
if (srv_print_latch_waits) {
|
if (srv_print_latch_waits) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@@ -343,13 +383,19 @@ rw_lock_x_lock_move_ownership(
|
|||||||
{
|
{
|
||||||
ut_ad(rw_lock_is_locked(lock, RW_LOCK_EX));
|
ut_ad(rw_lock_is_locked(lock, RW_LOCK_EX));
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_enter(&(lock->mutex));
|
mutex_enter(&(lock->mutex));
|
||||||
|
#endif
|
||||||
|
|
||||||
lock->writer_thread = os_thread_get_curr_id();
|
lock->writer_thread = os_thread_get_curr_id();
|
||||||
|
|
||||||
lock->pass = 0;
|
lock->pass = 0;
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_exit(&(lock->mutex));
|
mutex_exit(&(lock->mutex));
|
||||||
|
#else
|
||||||
|
__sync_synchronize();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
@@ -367,6 +413,89 @@ rw_lock_x_lock_low(
|
|||||||
const char* file_name,/* in: file name where lock requested */
|
const char* file_name,/* in: file name where lock requested */
|
||||||
ulint line) /* in: line where requested */
|
ulint line) /* in: line where requested */
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
os_thread_id_t curr_thread = os_thread_get_curr_id();
|
||||||
|
|
||||||
|
/* try to lock writer */
|
||||||
|
if(__sync_lock_test_and_set(&(lock->writer),RW_LOCK_EX)
|
||||||
|
== RW_LOCK_NOT_LOCKED) {
|
||||||
|
/* success */
|
||||||
|
/* obtain RW_LOCK_WAIT_EX right */
|
||||||
|
lock->writer_thread = curr_thread;
|
||||||
|
lock->pass = pass;
|
||||||
|
lock->writer_is_wait_ex = TRUE;
|
||||||
|
/* atomic operation may be safer about memory order. */
|
||||||
|
__sync_synchronize();
|
||||||
|
#ifdef UNIV_SYNC_DEBUG
|
||||||
|
rw_lock_add_debug_info(lock, pass, RW_LOCK_WAIT_EX,
|
||||||
|
file_name, line);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!os_thread_eq(lock->writer_thread, curr_thread)) {
|
||||||
|
return(RW_LOCK_NOT_LOCKED);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(rw_lock_get_writer(lock)) {
|
||||||
|
case RW_LOCK_WAIT_EX:
|
||||||
|
/* have right to try x-lock */
|
||||||
|
if (lock->lock_word == RW_LOCK_BIAS) {
|
||||||
|
/* try x-lock */
|
||||||
|
if(__sync_sub_and_fetch(&(lock->lock_word),
|
||||||
|
RW_LOCK_BIAS) == 0) {
|
||||||
|
/* success */
|
||||||
|
lock->pass = pass;
|
||||||
|
lock->writer_is_wait_ex = FALSE;
|
||||||
|
__sync_fetch_and_add(&(lock->writer_count),1);
|
||||||
|
|
||||||
|
#ifdef UNIV_SYNC_DEBUG
|
||||||
|
rw_lock_remove_debug_info(lock, pass, RW_LOCK_WAIT_EX);
|
||||||
|
rw_lock_add_debug_info(lock, pass, RW_LOCK_EX,
|
||||||
|
file_name, line);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lock->last_x_file_name = file_name;
|
||||||
|
lock->last_x_line = line;
|
||||||
|
|
||||||
|
/* Locking succeeded, we may return */
|
||||||
|
return(RW_LOCK_EX);
|
||||||
|
} else {
|
||||||
|
/* fail */
|
||||||
|
__sync_fetch_and_add(&(lock->lock_word),
|
||||||
|
RW_LOCK_BIAS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* There are readers, we have to wait */
|
||||||
|
return(RW_LOCK_WAIT_EX);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RW_LOCK_EX:
|
||||||
|
/* already have x-lock */
|
||||||
|
if ((lock->pass == 0)&&(pass == 0)) {
|
||||||
|
__sync_fetch_and_add(&(lock->writer_count),1);
|
||||||
|
|
||||||
|
#ifdef UNIV_SYNC_DEBUG
|
||||||
|
rw_lock_add_debug_info(lock, pass, RW_LOCK_EX, file_name,
|
||||||
|
line);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lock->last_x_file_name = file_name;
|
||||||
|
lock->last_x_line = line;
|
||||||
|
|
||||||
|
/* Locking succeeded, we may return */
|
||||||
|
return(RW_LOCK_EX);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(RW_LOCK_NOT_LOCKED);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* ??? */
|
||||||
|
return(RW_LOCK_NOT_LOCKED);
|
||||||
|
}
|
||||||
|
#else /* HAVE_GCC_ATOMIC_BUILTINS */
|
||||||
|
|
||||||
ut_ad(mutex_own(rw_lock_get_mutex(lock)));
|
ut_ad(mutex_own(rw_lock_get_mutex(lock)));
|
||||||
|
|
||||||
if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
|
if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
|
||||||
@@ -447,6 +576,7 @@ rw_lock_x_lock_low(
|
|||||||
/* Locking succeeded, we may return */
|
/* Locking succeeded, we may return */
|
||||||
return(RW_LOCK_EX);
|
return(RW_LOCK_EX);
|
||||||
}
|
}
|
||||||
|
#endif /* HAVE_GCC_ATOMIC_BUILTINS */
|
||||||
|
|
||||||
/* Locking did not succeed */
|
/* Locking did not succeed */
|
||||||
return(RW_LOCK_NOT_LOCKED);
|
return(RW_LOCK_NOT_LOCKED);
|
||||||
@@ -472,19 +602,33 @@ rw_lock_x_lock_func(
|
|||||||
ulint line) /* in: line where requested */
|
ulint line) /* in: line where requested */
|
||||||
{
|
{
|
||||||
ulint index; /* index of the reserved wait cell */
|
ulint index; /* index of the reserved wait cell */
|
||||||
ulint state; /* lock state acquired */
|
ulint state = RW_LOCK_NOT_LOCKED; /* lock state acquired */
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
ulint prev_state = RW_LOCK_NOT_LOCKED;
|
||||||
|
#endif
|
||||||
ulint i; /* spin round count */
|
ulint i; /* spin round count */
|
||||||
|
|
||||||
ut_ad(rw_lock_validate(lock));
|
ut_ad(rw_lock_validate(lock));
|
||||||
|
|
||||||
lock_loop:
|
lock_loop:
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
prev_state = state;
|
||||||
|
#else
|
||||||
/* Acquire the mutex protecting the rw-lock fields */
|
/* Acquire the mutex protecting the rw-lock fields */
|
||||||
mutex_enter_fast(&(lock->mutex));
|
mutex_enter_fast(&(lock->mutex));
|
||||||
|
#endif
|
||||||
|
|
||||||
state = rw_lock_x_lock_low(lock, pass, file_name, line);
|
state = rw_lock_x_lock_low(lock, pass, file_name, line);
|
||||||
|
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
if (state != prev_state) i=0; /* if progress, reset counter. */
|
||||||
|
#else
|
||||||
mutex_exit(&(lock->mutex));
|
mutex_exit(&(lock->mutex));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
spin_loop:
|
||||||
if (state == RW_LOCK_EX) {
|
if (state == RW_LOCK_EX) {
|
||||||
|
|
||||||
return; /* Locking succeeded */
|
return; /* Locking succeeded */
|
||||||
@@ -492,10 +636,9 @@ lock_loop:
|
|||||||
} else if (state == RW_LOCK_NOT_LOCKED) {
|
} else if (state == RW_LOCK_NOT_LOCKED) {
|
||||||
|
|
||||||
/* Spin waiting for the writer field to become free */
|
/* Spin waiting for the writer field to become free */
|
||||||
i = 0;
|
|
||||||
|
|
||||||
while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED
|
while (i < SYNC_SPIN_ROUNDS
|
||||||
&& i < SYNC_SPIN_ROUNDS) {
|
&& rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) {
|
||||||
if (srv_spin_wait_delay) {
|
if (srv_spin_wait_delay) {
|
||||||
ut_delay(ut_rnd_interval(0,
|
ut_delay(ut_rnd_interval(0,
|
||||||
srv_spin_wait_delay));
|
srv_spin_wait_delay));
|
||||||
@@ -509,9 +652,12 @@ lock_loop:
|
|||||||
} else if (state == RW_LOCK_WAIT_EX) {
|
} else if (state == RW_LOCK_WAIT_EX) {
|
||||||
|
|
||||||
/* Spin waiting for the reader count field to become zero */
|
/* Spin waiting for the reader count field to become zero */
|
||||||
i = 0;
|
|
||||||
|
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
while (lock->lock_word != RW_LOCK_BIAS
|
||||||
|
#else
|
||||||
while (rw_lock_get_reader_count(lock) != 0
|
while (rw_lock_get_reader_count(lock) != 0
|
||||||
|
#endif
|
||||||
&& i < SYNC_SPIN_ROUNDS) {
|
&& i < SYNC_SPIN_ROUNDS) {
|
||||||
if (srv_spin_wait_delay) {
|
if (srv_spin_wait_delay) {
|
||||||
ut_delay(ut_rnd_interval(0,
|
ut_delay(ut_rnd_interval(0,
|
||||||
@@ -524,7 +670,6 @@ lock_loop:
|
|||||||
os_thread_yield();
|
os_thread_yield();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
i = 0; /* Eliminate a compiler warning */
|
|
||||||
ut_error;
|
ut_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,34 +686,69 @@ lock_loop:
|
|||||||
/* We try once again to obtain the lock. Acquire the mutex protecting
|
/* We try once again to obtain the lock. Acquire the mutex protecting
|
||||||
the rw-lock fields */
|
the rw-lock fields */
|
||||||
|
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
prev_state = state;
|
||||||
|
#else
|
||||||
mutex_enter(rw_lock_get_mutex(lock));
|
mutex_enter(rw_lock_get_mutex(lock));
|
||||||
|
#endif
|
||||||
|
|
||||||
state = rw_lock_x_lock_low(lock, pass, file_name, line);
|
state = rw_lock_x_lock_low(lock, pass, file_name, line);
|
||||||
|
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
if (state != prev_state) i=0; /* if progress, reset counter. */
|
||||||
|
#endif
|
||||||
|
|
||||||
if (state == RW_LOCK_EX) {
|
if (state == RW_LOCK_EX) {
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_exit(rw_lock_get_mutex(lock));
|
mutex_exit(rw_lock_get_mutex(lock));
|
||||||
|
#endif
|
||||||
|
|
||||||
return; /* Locking succeeded */
|
return; /* Locking succeeded */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
/* like sync0sync.c doing */
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (i < SYNC_SPIN_ROUNDS) {
|
||||||
|
goto spin_loop;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
rw_x_system_call_count++;
|
rw_x_system_call_count++;
|
||||||
|
|
||||||
sync_array_reserve_cell(sync_primary_wait_array,
|
sync_array_reserve_cell(sync_primary_wait_array,
|
||||||
lock,
|
lock,
|
||||||
#ifdef __WIN__
|
|
||||||
/* On windows RW_LOCK_WAIT_EX signifies
|
|
||||||
that this thread should wait on the
|
|
||||||
special wait_ex_event. */
|
|
||||||
(state == RW_LOCK_WAIT_EX)
|
(state == RW_LOCK_WAIT_EX)
|
||||||
? RW_LOCK_WAIT_EX :
|
? RW_LOCK_WAIT_EX :
|
||||||
#endif
|
|
||||||
RW_LOCK_EX,
|
RW_LOCK_EX,
|
||||||
file_name, line,
|
file_name, line,
|
||||||
&index);
|
&index);
|
||||||
|
|
||||||
rw_lock_set_waiters(lock, 1);
|
if (state == RW_LOCK_WAIT_EX) {
|
||||||
|
rw_lock_set_wx_waiters(lock, 1);
|
||||||
|
} else {
|
||||||
|
rw_lock_set_x_waiters(lock, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
|
/* like sync0sync.c doing */
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
prev_state = state;
|
||||||
|
state = rw_lock_x_lock_low(lock, pass, file_name, line);
|
||||||
|
if (state == RW_LOCK_EX) {
|
||||||
|
sync_array_free_cell(sync_primary_wait_array, index);
|
||||||
|
return; /* Locking succeeded */
|
||||||
|
}
|
||||||
|
if (state != prev_state) {
|
||||||
|
/* retry! */
|
||||||
|
sync_array_free_cell(sync_primary_wait_array, index);
|
||||||
|
goto lock_loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
mutex_exit(rw_lock_get_mutex(lock));
|
mutex_exit(rw_lock_get_mutex(lock));
|
||||||
|
#endif
|
||||||
|
|
||||||
if (srv_print_latch_waits) {
|
if (srv_print_latch_waits) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@@ -730,7 +910,9 @@ rw_lock_own(
|
|||||||
ut_ad(lock);
|
ut_ad(lock);
|
||||||
ut_ad(rw_lock_validate(lock));
|
ut_ad(rw_lock_validate(lock));
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_enter(&(lock->mutex));
|
mutex_enter(&(lock->mutex));
|
||||||
|
#endif
|
||||||
|
|
||||||
info = UT_LIST_GET_FIRST(lock->debug_list);
|
info = UT_LIST_GET_FIRST(lock->debug_list);
|
||||||
|
|
||||||
@@ -740,7 +922,9 @@ rw_lock_own(
|
|||||||
&& (info->pass == 0)
|
&& (info->pass == 0)
|
||||||
&& (info->lock_type == lock_type)) {
|
&& (info->lock_type == lock_type)) {
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_exit(&(lock->mutex));
|
mutex_exit(&(lock->mutex));
|
||||||
|
#endif
|
||||||
/* Found! */
|
/* Found! */
|
||||||
|
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
@@ -748,7 +932,9 @@ rw_lock_own(
|
|||||||
|
|
||||||
info = UT_LIST_GET_NEXT(list, info);
|
info = UT_LIST_GET_NEXT(list, info);
|
||||||
}
|
}
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_exit(&(lock->mutex));
|
mutex_exit(&(lock->mutex));
|
||||||
|
#endif
|
||||||
|
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
}
|
}
|
||||||
@@ -770,21 +956,25 @@ rw_lock_is_locked(
|
|||||||
ut_ad(lock);
|
ut_ad(lock);
|
||||||
ut_ad(rw_lock_validate(lock));
|
ut_ad(rw_lock_validate(lock));
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_enter(&(lock->mutex));
|
mutex_enter(&(lock->mutex));
|
||||||
|
#endif
|
||||||
|
|
||||||
if (lock_type == RW_LOCK_SHARED) {
|
if (lock_type == RW_LOCK_SHARED) {
|
||||||
if (lock->reader_count > 0) {
|
if (lock->reader_count > 0) {
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
} else if (lock_type == RW_LOCK_EX) {
|
} else if (lock_type == RW_LOCK_EX) {
|
||||||
if (lock->writer == RW_LOCK_EX) {
|
if (rw_lock_get_writer(lock) == RW_LOCK_EX) {
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ut_error;
|
ut_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_exit(&(lock->mutex));
|
mutex_exit(&(lock->mutex));
|
||||||
|
#endif
|
||||||
|
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
@@ -814,16 +1004,26 @@ rw_lock_list_print_info(
|
|||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_enter(&(lock->mutex));
|
mutex_enter(&(lock->mutex));
|
||||||
|
#endif
|
||||||
|
|
||||||
if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
|
if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
|
||||||
|| (rw_lock_get_reader_count(lock) != 0)
|
|| (rw_lock_get_reader_count(lock) != 0)
|
||||||
|| (rw_lock_get_waiters(lock) != 0)) {
|
|| (rw_lock_get_s_waiters(lock) != 0)
|
||||||
|
|| (rw_lock_get_x_waiters(lock) != 0)
|
||||||
|
|| (rw_lock_get_wx_waiters(lock) != 0)) {
|
||||||
|
|
||||||
fprintf(file, "RW-LOCK: %p ", (void*) lock);
|
fprintf(file, "RW-LOCK: %p ", (void*) lock);
|
||||||
|
|
||||||
if (rw_lock_get_waiters(lock)) {
|
if (rw_lock_get_s_waiters(lock)) {
|
||||||
fputs(" Waiters for the lock exist\n", file);
|
fputs(" s_waiters for the lock exist,", file);
|
||||||
|
}
|
||||||
|
if (rw_lock_get_x_waiters(lock)) {
|
||||||
|
fputs(" x_waiters for the lock exist\n", file);
|
||||||
|
}
|
||||||
|
if (rw_lock_get_wx_waiters(lock)) {
|
||||||
|
fputs(" wait_ex_waiters for the lock exist\n", file);
|
||||||
} else {
|
} else {
|
||||||
putc('\n', file);
|
putc('\n', file);
|
||||||
}
|
}
|
||||||
@@ -835,7 +1035,9 @@ rw_lock_list_print_info(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_exit(&(lock->mutex));
|
mutex_exit(&(lock->mutex));
|
||||||
|
#endif
|
||||||
lock = UT_LIST_GET_NEXT(list, lock);
|
lock = UT_LIST_GET_NEXT(list, lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -860,10 +1062,18 @@ rw_lock_print(
|
|||||||
|
|
||||||
if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
|
if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
|
||||||
|| (rw_lock_get_reader_count(lock) != 0)
|
|| (rw_lock_get_reader_count(lock) != 0)
|
||||||
|| (rw_lock_get_waiters(lock) != 0)) {
|
|| (rw_lock_get_s_waiters(lock) != 0)
|
||||||
|
|| (rw_lock_get_x_waiters(lock) != 0)
|
||||||
|
|| (rw_lock_get_wx_waiters(lock) != 0)) {
|
||||||
|
|
||||||
if (rw_lock_get_waiters(lock)) {
|
if (rw_lock_get_s_waiters(lock)) {
|
||||||
fputs(" Waiters for the lock exist\n", stderr);
|
fputs(" s_waiters for the lock exist,", stderr);
|
||||||
|
}
|
||||||
|
if (rw_lock_get_x_waiters(lock)) {
|
||||||
|
fputs(" x_waiters for the lock exist\n", stderr);
|
||||||
|
}
|
||||||
|
if (rw_lock_get_wx_waiters(lock)) {
|
||||||
|
fputs(" wait_ex_waiters for the lock exist\n", stderr);
|
||||||
} else {
|
} else {
|
||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
}
|
}
|
||||||
@@ -922,14 +1132,18 @@ rw_lock_n_locked(void)
|
|||||||
lock = UT_LIST_GET_FIRST(rw_lock_list);
|
lock = UT_LIST_GET_FIRST(rw_lock_list);
|
||||||
|
|
||||||
while (lock != NULL) {
|
while (lock != NULL) {
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_enter(rw_lock_get_mutex(lock));
|
mutex_enter(rw_lock_get_mutex(lock));
|
||||||
|
#endif
|
||||||
|
|
||||||
if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
|
if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
|
||||||
|| (rw_lock_get_reader_count(lock) != 0)) {
|
|| (rw_lock_get_reader_count(lock) != 0)) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef HAVE_GCC_ATOMIC_BUILTINS
|
||||||
mutex_exit(rw_lock_get_mutex(lock));
|
mutex_exit(rw_lock_get_mutex(lock));
|
||||||
|
#endif
|
||||||
lock = UT_LIST_GET_NEXT(list, lock);
|
lock = UT_LIST_GET_NEXT(list, lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ static mutex_t thr_local_mutex;
|
|||||||
|
|
||||||
/* The hash table. The module is not yet initialized when it is NULL. */
|
/* The hash table. The module is not yet initialized when it is NULL. */
|
||||||
static hash_table_t* thr_local_hash = NULL;
|
static hash_table_t* thr_local_hash = NULL;
|
||||||
|
ulint thr_local_hash_n_nodes = 0;
|
||||||
|
|
||||||
/* The private data for each thread should be put to
|
/* The private data for each thread should be put to
|
||||||
the structure below and the accessor functions written
|
the structure below and the accessor functions written
|
||||||
@@ -177,6 +178,7 @@ thr_local_create(void)
|
|||||||
os_thread_pf(os_thread_get_curr_id()),
|
os_thread_pf(os_thread_get_curr_id()),
|
||||||
local);
|
local);
|
||||||
|
|
||||||
|
thr_local_hash_n_nodes++;
|
||||||
mutex_exit(&thr_local_mutex);
|
mutex_exit(&thr_local_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,6 +206,7 @@ thr_local_free(
|
|||||||
|
|
||||||
HASH_DELETE(thr_local_t, hash, thr_local_hash,
|
HASH_DELETE(thr_local_t, hash, thr_local_hash,
|
||||||
os_thread_pf(id), local);
|
os_thread_pf(id), local);
|
||||||
|
thr_local_hash_n_nodes--;
|
||||||
|
|
||||||
mutex_exit(&thr_local_mutex);
|
mutex_exit(&thr_local_mutex);
|
||||||
|
|
||||||
@@ -226,3 +229,29 @@ thr_local_init(void)
|
|||||||
|
|
||||||
mutex_create(&thr_local_mutex, SYNC_THR_LOCAL);
|
mutex_create(&thr_local_mutex, SYNC_THR_LOCAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Return local hash table informations. */
|
||||||
|
|
||||||
|
ulint
|
||||||
|
thr_local_hash_cells(void)
|
||||||
|
/*======================*/
|
||||||
|
{
|
||||||
|
if (thr_local_hash) {
|
||||||
|
return (thr_local_hash->n_cells);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ulint
|
||||||
|
thr_local_hash_nodes(void)
|
||||||
|
/*======================*/
|
||||||
|
{
|
||||||
|
if (thr_local_hash) {
|
||||||
|
return (thr_local_hash_n_nodes
|
||||||
|
* (sizeof(thr_local_t) + MEM_BLOCK_HEADER_SIZE));
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user