branches/innodb+: Merge branches/perfschema back into innodb+.

Check in code change for implementing Performace Schema in InnoDB.
Objects in four different modules in InnoDB have been performance
instrumented, these modules are:
1) mutexes
2) rwlocks
3) file I/O
4) threads

We mostly preserved the existing APIs, but APIs would point to
instrumented function wrappers if performance schema is defined.
There are 4 different defines that controls the instrumentation of
each module.  The feature is off by default, and will be compiled in
with special build option, and requre configure option to turn it on
when server boots.  For more detail design and functional information,
please refer to performance schema wiki page.

rb://270 approved by Marko Mäkelä
This commit is contained in:
jyang 2010-03-29 07:34:42 +00:00
parent 9e85abaea1
commit cefc7748b2
38 changed files with 2431 additions and 256 deletions

View file

@ -117,6 +117,7 @@ noinst_HEADERS= \
include/mtr0types.h \
include/mysql_addons.h \
include/os0file.h \
include/os0file.ic \
include/os0proc.h \
include/os0proc.ic \
include/os0sync.h \

View file

@ -50,6 +50,11 @@ UNIV_INTERN char btr_search_enabled = TRUE;
/** Mutex protecting btr_search_enabled */
static mutex_t btr_search_enabled_mutex;
#ifdef UNIV_PFS_MUTEX
/* Key to register btr_search_enabled_mutex with performance schema */
UNIV_INTERN mysql_pfs_key_t btr_search_enabled_mutex_key;
#endif /* UNIV_PFS_MUTEX */
/** A dummy variable to fool the compiler */
UNIV_INTERN ulint btr_search_this_is_zero = 0;
@ -82,6 +87,11 @@ UNIV_INTERN byte btr_sea_pad2[64];
/** The adaptive hash index */
UNIV_INTERN btr_search_sys_t* btr_search_sys;
#ifdef UNIV_PFS_RWLOCK
/* Key to register btr_search_sys with performance schema */
UNIV_INTERN mysql_pfs_key_t btr_search_latch_key;
#endif /* UNIV_PFS_RWLOCK */
/** If the number of records on the page divided by this parameter
would have been successfully accessed using a hash index, the index
is then built on the page, assuming the global limit has been reached */
@ -167,8 +177,10 @@ btr_search_sys_create(
btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t));
rw_lock_create(&btr_search_latch, SYNC_SEARCH_SYS);
mutex_create(&btr_search_enabled_mutex, SYNC_SEARCH_SYS_CONF);
rw_lock_create(btr_search_latch_key, &btr_search_latch,
SYNC_SEARCH_SYS);
mutex_create(btr_search_enabled_mutex_key,
&btr_search_enabled_mutex, SYNC_SEARCH_SYS_CONF);
btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));

View file

@ -270,6 +270,22 @@ read-ahead or flush occurs */
UNIV_INTERN ibool buf_debug_prints = FALSE;
#endif /* UNIV_DEBUG */
#ifdef UNIV_PFS_RWLOCK
/* Keys to register buffer block related rwlocks and mutexes with
performance schema */
UNIV_INTERN mysql_pfs_key_t buf_block_lock_key;
# ifdef UNIV_SYNC_DEBUG
UNIV_INTERN mysql_pfs_key_t buf_block_debug_latch_key;
# endif /* UNIV_SYNC_DEBUG */
#endif /* UNIV_PFS_RWLOCK */
#ifdef UNIV_PFS_MUTEX
UNIV_INTERN mysql_pfs_key_t buffer_block_mutex_key;
UNIV_INTERN mysql_pfs_key_t buf_pool_mutex_key;
UNIV_INTERN mysql_pfs_key_t buf_pool_zip_mutex_key;
UNIV_INTERN mysql_pfs_key_t flush_list_mutex_key;
#endif /* UNIV_PFS_MUTEX */
/** A chunk of buffers. The buffer pool is allocated in chunks. */
struct buf_chunk_struct{
ulint mem_size; /*!< allocated size of the chunk */
@ -678,13 +694,15 @@ buf_block_init(
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
page_zip_des_init(&block->page.zip);
mutex_create(&block->mutex, SYNC_BUF_BLOCK);
mutex_create(buffer_block_mutex_key,
&block->mutex, SYNC_BUF_BLOCK);
rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
rw_lock_create(buf_block_lock_key, &block->lock, SYNC_LEVEL_VARYING);
ut_ad(rw_lock_validate(&(block->lock)));
#ifdef UNIV_SYNC_DEBUG
rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
rw_lock_create(buf_block_debug_latch_key,
&block->debug_latch, SYNC_NO_ORDER_CHECK);
#endif /* UNIV_SYNC_DEBUG */
}
@ -955,8 +973,10 @@ buf_pool_init(void)
/* 1. Initialize general fields
------------------------------- */
mutex_create(&buf_pool_mutex, SYNC_BUF_POOL);
mutex_create(&buf_pool_zip_mutex, SYNC_BUF_BLOCK);
mutex_create(buf_pool_mutex_key,
&buf_pool_mutex, SYNC_BUF_POOL);
mutex_create(buf_pool_zip_mutex_key,
&buf_pool_zip_mutex, SYNC_BUF_BLOCK);
buf_pool_mutex_enter();
@ -984,7 +1004,8 @@ buf_pool_init(void)
/* 2. Initialize flushing fields
-------------------------------- */
mutex_create(&buf_pool->flush_list_mutex, SYNC_BUF_FLUSH_LIST);
mutex_create(flush_list_mutex_key, &buf_pool->flush_list_mutex,
SYNC_BUF_FLUSH_LIST);
for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
buf_pool->no_flush[i] = os_event_create(NULL);
}

View file

@ -70,6 +70,17 @@ we need this; NOTE: a transaction which reserves this must keep book
on the mode in trx_struct::dict_operation_lock_mode */
UNIV_INTERN rw_lock_t dict_operation_lock;
/* Keys to register rwlocks and mutexes with performance schema */
#ifdef UNIV_PFS_RWLOCK
UNIV_INTERN mysql_pfs_key_t dict_operation_lock_key;
UNIV_INTERN mysql_pfs_key_t index_tree_rw_lock_key;
#endif /* UNIV_PFS_RWLOCK */
#ifdef UNIV_PFS_MUTEX
UNIV_INTERN mysql_pfs_key_t dict_sys_mutex_key;
UNIV_INTERN mysql_pfs_key_t dict_foreign_err_mutex_key;
#endif /* UNIV_PFS_MUTEX */
#define DICT_HEAP_SIZE 100 /*!< initial memory heap size when
creating a table or index object */
#define DICT_POOL_PER_TABLE_HASH 512 /*!< buffer pool max size per table
@ -607,7 +618,7 @@ dict_init(void)
{
dict_sys = mem_alloc(sizeof(dict_sys_t));
mutex_create(&dict_sys->mutex, SYNC_DICT);
mutex_create(dict_sys_mutex_key, &dict_sys->mutex, SYNC_DICT);
dict_sys->table_hash = hash_create(buf_pool_get_curr_size()
/ (DICT_POOL_PER_TABLE_HASH
@ -619,12 +630,14 @@ dict_init(void)
UT_LIST_INIT(dict_sys->table_LRU);
rw_lock_create(&dict_operation_lock, SYNC_DICT_OPERATION);
rw_lock_create(dict_operation_lock_key,
&dict_operation_lock, SYNC_DICT_OPERATION);
dict_foreign_err_file = os_file_create_tmpfile();
ut_a(dict_foreign_err_file);
mutex_create(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
mutex_create(dict_foreign_err_mutex_key,
&dict_foreign_err_mutex, SYNC_ANY_LATCH);
}
/**********************************************************************//**
@ -1567,7 +1580,8 @@ undo_size_ok:
new_index->stat_n_leaf_pages = 1;
new_index->page = page_no;
rw_lock_create(&new_index->lock, SYNC_INDEX_TREE);
rw_lock_create(index_tree_rw_lock_key, &new_index->lock,
SYNC_INDEX_TREE);
if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {

View file

@ -40,6 +40,11 @@ Created 1/8/1996 Heikki Tuuri
#define DICT_HEAP_SIZE 100 /*!< initial memory heap size when
creating a table or index object */
#ifdef UNIV_PFS_MUTEX
/* Key to register autoinc_mutex with performance schema */
UNIV_INTERN mysql_pfs_key_t autoinc_mutex_key;
#endif /* UNIV_PFS_MUTEX */
/**********************************************************************//**
Creates a table memory object.
@return own: table object */
@ -78,7 +83,8 @@ dict_mem_table_create(
#ifndef UNIV_HOTBACKUP
table->autoinc_lock = mem_heap_alloc(heap, lock_get_size());
mutex_create(&table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX);
mutex_create(autoinc_mutex_key,
&table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX);
table->autoinc = 0;

View file

@ -121,6 +121,16 @@ UNIV_INTERN ulint fil_n_pending_tablespace_flushes = 0;
/** The null file address */
UNIV_INTERN fil_addr_t fil_addr_null = {FIL_NULL, 0};
#ifdef UNIV_PFS_MUTEX
/* Key to register fil_system_mutex with performance schema */
UNIV_INTERN mysql_pfs_key_t fil_system_mutex_key;
#endif /* UNIV_PFS_MUTEX */
#ifdef UNIV_PFS_RWLOCK
/* Key to register file space latch with performance schema */
UNIV_INTERN mysql_pfs_key_t fil_space_latch_key;
#endif /* UNIV_PFS_RWLOCK */
/** File node of a tablespace or the log data space */
struct fil_node_struct {
fil_space_t* space; /*!< backpointer to the space where this node
@ -649,7 +659,8 @@ fil_node_open_file(
async I/O! */
node->handle = os_file_create_simple_no_error_handling(
node->name, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success);
innodb_file_data_key, node->name, OS_FILE_OPEN,
OS_FILE_READ_ONLY, &success);
if (!success) {
/* The following call prints an error message */
os_file_get_last_error(TRUE);
@ -767,15 +778,21 @@ add_size:
os_file_create() to fall back to the normal file I/O mode. */
if (space->purpose == FIL_LOG) {
node->handle = os_file_create(node->name, OS_FILE_OPEN,
OS_FILE_AIO, OS_LOG_FILE, &ret);
node->handle = os_file_create(innodb_file_log_key,
node->name, OS_FILE_OPEN,
OS_FILE_AIO, OS_LOG_FILE,
&ret);
} else if (node->is_raw_disk) {
node->handle = os_file_create(node->name,
node->handle = os_file_create(innodb_file_data_key,
node->name,
OS_FILE_OPEN_RAW,
OS_FILE_AIO, OS_DATA_FILE, &ret);
OS_FILE_AIO, OS_DATA_FILE,
&ret);
} else {
node->handle = os_file_create(node->name, OS_FILE_OPEN,
OS_FILE_AIO, OS_DATA_FILE, &ret);
node->handle = os_file_create(innodb_file_data_key,
node->name, OS_FILE_OPEN,
OS_FILE_AIO, OS_DATA_FILE,
&ret);
}
ut_a(ret);
@ -1212,7 +1229,7 @@ try_again:
UT_LIST_INIT(space->chain);
space->magic_n = FIL_SPACE_MAGIC_N;
rw_lock_create(&space->latch, SYNC_FSP);
rw_lock_create(fil_space_latch_key, &space->latch, SYNC_FSP);
HASH_INSERT(fil_space_t, hash, fil_system->spaces, id, space);
@ -1514,7 +1531,8 @@ fil_init(
fil_system = mem_alloc(sizeof(fil_system_t));
mutex_create(&fil_system->mutex, SYNC_ANY_LATCH);
mutex_create(fil_system_mutex_key,
&fil_system->mutex, SYNC_ANY_LATCH);
fil_system->spaces = hash_create(hash_size);
fil_system->name_hash = hash_create(hash_size);
@ -2519,7 +2537,7 @@ retry:
success = fil_rename_tablespace_in_mem(space, node, path);
if (success) {
success = os_file_rename(old_path, path);
success = os_file_rename(innodb_file_data_key, old_path, path);
if (!success) {
/* We have to revert the changes we made
@ -2596,7 +2614,8 @@ fil_create_new_single_table_tablespace(
path = fil_make_ibd_name(tablename, is_temp);
file = os_file_create(path, OS_FILE_CREATE, OS_FILE_NORMAL,
file = os_file_create(innodb_file_data_key, path,
OS_FILE_CREATE, OS_FILE_NORMAL,
OS_DATA_FILE, &ret);
if (ret == FALSE) {
ut_print_timestamp(stderr);
@ -2798,7 +2817,8 @@ fil_reset_too_high_lsns(
filepath = fil_make_ibd_name(name, FALSE);
file = os_file_create_simple_no_error_handling(
filepath, OS_FILE_OPEN, OS_FILE_READ_WRITE, &success);
innodb_file_data_key, filepath, OS_FILE_OPEN,
OS_FILE_READ_WRITE, &success);
if (!success) {
/* The following call prints an error message */
os_file_get_last_error(TRUE);
@ -2982,7 +3002,8 @@ fil_open_single_table_tablespace(
ut_a(!(flags & (~0UL << DICT_TF_BITS)));
file = os_file_create_simple_no_error_handling(
filepath, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success);
innodb_file_data_key, filepath, OS_FILE_OPEN,
OS_FILE_READ_ONLY, &success);
if (!success) {
/* The following call prints an error message */
os_file_get_last_error(TRUE);
@ -3138,7 +3159,8 @@ fil_load_single_table_tablespace(
# endif /* !UNIV_HOTBACKUP */
#endif
file = os_file_create_simple_no_error_handling(
filepath, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success);
innodb_file_data_key, filepath, OS_FILE_OPEN,
OS_FILE_READ_ONLY, &success);
if (!success) {
/* The following call prints an error message */
os_file_get_last_error(TRUE);
@ -3296,7 +3318,7 @@ fil_load_single_table_tablespace(
os_file_close(file);
new_path = fil_make_ibbackup_old_name(filepath);
ut_a(os_file_rename(filepath, new_path));
ut_a(os_file_rename(innodb_file_data_key, filepath, new_path));
ut_free(buf2);
mem_free(filepath);
@ -3334,7 +3356,7 @@ fil_load_single_table_tablespace(
mutex_exit(&fil_system->mutex);
ut_a(os_file_rename(filepath, new_path));
ut_a(os_file_rename(innodb_file_data_key, filepath, new_path));
ut_free(buf2);
mem_free(filepath);

View file

@ -31,6 +31,11 @@ Created 5/20/1997 Heikki Tuuri
#include "mem0mem.h"
#ifndef UNIV_HOTBACKUP
# ifdef UNIV_PFS_MUTEX
UNIV_INTERN mysql_pfs_key_t hash_table_mutex_key;
# endif /* UNIV_PFS_MUTEX */
/************************************************************//**
Reserves the mutex for a fold value in a hash table. */
UNIV_INTERN
@ -166,7 +171,8 @@ hash_create_mutexes_func(
table->mutexes = mem_alloc(n_mutexes * sizeof(mutex_t));
for (i = 0; i < n_mutexes; i++) {
mutex_create(table->mutexes + i, sync_level);
mutex_create(hash_table_mutex_key,
table->mutexes + i, sync_level);
}
table->n_mutexes = n_mutexes;

View file

@ -48,6 +48,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include <m_ctype.h>
#include <mysys_err.h>
#include <mysql/plugin.h>
#include <mysql/psi/psi.h>
/** @file ha_innodb.cc */
@ -101,14 +102,14 @@ bool check_global_access(THD *thd, ulong want_access);
#endif /* MYSQL_SERVER */
/** to protect innobase_open_files */
static pthread_mutex_t innobase_share_mutex;
static mysql_mutex_t innobase_share_mutex;
/** to force correct commit order in binlog */
static pthread_mutex_t prepare_commit_mutex;
static mysql_mutex_t prepare_commit_mutex;
static ulong commit_threads = 0;
static pthread_mutex_t commit_threads_m;
static pthread_cond_t commit_cond;
static pthread_mutex_t commit_cond_m;
static pthread_mutex_t analyze_mutex;
static mysql_mutex_t commit_threads_m;
static mysql_cond_t commit_cond;
static mysql_mutex_t commit_cond_m;
static mysql_mutex_t analyze_mutex;
static bool innodb_inited = 0;
#define INSIDE_HA_INNOBASE_CC
@ -199,6 +200,126 @@ static const char* innobase_change_buffering_values[IBUF_USE_COUNT] = {
"all" /* IBUF_USE_ALL */
};
#ifdef HAVE_PSI_INTERFACE
/* Keys to register pthread mutexes/cond in the current file with
performance schema */
static mysql_pfs_key_t innobase_share_mutex_key;
static mysql_pfs_key_t prepare_commit_mutex_key;
static mysql_pfs_key_t commit_threads_m_key;
static mysql_pfs_key_t analyze_mutex_key;
static mysql_pfs_key_t commit_cond_mutex_key;
static mysql_pfs_key_t commit_cond_key;
static PSI_mutex_info all_pthread_mutexes[] = {
{&analyze_mutex_key, "analyze_mutex", 0},
{&commit_threads_m_key, "commit_threads_m", 0},
{&commit_cond_mutex_key, "commit_cond_mutex", 0},
{&innobase_share_mutex_key, "innobase_share_mutex", 0},
{&prepare_commit_mutex_key, "prepare_commit_mutex", 0}
};
static PSI_cond_info all_innodb_conds[] = {
{&commit_cond_key, "commit_cond", 0}
};
# ifdef UNIV_PFS_MUTEX
/* all_innodb_mutexes array contains mutexes that are
performance schema instrumented if "UNIV_PFS_MUTEX"
is defined */
static PSI_mutex_info all_innodb_mutexes[] = {
{&autoinc_mutex_key, "autoinc_mutex", 0},
{&btr_search_enabled_mutex_key, "btr_search_enabled_mutex", 0},
{&buffer_block_mutex_key, "buffer_block_mutex", 0},
{&buf_pool_mutex_key, "buf_pool_mutex", 0},
{&buf_pool_zip_mutex_key, "buf_pool_zip_mutex", 0},
{&cache_last_read_mutex_key, "cache_last_read_mutex", 0},
{&dict_foreign_err_mutex_key, "dict_foreign_err_mutex", 0},
{&dict_sys_mutex_key, "dict_sys_mutex", 0},
{&file_format_max_mutex_key, "file_format_max_mutex", 0},
{&fil_system_mutex_key, "fil_system_mutex", 0},
{&flush_list_mutex_key, "flush_list_mutex", 0},
{&hash_table_mutex_key, "hash_table_mutex", 0},
{&ibuf_bitmap_mutex_key, "ibuf_bitmap_mutex", 0},
{&ibuf_mutex_key, "ibuf_mutex", 0},
{&ibuf_pessimistic_insert_mutex_key,
"ibuf_pessimistic_insert_mutex", 0},
{&ios_mutex_key, "ios_mutex", 0},
{&kernel_mutex_key, "kernel_mutex", 0},
{&log_sys_mutex_key, "log_sys_mutex", 0},
# ifdef UNIV_MEM_DEBUG
{&mem_hash_mutex_key, "mem_hash_mutex", 0},
# endif /* UNIV_MEM_DEBUG */
{&mem_pool_mutex_key, "mem_pool_mutex", 0},
{&mutex_list_mutex_key, "mutex_list_mutex", 0},
{&purge_sys_mutex_key, "purge_sys_mutex", 0},
{&recv_sys_mutex_key, "recv_sys_mutex", 0},
{&rseg_mutex_key, "rseg_mutex", 0},
# ifdef UNIV_SYNC_DEBUG
{&rw_lock_debug_mutex_key, "rw_lock_debug_mutex", 0},
# endif /* UNIV_SYNC_DEBUG */
{&rw_lock_list_mutex_key, "rw_lock_list_mutex", 0},
{&rw_lock_mutex_key, "rw_lock_mutex", 0},
{&srv_dict_tmpfile_mutex_key, "srv_dict_tmpfile_mutex", 0},
{&srv_innodb_monitor_mutex_key, "srv_innodb_monitor_mutex", 0},
{&srv_misc_tmpfile_mutex_key, "srv_misc_tmpfile_mutex", 0},
{&srv_monitor_file_mutex_key, "srv_monitor_file_mutex", 0},
{&syn_arr_mutex_key, "syn_arr_mutex", 0},
# ifdef UNIV_SYNC_DEBUG
{&sync_thread_mutex_key, "sync_thread_mutex", 0},
# endif /* UNIV_SYNC_DEBUG */
{&trx_doublewrite_mutex_key, "trx_doublewrite_mutex", 0},
{&thr_local_mutex_key, "thr_local_mutex", 0},
{&trx_undo_mutex_key, "trx_undo_mutex", 0},
{&wq_mutex_key, "wq_mutex", 0}
};
# endif /* UNIV_PFS_MUTEX */
# ifdef UNIV_PFS_RWLOCK
/* all_innodb_rwlocks array contains rwlocks that are
performance schema instrumented if "UNIV_PFS_RWLOCK"
is defined */
static PSI_rwlock_info all_innodb_rwlocks[] = {
{&btr_search_latch_key, "btr_search_latch", 0},
{&buf_block_lock_key, "buf_block_lock", 0},
# ifdef UNIV_SYNC_DEBUG
{&buf_block_debug_latch_key, "buf_block_debug_latch", 0},
# endif /* UNIV_SYNC_DEBUG */
{&dict_operation_lock_key, "dict_operation_lock", 0},
{&fil_space_latch_key, "fil_space_latch", 0},
{&checkpoint_lock_key, "checkpoint_lock", 0},
{&archive_lock_key, "archive_lock", 0},
{&trx_i_s_cache_lock_key, "trx_i_s_cache_lock", 0},
{&trx_purge_latch_key, "trx_purge_latch", 0},
{&index_tree_rw_lock_key, "index_tree_rw_lock", 0}
};
# endif /* UNIV_PFS_RWLOCK */
# ifdef UNIV_PFS_THREAD
/* all_innodb_threads array contains threads that are
performance schema instrumented if "UNIV_PFS_THREAD"
is defined */
static PSI_thread_info all_innodb_threads[] = {
{&trx_rollback_clean_thread_key, "trx_rollback_clean_thread", 0},
{&io_handler_thread_key, "io_handler_thread", 0},
{&srv_lock_timeout_thread_key, "srv_lock_timeout_thread", 0},
{&srv_error_monitor_thread_key, "srv_error_monitor_thread", 0},
{&srv_monitor_thread_key, "srv_monitor_thread", 0},
{&srv_master_thread_key, "srv_master_thread", 0}
};
# endif /* UNIV_PFS_THREAD */
# ifdef UNIV_PFS_IO
/* all_innodb_files array contains the type of files that are
performance schema instrumented if "UNIV_PFS_IO" is defined */
static PSI_file_info all_innodb_files[] = {
{&innodb_file_data_key, "innodb_data_file", 0},
{&innodb_file_log_key, "innodb_log_file", 0},
{&innodb_file_temp_key, "innodb_temp_file", 0}
};
# endif /* UNIV_PFS_IO */
#endif /* HAVE_PSI_INTERFACE */
static INNOBASE_SHARE *get_share(const char *table_name);
static void free_share(INNOBASE_SHARE *share);
static int innobase_close_connection(handlerton *hton, THD* thd);
@ -2225,6 +2346,45 @@ innobase_change_buffering_inited_ok:
innobase_commit_concurrency_init_default();
#ifdef HAVE_PSI_INTERFACE
/* Register keys with MySQL performance schema */
if (PSI_server) {
int count;
count = array_elements(all_pthread_mutexes);
PSI_server->register_mutex("innodb",
all_pthread_mutexes, count);
# ifdef UNIV_PFS_MUTEX
count = array_elements(all_innodb_mutexes);
PSI_server->register_mutex("innodb",
all_innodb_mutexes, count);
# endif /* UNIV_PFS_MUTEX */
# ifdef UNIV_PFS_RWLOCK
count = array_elements(all_innodb_rwlocks);
PSI_server->register_rwlock("innodb",
all_innodb_rwlocks, count);
# endif /* UNIV_PFS_MUTEX */
# ifdef UNIV_PFS_THREAD
count = array_elements(all_innodb_threads);
PSI_server->register_thread("innodb",
all_innodb_threads, count);
# endif /* UNIV_PFS_THREAD */
# ifdef UNIV_PFS_IO
count = array_elements(all_innodb_files);
PSI_server->register_file("innodb",
all_innodb_files, count);
# endif /* UNIV_PFS_IO */
count = array_elements(all_innodb_conds);
PSI_server->register_cond("innodb",
all_innodb_conds, count);
}
#endif /* HAVE_PSI_INTERFACE */
/* Since we in this module access directly the fields of a trx
struct, and due to different headers and flags it might happen that
mutex_t has a different size in this module and in InnoDB
@ -2238,12 +2398,18 @@ innobase_change_buffering_inited_ok:
}
innobase_open_tables = hash_create(200);
pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&analyze_mutex, MY_MUTEX_INIT_FAST);
pthread_cond_init(&commit_cond, NULL);
mysql_mutex_init(innobase_share_mutex_key,
&innobase_share_mutex,
MY_MUTEX_INIT_FAST);
mysql_mutex_init(prepare_commit_mutex_key,
&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
mysql_mutex_init(commit_threads_m_key,
&commit_threads_m, MY_MUTEX_INIT_FAST);
mysql_mutex_init(commit_cond_mutex_key,
&commit_cond_m, MY_MUTEX_INIT_FAST);
mysql_mutex_init(analyze_mutex_key,
&analyze_mutex, MY_MUTEX_INIT_FAST);
mysql_cond_init(commit_cond_key, &commit_cond, NULL);
innodb_inited= 1;
#ifdef MYSQL_DYNAMIC_PLUGIN
if (innobase_hton != p) {
@ -2293,12 +2459,12 @@ innobase_end(
srv_free_paths_and_sizes();
my_free(internal_innobase_data_file_path,
MYF(MY_ALLOW_ZERO_PTR));
pthread_mutex_destroy(&innobase_share_mutex);
pthread_mutex_destroy(&prepare_commit_mutex);
pthread_mutex_destroy(&commit_threads_m);
pthread_mutex_destroy(&commit_cond_m);
pthread_mutex_destroy(&analyze_mutex);
pthread_cond_destroy(&commit_cond);
mysql_mutex_destroy(&innobase_share_mutex);
mysql_mutex_destroy(&prepare_commit_mutex);
mysql_mutex_destroy(&commit_threads_m);
mysql_mutex_destroy(&commit_cond_m);
mysql_mutex_destroy(&analyze_mutex);
mysql_cond_destroy(&commit_cond);
}
DBUG_RETURN(err);
@ -2463,18 +2629,18 @@ innobase_commit(
prepare_commit_mutex */
retry:
if (innobase_commit_concurrency > 0) {
pthread_mutex_lock(&commit_cond_m);
mysql_mutex_lock(&commit_cond_m);
commit_threads++;
if (commit_threads > innobase_commit_concurrency) {
commit_threads--;
pthread_cond_wait(&commit_cond,
mysql_cond_wait(&commit_cond,
&commit_cond_m);
pthread_mutex_unlock(&commit_cond_m);
mysql_mutex_unlock(&commit_cond_m);
goto retry;
}
else {
pthread_mutex_unlock(&commit_cond_m);
mysql_mutex_unlock(&commit_cond_m);
}
}
@ -2502,15 +2668,15 @@ retry:
trx->flush_log_later = FALSE;
if (innobase_commit_concurrency > 0) {
pthread_mutex_lock(&commit_cond_m);
mysql_mutex_lock(&commit_cond_m);
commit_threads--;
pthread_cond_signal(&commit_cond);
pthread_mutex_unlock(&commit_cond_m);
mysql_cond_signal(&commit_cond);
mysql_mutex_unlock(&commit_cond_m);
}
if (trx->active_trans == 2) {
pthread_mutex_unlock(&prepare_commit_mutex);
mysql_mutex_unlock(&prepare_commit_mutex);
}
/* Now do a write + flush of logs. */
@ -7666,12 +7832,12 @@ ha_innobase::analyze(
{
/* Serialize ANALYZE TABLE inside InnoDB, see
Bug#38996 Race condition in ANALYZE TABLE */
pthread_mutex_lock(&analyze_mutex);
mysql_mutex_lock(&analyze_mutex);
/* Simply call ::info() with all the flags */
info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
pthread_mutex_unlock(&analyze_mutex);
mysql_mutex_unlock(&analyze_mutex);
return(0);
}
@ -8696,8 +8862,8 @@ innodb_show_status(
read the contents of the temporary file */
if (!(str = (char*) my_malloc(usable_len + 1, MYF(0)))) {
mutex_exit(&srv_monitor_file_mutex);
DBUG_RETURN(TRUE);
mutex_exit(&srv_monitor_file_mutex);
DBUG_RETURN(TRUE);
}
rewind(srv_monitor_file);
@ -8937,7 +9103,7 @@ bool innobase_show_status(handlerton *hton, THD* thd,
static INNOBASE_SHARE* get_share(const char* table_name)
{
INNOBASE_SHARE *share;
pthread_mutex_lock(&innobase_share_mutex);
mysql_mutex_lock(&innobase_share_mutex);
ulint fold = ut_fold_string(table_name);
@ -8971,14 +9137,14 @@ static INNOBASE_SHARE* get_share(const char* table_name)
}
share->use_count++;
pthread_mutex_unlock(&innobase_share_mutex);
mysql_mutex_unlock(&innobase_share_mutex);
return(share);
}
static void free_share(INNOBASE_SHARE* share)
{
pthread_mutex_lock(&innobase_share_mutex);
mysql_mutex_lock(&innobase_share_mutex);
#ifdef UNIV_DEBUG
INNOBASE_SHARE* share2;
@ -9009,7 +9175,7 @@ static void free_share(INNOBASE_SHARE* share)
shrinks too much */
}
pthread_mutex_unlock(&innobase_share_mutex);
mysql_mutex_unlock(&innobase_share_mutex);
}
/*****************************************************************//**
@ -9718,7 +9884,7 @@ innobase_xa_prepare(
In this case we cannot know how many minutes or hours
will be between XA PREPARE and XA COMMIT, and we don't want
to block for undefined period of time. */
pthread_mutex_lock(&prepare_commit_mutex);
mysql_mutex_lock(&prepare_commit_mutex);
trx->active_trans = 2;
}

View file

@ -197,6 +197,12 @@ UNIV_INTERN ibuf_t* ibuf = NULL;
/** Counter for ibuf_should_try() */
UNIV_INTERN ulint ibuf_flush_count = 0;
#ifdef UNIV_PFS_MUTEX
UNIV_INTERN mysql_pfs_key_t ibuf_pessimistic_insert_mutex_key;
UNIV_INTERN mysql_pfs_key_t ibuf_mutex_key;
UNIV_INTERN mysql_pfs_key_t ibuf_bitmap_mutex_key;
#endif /* UNIV_PFS_MUTEX */
#ifdef UNIV_IBUF_COUNT_DEBUG
/** Number of tablespaces in the ibuf_counts array */
#define IBUF_COUNT_N_SPACES 4
@ -508,12 +514,15 @@ ibuf_init_at_db_start(void)
ibuf->max_size = buf_pool_get_curr_size() / UNIV_PAGE_SIZE
/ IBUF_POOL_SIZE_PER_MAX_SIZE;
mutex_create(&ibuf_pessimistic_insert_mutex,
mutex_create(ibuf_pessimistic_insert_mutex_key,
&ibuf_pessimistic_insert_mutex,
SYNC_IBUF_PESS_INSERT_MUTEX);
mutex_create(&ibuf_mutex, SYNC_IBUF_MUTEX);
mutex_create(ibuf_mutex_key,
&ibuf_mutex, SYNC_IBUF_MUTEX);
mutex_create(&ibuf_bitmap_mutex, SYNC_IBUF_BITMAP_MUTEX);
mutex_create(ibuf_bitmap_mutex_key,
&ibuf_bitmap_mutex, SYNC_IBUF_BITMAP_MUTEX);
mtr_start(&mtr);

View file

@ -76,18 +76,18 @@ extern ulint os_n_pending_writes;
#ifdef __WIN__
/** File handle */
#define os_file_t HANDLE
# define os_file_t HANDLE
/** Convert a C file descriptor to a native file handle
@param fd file descriptor
@return native file handle */
#define OS_FILE_FROM_FD(fd) (HANDLE) _get_osfhandle(fd)
# define OS_FILE_FROM_FD(fd) (HANDLE) _get_osfhandle(fd)
#else
/** File handle */
typedef int os_file_t;
/** Convert a C file descriptor to a native file handle
@param fd file descriptor
@return native file handle */
#define OS_FILE_FROM_FD(fd) fd
# define OS_FILE_FROM_FD(fd) fd
#endif
/** Umask for creating files */
@ -182,6 +182,157 @@ extern ulint os_n_file_reads;
extern ulint os_n_file_writes;
extern ulint os_n_fsyncs;
#ifdef UNIV_PFS_IO
/* Keys to register InnoDB I/O with performance schema */
extern mysql_pfs_key_t innodb_file_data_key;
extern mysql_pfs_key_t innodb_file_log_key;
extern mysql_pfs_key_t innodb_file_temp_key;
/* Following four macros are instumentations to register
various file I/O operations with performance schema.
1) register_pfs_file_open_begin() and register_pfs_file_open_end() are
used to register file creation, opening, closing and renaming.
2) register_pfs_file_io_begin() and register_pfs_file_io_end() are
used to register actual file read, write and flush */
# define register_pfs_file_open_begin(locker, key, op, name, \
src_file, src_line) \
do { \
if (PSI_server) { \
locker = PSI_server->get_thread_file_name_locker( \
key, op, name, &locker); \
if (locker) { \
PSI_server->start_file_open_wait( \
locker, src_file, src_line); \
} \
} \
} while (0)
# define register_pfs_file_open_end(locker, file) \
do { \
if (locker) { \
PSI_server->end_file_open_wait_and_bind_to_descriptor( \
locker, file); \
} \
} while (0)
# define register_pfs_file_io_begin(locker, file, count, op, \
src_file, src_line) \
do { \
if (PSI_server) { \
locker = PSI_server->get_thread_file_descriptor_locker( \
file, op); \
if (locker) { \
PSI_server->start_file_wait( \
locker, count, src_file, src_line); \
} \
} \
} while (0)
# define register_pfs_file_io_end(locker, count) \
do { \
if (locker) { \
PSI_server->end_file_wait(locker, count); \
} \
} while (0)
#endif /* UNIV_PFS_IO */
/* Following macros/functions are file I/O APIs that would be performance
schema instrumented if "UNIV_PFS_IO" is defined. They would point to
wrapper functions with performance schema instrumentation in such case.
os_file_create
os_file_create_simple
os_file_create_simple_no_error_handling
os_file_close
os_file_rename
os_aio
os_file_read
os_file_read_no_error_handling
os_file_write
The wrapper functions have the prefix of "innodb_". */
#ifdef UNIV_PFS_IO
# define os_file_create(key, name, create, purpose, type, success) \
pfs_os_file_create_func(key, name, create, purpose, type, \
success, __FILE__, __LINE__)
# define os_file_create_simple(key, name, create, access, success) \
pfs_os_file_create_simple_func(key, name, create, access, \
success, __FILE__, __LINE__)
# define os_file_create_simple_no_error_handling( \
key, name, create_mode, access, success) \
pfs_os_file_create_simple_no_error_handling_func( \
key, name, create_mode, access, success, __FILE__, __LINE__)
# define os_file_close(file) \
pfs_os_file_close_func(file, __FILE__, __LINE__)
# define os_aio(type, mode, name, file, buf, offset, offset_high, \
n, message1, message2) \
pfs_os_aio_func(type, mode, name, file, buf, offset, \
offset_high, n, message1, message2, \
__FILE__, __LINE__)
# define os_file_read(file, buf, offset, offset_high, n) \
pfs_os_file_read_func(file, buf, offset, offset_high, n, \
__FILE__, __LINE__)
# define os_file_read_no_error_handling(file, buf, offset, \
offset_high, n) \
pfs_os_file_read_no_error_handling_func(file, buf, offset, \
offset_high, n, \
__FILE__, __LINE__)
# define os_file_write(name, file, buf, offset, offset_high, n) \
pfs_os_file_write_func(name, file, buf, offset, offset_high, \
n, __FILE__, __LINE__)
# define os_file_flush(file) \
pfs_os_file_flush_func(file, __FILE__, __LINE__)
# define os_file_rename(key, oldpath, newpath) \
pfs_os_file_rename_func(key, oldpath, newpath, __FILE__, __LINE__)
#else /* UNIV_PFS_IO */
/* If UNIV_PFS_IO is not defined, these I/O APIs point
to original un-instrumented file I/O APIs */
# define os_file_create(key, name, create, purpose, type, success) \
os_file_create_func(name, create, purpose, type, success)
# define os_file_create_simple(key, name, create, access, success) \
os_file_create_simple_func(name, create_mode, access, success)
# define os_file_create_simple_no_error_handling( \
key, name, create_mode, access, success) \
os_file_create_simple_no_error_handling_func( \
name, create_mode, access, success)
# define os_file_close(file) os_file_close_func(file)
# define os_aio(type, mode, name, file, buf, offset, offset_high, \
n, message1, message2) \
os_aio_func(type, mode, name, file, buf, offset, offset_high, n,\
message1, message2)
# define os_file_read(file, buf, offset, offset_high, n) \
os_file_read_func(file, buf, offset, offset_high, n)
# define os_file_read_no_error_handling(file, buf, offset, \
offset_high, n) \
os_file_read_no_error_handling_func(file, buf, offset, offset_high, n)
# define os_file_write(name, file, buf, offset, offset_high, n) \
os_file_write_func(name, file, buf, offset, offset_high, n)
# define os_file_flush(file) os_file_flush_func(file)
# define os_file_rename(key, oldpath, newpath) \
os_file_rename_func(oldpath, newpath)
#endif /* UNIV_PFS_IO */
/* File types for directory entry data type */
enum os_file_type_enum{
@ -291,13 +442,15 @@ os_file_create_directory(
ibool fail_if_exists);/*!< in: if TRUE, pre-existing directory
is treated as an error. */
/****************************************************************//**
NOTE! Use the corresponding macro os_file_create_simple(), not directly
this function!
A simple function to open or create a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
os_file_t
os_file_create_simple(
/*==================*/
os_file_create_simple_func(
/*=======================*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file is
@ -311,13 +464,15 @@ os_file_create_simple(
OS_FILE_READ_WRITE */
ibool* success);/*!< out: TRUE if succeed, FALSE if error */
/****************************************************************//**
NOTE! Use the corresponding macro
os_file_create_simple_no_error_handling(), not directly this function!
A simple function to open or create a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
os_file_t
os_file_create_simple_no_error_handling(
/*====================================*/
os_file_create_simple_no_error_handling_func(
/*=========================================*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
@ -341,13 +496,15 @@ os_file_set_nocache(
const char* operation_name);/*!< in: "open" or "create"; used in the
diagnostic message */
/****************************************************************//**
NOTE! Use the corresponding macro os_file_create(), not directly
this function!
Opens an existing file or creates a new.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
os_file_t
os_file_create(
/*===========*/
os_file_create_func(
/*================*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
@ -385,25 +542,258 @@ os_file_delete_if_exists(
/*=====================*/
const char* name); /*!< in: file path as a null-terminated string */
/***********************************************************************//**
NOTE! Use the corresponding macro os_file_rename(), not directly
this function!
Renames a file (can also move it to another directory). It is safest that the
file is closed before calling this function.
@return TRUE if success */
UNIV_INTERN
ibool
os_file_rename(
/*===========*/
os_file_rename_func(
/*================*/
const char* oldpath, /*!< in: old file path as a
null-terminated string */
const char* newpath); /*!< in: new file path */
/***********************************************************************//**
NOTE! Use the corresponding macro os_file_close(), not directly this
function!
Closes a file handle. In case of error, error number can be retrieved with
os_file_get_last_error.
@return TRUE if success */
UNIV_INTERN
ibool
os_file_close(
/*==========*/
os_file_close_func(
/*===============*/
os_file_t file); /*!< in, own: handle to a file */
#ifdef UNIV_PFS_IO
/****************************************************************//**
NOTE! Please use the corresponding macro os_file_create_simple(),
not directly this function!
A performance schema instrumented wrapper function for
os_file_create_simple() which opens or creates a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
os_file_t
pfs_os_file_create_simple_func(
/*===========================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file is
opened (if does not exist, error), or
OS_FILE_CREATE if a new file is created
(if exists, error), or
OS_FILE_CREATE_PATH if new file
(if exists, error) and subdirectories along
its path are created (if needed)*/
ulint access_type,/*!< in: OS_FILE_READ_ONLY or
OS_FILE_READ_WRITE */
ibool* success,/*!< out: TRUE if succeed, FALSE if error */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/****************************************************************//**
NOTE! Please use the corresponding macro
os_file_create_simple_no_error_handling(), not directly this function!
A performance schema instrumented wrapper function for
os_file_create_simple_no_error_handling(). Add instrumentation to
monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
os_file_t
pfs_os_file_create_simple_no_error_handling_func(
/*=============================================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
is opened (if does not exist, error), or
OS_FILE_CREATE if a new file is created
(if exists, error) */
ulint access_type,/*!< in: OS_FILE_READ_ONLY,
OS_FILE_READ_WRITE, or
OS_FILE_READ_ALLOW_DELETE; the last option is
used by a backup program reading the file */
ibool* success,/*!< out: TRUE if succeed, FALSE if error */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/****************************************************************//**
NOTE! Please use the corresponding macro os_file_create(), not directly
this function!
A performance schema wrapper function for os_file_create().
Add instrumentation to monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
os_file_t
pfs_os_file_create_func(
/*====================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
is opened (if does not exist, error), or
OS_FILE_CREATE if a new file is created
(if exists, error),
OS_FILE_OVERWRITE if a new file is created
or an old overwritten;
OS_FILE_OPEN_RAW, if a raw device or disk
partition should be opened */
ulint purpose,/*!< in: OS_FILE_AIO, if asynchronous,
non-buffered i/o is desired,
OS_FILE_NORMAL, if any normal file;
NOTE that it also depends on type, os_aio_..
and srv_.. variables whether we really use
async i/o or unbuffered i/o: look in the
function source code for the exact rules */
ulint type, /*!< in: OS_DATA_FILE or OS_LOG_FILE */
ibool* success,/*!< out: TRUE if succeed, FALSE if error */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/***********************************************************************//**
NOTE! Please use the corresponding macro os_file_close(), not directly
this function!
A performance schema instrumented wrapper function for os_file_close().
@return TRUE if success */
UNIV_INLINE
ibool
pfs_os_file_close_func(
/*===================*/
os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/*******************************************************************//**
NOTE! Please use the corresponding macro os_file_read(), not directly
this function!
This is the performance schema instrumented wrapper function for
os_file_read() which requests a synchronous read operation.
@return TRUE if request was successful, FALSE if fail */
UNIV_INLINE
ibool
pfs_os_file_read_func(
/*==================*/
os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
ulint offset, /*!< in: least significant 32 bits of file
offset where to read */
ulint offset_high,/*!< in: most significant 32 bits of
offset */
ulint n, /*!< in: number of bytes to read */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/*******************************************************************//**
NOTE! Please use the corresponding macro os_file_read_no_error_handling(),
not directly this function!
This is the performance schema instrumented wrapper function for
os_file_read_no_error_handling_func() which requests a synchronous
read operation.
@return TRUE if request was successful, FALSE if fail */
UNIV_INLINE
ibool
pfs_os_file_read_no_error_handling_func(
/*====================================*/
os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
ulint offset, /*!< in: least significant 32 bits of file
offset where to read */
ulint offset_high,/*!< in: most significant 32 bits of
offset */
ulint n, /*!< in: number of bytes to read */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/*******************************************************************//**
NOTE! Please use the corresponding macro os_aio(), not directly this
function!
Performance schema wrapper function of os_aio() which requests
an asynchronous i/o operation.
@return TRUE if request was queued successfully, FALSE if fail */
UNIV_INLINE
ibool
pfs_os_aio_func(
/*============*/
ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE */
ulint mode, /*!< in: OS_AIO_NORMAL etc. I/O mode */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read or from which
to write */
ulint offset, /*!< in: least significant 32 bits of file
offset where to read or write */
ulint offset_high,/*!< in: most significant 32 bits of
offset */
ulint n, /*!< in: number of bytes to read or write */
fil_node_t* message1,/*!< in: message for the aio handler
(can be used to identify a completed
aio operation); ignored if mode is
OS_AIO_SYNC */
void* message2,/*!< in: message for the aio handler
(can be used to identify a completed
aio operation); ignored if mode is
OS_AIO_SYNC */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/*******************************************************************//**
NOTE! Please use the corresponding macro os_file_write(), not directly
this function!
This is the performance schema instrumented wrapper function for
os_file_write() which requests a synchronous write operation.
@return TRUE if request was successful, FALSE if fail */
UNIV_INLINE
ibool
pfs_os_file_write_func(
/*===================*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
os_file_t file, /*!< in: handle to a file */
const void* buf, /*!< in: buffer from which to write */
ulint offset, /*!< in: least significant 32 bits of file
offset where to write */
ulint offset_high,/*!< in: most significant 32 bits of
offset */
ulint n, /*!< in: number of bytes to write */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/***********************************************************************//**
NOTE! Please use the corresponding macro os_file_flush(), not directly
this function!
This is the performance schema instrumented wrapper function for
os_file_flush() which flushes the write buffers of a given file to the disk.
Flushes the write buffers of a given file to the disk.
@return TRUE if success */
UNIV_INLINE
ibool
pfs_os_file_flush_func(
/*===================*/
os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/***********************************************************************//**
NOTE! Please use the corresponding macro os_file_rename(), not directly
this function!
This is the performance schema instrumented wrapper function for
os_file_rename()
@return TRUE if success */
UNIV_INLINE
ibool
pfs_os_file_rename_func(
/*====================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
const char* oldpath,/*!< in: old file path as a null-terminated
string */
const char* newpath,/*!< in: new file path */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
#endif /* UNIV_PFS_IO */
#ifdef UNIV_HOTBACKUP
/***********************************************************************//**
Closes a file handle.
@ -455,12 +845,13 @@ os_file_set_eof(
/*============*/
FILE* file); /*!< in: file to be truncated */
/***********************************************************************//**
NOTE! Use the corresponding macro os_file_flush(), not directly this function!
Flushes the write buffers of a given file to the disk.
@return TRUE if success */
UNIV_INTERN
ibool
os_file_flush(
/*==========*/
os_file_flush_func(
/*===============*/
os_file_t file); /*!< in, own: handle to a file */
/***********************************************************************//**
Retrieves the last error number if an error occurs in a file io function.
@ -475,12 +866,13 @@ os_file_get_last_error(
ibool report_all_errors); /*!< in: TRUE if we want an error message
printed of all errors */
/*******************************************************************//**
NOTE! Use the corresponding macro os_file_read(), not directly this function!
Requests a synchronous read operation.
@return TRUE if request was successful, FALSE if fail */
UNIV_INTERN
ibool
os_file_read(
/*=========*/
os_file_read_func(
/*==============*/
os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
ulint offset, /*!< in: least significant 32 bits of file
@ -500,13 +892,15 @@ os_file_read_string(
char* str, /*!< in: buffer where to read */
ulint size); /*!< in: size of buffer */
/*******************************************************************//**
NOTE! Use the corresponding macro os_file_read_no_error_handling(),
not directly this function!
Requests a synchronous positioned read operation. This function does not do
any error handling. In case of error it returns FALSE.
@return TRUE if request was successful, FALSE if fail */
UNIV_INTERN
ibool
os_file_read_no_error_handling(
/*===========================*/
os_file_read_no_error_handling_func(
/*================================*/
os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
ulint offset, /*!< in: least significant 32 bits of file
@ -516,12 +910,14 @@ os_file_read_no_error_handling(
ulint n); /*!< in: number of bytes to read */
/*******************************************************************//**
NOTE! Use the corresponding macro os_file_write(), not directly this
function!
Requests a synchronous write operation.
@return TRUE if request was successful, FALSE if fail */
UNIV_INTERN
ibool
os_file_write(
/*==========*/
os_file_write_func(
/*===============*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
os_file_t file, /*!< in: handle to a file */
@ -607,12 +1003,13 @@ os_aio_free(void);
/*=============*/
/*******************************************************************//**
NOTE! Use the corresponding macro os_aio(), not directly this function!
Requests an asynchronous i/o operation.
@return TRUE if request was queued successfully, FALSE if fail */
UNIV_INTERN
ibool
os_aio(
/*===*/
os_aio_func(
/*========*/
ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE */
ulint mode, /*!< in: OS_AIO_NORMAL, ..., possibly ORed
to OS_AIO_SIMULATED_WAKE_LATER: the
@ -808,4 +1205,8 @@ os_aio_linux_handle(
ulint* type); /*!< out: OS_FILE_WRITE or ..._READ */
#endif /* LINUX_NATIVE_AIO */
#ifndef UNIV_NONINL
#include "os0file.ic"
#endif
#endif

408
include/os0file.ic Normal file
View file

@ -0,0 +1,408 @@
/*****************************************************************************
Copyright (c) 2010, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/**************************************************//**
@file include/os0file.ic
The interface to the operating system file io
Created 2/20/2010 Jimmy Yang
*******************************************************/
#include "univ.i"
#ifdef UNIV_PFS_IO
/****************************************************************//**
NOTE! Please use the corresponding macro os_file_create_simple(),
not directly this function!
A performance schema instrumented wrapper function for
os_file_create_simple() which opens or creates a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
os_file_t
pfs_os_file_create_simple_func(
/*===========================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file is
opened (if does not exist, error), or
OS_FILE_CREATE if a new file is created
(if exists, error), or
OS_FILE_CREATE_PATH if new file
(if exists, error) and subdirectories along
its path are created (if needed)*/
ulint access_type,/*!< in: OS_FILE_READ_ONLY or
OS_FILE_READ_WRITE */
ibool* success,/*!< out: TRUE if succeed, FALSE if error */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
os_file_t file;
struct PSI_file_locker* locker = NULL;
/* register a file open or creation depending on "create_mode" */
register_pfs_file_open_begin(locker, key,
((create_mode == OS_FILE_CREATE)
? PSI_FILE_CREATE
: PSI_FILE_OPEN),
name, src_file, src_line);
file = os_file_create_simple_func(name, create_mode,
access_type, success);
/* Regsiter the returning "file" value with the system */
register_pfs_file_open_end(locker, file);
return(file);
}
/****************************************************************//**
NOTE! Please use the corresponding macro
os_file_create_simple_no_error_handling(), not directly this function!
A performance schema instrumented wrapper function for
os_file_create_simple_no_error_handling(). Add instrumentation to
monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
os_file_t
pfs_os_file_create_simple_no_error_handling_func(
/*=============================================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
is opened (if does not exist, error), or
OS_FILE_CREATE if a new file is created
(if exists, error) */
ulint access_type,/*!< in: OS_FILE_READ_ONLY,
OS_FILE_READ_WRITE, or
OS_FILE_READ_ALLOW_DELETE; the last option is
used by a backup program reading the file */
ibool* success,/*!< out: TRUE if succeed, FALSE if error */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
os_file_t file;
struct PSI_file_locker* locker = NULL;
/* register a file open or creation depending on "create_mode" */
register_pfs_file_open_begin(locker, key,
((create_mode == OS_FILE_CREATE)
? PSI_FILE_CREATE
: PSI_FILE_OPEN),
name, src_file, src_line);
file = os_file_create_simple_no_error_handling_func(
name, create_mode, access_type, success);
register_pfs_file_open_end(locker, file);
return(file);
}
/****************************************************************//**
NOTE! Please use the corresponding macro os_file_create(), not directly
this function!
A performance schema wrapper function for os_file_create().
Add instrumentation to monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
os_file_t
pfs_os_file_create_func(
/*====================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
is opened (if does not exist, error), or
OS_FILE_CREATE if a new file is created
(if exists, error),
OS_FILE_OVERWRITE if a new file is created
or an old overwritten;
OS_FILE_OPEN_RAW, if a raw device or disk
partition should be opened */
ulint purpose,/*!< in: OS_FILE_AIO, if asynchronous,
non-buffered i/o is desired,
OS_FILE_NORMAL, if any normal file;
NOTE that it also depends on type, os_aio_..
and srv_.. variables whether we really use
async i/o or unbuffered i/o: look in the
function source code for the exact rules */
ulint type, /*!< in: OS_DATA_FILE or OS_LOG_FILE */
ibool* success,/*!< out: TRUE if succeed, FALSE if error */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
os_file_t file;
struct PSI_file_locker* locker = NULL;
/* register a file open or creation depending on "create_mode" */
register_pfs_file_open_begin(locker, key,
((create_mode == OS_FILE_CREATE)
? PSI_FILE_CREATE
: PSI_FILE_OPEN),
name, src_file, src_line);
file = os_file_create_func(name, create_mode, purpose, type, success);
register_pfs_file_open_end(locker, file);
return(file);
}
/***********************************************************************//**
NOTE! Please use the corresponding macro os_file_close(), not directly
this function!
A performance schema instrumented wrapper function for os_file_close().
@return TRUE if success */
UNIV_INLINE
ibool
pfs_os_file_close_func(
/*===================*/
os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
ibool result;
struct PSI_file_locker* locker = NULL;
/* register the file close */
register_pfs_file_io_begin(locker, file, 0, PSI_FILE_CLOSE,
src_file, src_line);
result = os_file_close_func(file);
register_pfs_file_io_end(locker, 0);
return(result);
}
/*******************************************************************//**
NOTE! Please use the corresponding macro os_aio(), not directly this
function!
Performance schema instrumented wrapper function of os_aio() which
requests an asynchronous i/o operation.
@return TRUE if request was queued successfully, FALSE if fail */
UNIV_INLINE
ibool
pfs_os_aio_func(
/*============*/
ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE */
ulint mode, /*!< in: OS_AIO_NORMAL etc. I/O mode */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read or from which
to write */
ulint offset, /*!< in: least significant 32 bits of file
offset where to read or write */
ulint offset_high,/*!< in: most significant 32 bits of
offset */
ulint n, /*!< in: number of bytes to read or write */
fil_node_t* message1,/*!< in: message for the aio handler
(can be used to identify a completed
aio operation); ignored if mode is
OS_AIO_SYNC */
void* message2,/*!< in: message for the aio handler
(can be used to identify a completed
aio operation); ignored if mode is
OS_AIO_SYNC */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
ibool result;
struct PSI_file_locker* locker = NULL;
/* Register the read or write I/O depending on "type" */
register_pfs_file_io_begin(locker, file, n,
(type == OS_FILE_WRITE)
? PSI_FILE_WRITE
: PSI_FILE_READ,
src_file, src_line);
result = os_aio_func(type, mode, name, file, buf, offset, offset_high,
n, message1, message2);
register_pfs_file_io_end(locker, n);
return(result);
}
/*******************************************************************//**
NOTE! Please use the corresponding macro os_file_read(), not directly
this function!
This is the performance schema instrumented wrapper function for
os_file_read() which requests a synchronous read operation.
@return TRUE if request was successful, FALSE if fail */
UNIV_INLINE
ibool
pfs_os_file_read_func(
/*==================*/
os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
ulint offset, /*!< in: least significant 32 bits of file
offset where to read */
ulint offset_high,/*!< in: most significant 32 bits of
offset */
ulint n, /*!< in: number of bytes to read */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
ibool result;
struct PSI_file_locker* locker = NULL;
register_pfs_file_io_begin(locker, file, n, PSI_FILE_READ,
src_file, src_line);
result = os_file_read_func(file, buf, offset, offset_high, n);
register_pfs_file_io_end(locker, n);
return(result);
}
/*******************************************************************//**
NOTE! Please use the corresponding macro
os_file_read_no_error_handling(), not directly this function!
This is the performance schema instrumented wrapper function for
os_file_read_no_error_handling() which requests a synchronous
positioned read operation. This function does not do any error
handling. In case of error it returns FALSE.
@return TRUE if request was successful, FALSE if fail */
UNIV_INLINE
ibool
pfs_os_file_read_no_error_handling_func(
/*====================================*/
os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
ulint offset, /*!< in: least significant 32 bits of file
offset where to read */
ulint offset_high,/*!< in: most significant 32 bits of
offset */
ulint n, /*!< in: number of bytes to read */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
ibool result;
struct PSI_file_locker* locker = NULL;
register_pfs_file_io_begin(locker, file, n, PSI_FILE_READ,
src_file, src_line);
result = os_file_read_no_error_handling_func(file, buf, offset,
offset_high, n);
register_pfs_file_io_end(locker, n);
return(result);
}
/*******************************************************************//**
NOTE! Please use the corresponding macro os_file_write(), not directly
this function!
This is the performance schema instrumented wrapper function for
os_file_write() which requests a synchronous write operation.
@return TRUE if request was successful, FALSE if fail */
UNIV_INLINE
ibool
pfs_os_file_write_func(
/*===================*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
os_file_t file, /*!< in: handle to a file */
const void* buf, /*!< in: buffer from which to write */
ulint offset, /*!< in: least significant 32 bits of file
offset where to write */
ulint offset_high,/*!< in: most significant 32 bits of
offset */
ulint n, /*!< in: number of bytes to write */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
ibool result;
struct PSI_file_locker* locker = NULL;
register_pfs_file_io_begin(locker, file, n, PSI_FILE_WRITE,
src_file, src_line);
result = os_file_write_func(name, file, buf, offset, offset_high, n);
register_pfs_file_io_end(locker, n);
return(result);
}
/***********************************************************************//**
NOTE! Please use the corresponding macro os_file_flush(), not directly
this function!
This is the performance schema instrumented wrapper function for
os_file_flush() which flushes the write buffers of a given file to the disk.
@return TRUE if success */
UNIV_INLINE
ibool
pfs_os_file_flush_func(
/*===================*/
os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
ibool result;
struct PSI_file_locker* locker = NULL;
register_pfs_file_io_begin(locker, file, 0, PSI_FILE_SYNC,
src_file, src_line);
result = os_file_flush_func(file);
register_pfs_file_io_end(locker, 0);
return(result);
}
/***********************************************************************//**
NOTE! Please use the corresponding macro os_file_rename(), not directly
this function!
This is the performance schema instrumented wrapper function for
os_file_rename()
@return TRUE if success */
UNIV_INLINE
ibool
pfs_os_file_rename_func(
/*====================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
const char* oldpath,/*!< in: old file path as a null-terminated
string */
const char* newpath,/*!< in: new file path */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
ibool result;
struct PSI_file_locker* locker = NULL;
register_pfs_file_open_begin(locker, key, PSI_FILE_RENAME, newpath,
src_file, src_line);
result = os_file_rename_func(oldpath, newpath);
register_pfs_file_open_end(locker, 0);
return(result);
}
#endif /* UNIV_PFS_IO */

View file

@ -56,6 +56,11 @@ typedef os_thread_t os_thread_id_t; /*!< In Unix we use the thread
/* Define a function pointer type to use in a typecast */
typedef void* (*os_posix_f_t) (void*);
#ifdef HAVE_PSI_INTERFACE
/* Define for performance schema registration key */
typedef unsigned int mysql_pfs_key_t;
#endif
/***************************************************************//**
Compares two thread ids for equality.
@return TRUE if equal */
@ -86,7 +91,7 @@ os_thread_t
os_thread_create(
/*=============*/
#ifndef __WIN__
os_posix_f_t start_f,
os_posix_f_t start_f,
#else
ulint (*start_f)(void*), /*!< in: pointer to function
from which to start */

View file

@ -312,6 +312,37 @@ typedef struct srv_sys_struct srv_sys_t;
/** The server system */
extern srv_sys_t* srv_sys;
# ifdef UNIV_PFS_THREAD
/* Keys to register InnoDB threads with performance schema */
extern mysql_pfs_key_t trx_rollback_clean_thread_key;
extern mysql_pfs_key_t io_handler_thread_key;
extern mysql_pfs_key_t srv_lock_timeout_thread_key;
extern mysql_pfs_key_t srv_error_monitor_thread_key;
extern mysql_pfs_key_t srv_monitor_thread_key;
extern mysql_pfs_key_t srv_master_thread_key;
/* This macro register the current thread and its key with performance
schema */
# define pfs_register_thread(key) \
do { \
if (PSI_server) { \
struct PSI_thread* psi = PSI_server->new_thread(key, NULL, 0);\
if (psi) { \
PSI_server->set_thread(psi); \
} \
} \
} while (0)
/* This macro delist the current thread from performance schema */
# define pfs_delete_thread() \
do { \
if (PSI_server) { \
PSI_server->delete_current_thread(); \
} \
} while (0)
# endif /* UNIV_PFS_THREAD */
#endif /* !UNIV_HOTBACKUP */
/** Types of raw partitions in innodb_data_file_path */

View file

@ -105,23 +105,138 @@ extern ib_int64_t rw_x_os_wait_count;
set only when UNIV_SYNC_PERF_STAT is defined */
extern ib_int64_t rw_x_exit_count;
#ifdef UNIV_PFS_RWLOCK
/* Following are rwlock keys used to register with MySQL
performance schema */
extern mysql_pfs_key_t btr_search_latch_key;
extern mysql_pfs_key_t buf_block_lock_key;
# ifdef UNIV_SYNC_DEBUG
extern mysql_pfs_key_t buf_block_debug_latch_key;
# endif
extern mysql_pfs_key_t dict_operation_lock_key;
extern mysql_pfs_key_t fil_space_latch_key;
extern mysql_pfs_key_t checkpoint_lock_key;
extern mysql_pfs_key_t archive_lock_key;
extern mysql_pfs_key_t trx_i_s_cache_lock_key;
extern mysql_pfs_key_t trx_purge_latch_key;
extern mysql_pfs_key_t index_tree_rw_lock_key;
#endif /* UNIV_PFS_RWLOCK */
#ifndef UNIV_PFS_RWLOCK
/******************************************************************//**
Creates, or rather, initializes an rw-lock object in a specified memory
location (which must be appropriately aligned). The rw-lock is initialized
to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free
is necessary only if the memory block containing it is freed. */
#ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
# define rw_lock_create(L, level) \
is necessary only if the memory block containing it is freed.
if MySQL performance schema is enabled and "UNIV_PFS_RWLOCK" is
defined, the rwlock are instrumented with performance schema probes. */
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
# define rw_lock_create(K, L, level) \
rw_lock_create_func((L), (level), #L, __FILE__, __LINE__)
# else /* UNIV_SYNC_DEBUG */
# define rw_lock_create(L, level) \
# else /* UNIV_SYNC_DEBUG */
# define rw_lock_create(K, L, level) \
rw_lock_create_func((L), #L, __FILE__, __LINE__)
# endif /* UNIV_SYNC_DEBUG */
#else /* UNIV_DEBUG */
# define rw_lock_create(L, level) \
# endif/* UNIV_SYNC_DEBUG */
# else /* UNIV_DEBUG */
# define rw_lock_create(K, L, level) \
rw_lock_create_func((L), __FILE__, __LINE__)
#endif /* UNIV_DEBUG */
# endif /* UNIV_DEBUG */
/**************************************************************//**
NOTE! The following macros should be used in rw locking and
unlocking, not the corresponding function. */
# define rw_lock_s_lock(M) \
rw_lock_s_lock_func((M), 0, __FILE__, __LINE__)
# define rw_lock_s_lock_gen(M, P) \
rw_lock_s_lock_func((M), (P), __FILE__, __LINE__)
# define rw_lock_s_lock_nowait(M, F, L) \
rw_lock_s_lock_low((M), 0, (F), (L))
# ifdef UNIV_SYNC_DEBUG
# define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(P, L)
# else
# define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(L)
# endif
# define rw_lock_x_lock(M) \
rw_lock_x_lock_func((M), 0, __FILE__, __LINE__)
# define rw_lock_x_lock_gen(M, P) \
rw_lock_x_lock_func((M), (P), __FILE__, __LINE__)
# define rw_lock_x_lock_nowait(M) \
rw_lock_x_lock_func_nowait((M), __FILE__, __LINE__)
# ifdef UNIV_SYNC_DEBUG
# define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(P, L)
# else
# define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(L)
# endif
# define rw_lock_free(M) rw_lock_free_func(M)
#else /* !UNIV_PFS_RWLOCK */
/* Following macros point to Performance Schema instrumented functions. */
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
# define rw_lock_create(K, L, level) \
pfs_rw_lock_create_func((K), (L), (level), #L, __FILE__, __LINE__)
# else /* UNIV_SYNC_DEBUG */
# define rw_lock_create(K, L, level) \
pfs_rw_lock_create_func((K), (L), #L, __FILE__, __LINE__)
# endif/* UNIV_SYNC_DEBUG */
# else /* UNIV_DEBUG */
# define rw_lock_create(K, L, level) \
pfs_rw_lock_create_func((K), (L), __FILE__, __LINE__)
# endif /* UNIV_DEBUG */
/******************************************************************
NOTE! The following macros should be used in rw locking and
unlocking, not the corresponding function. */
# define rw_lock_s_lock(M) \
pfs_rw_lock_s_lock_func((M), 0, __FILE__, __LINE__)
# define rw_lock_s_lock_gen(M, P) \
pfs_rw_lock_s_lock_func((M), (P), __FILE__, __LINE__)
# define rw_lock_s_lock_nowait(M, F, L) \
pfs_rw_lock_s_lock_low((M), 0, (F), (L))
# ifdef UNIV_SYNC_DEBUG
# define rw_lock_s_unlock_gen(L, P) pfs_rw_lock_s_unlock_func(P, L)
# else
# define rw_lock_s_unlock_gen(L, P) pfs_rw_lock_s_unlock_func(L)
# endif
# define rw_lock_x_lock(M) \
pfs_rw_lock_x_lock_func((M), 0, __FILE__, __LINE__)
# define rw_lock_x_lock_gen(M, P) \
pfs_rw_lock_x_lock_func((M), (P), __FILE__, __LINE__)
# define rw_lock_x_lock_nowait(M) \
pfs_rw_lock_x_lock_func_nowait((M), __FILE__, __LINE__)
# ifdef UNIV_SYNC_DEBUG
# define rw_lock_x_unlock_gen(L, P) pfs_rw_lock_x_unlock_func(P, L)
# else
# define rw_lock_x_unlock_gen(L, P) pfs_rw_lock_x_unlock_func(L)
# endif
# define rw_lock_free(M) pfs_rw_lock_free_func(M)
#endif /* UNIV_PFS_RWLOCK */
#define rw_lock_s_unlock(L) rw_lock_s_unlock_gen(L, 0)
#define rw_lock_x_unlock(L) rw_lock_x_unlock_gen(L, 0)
/******************************************************************//**
Creates, or rather, initializes an rw-lock object in a specified memory
@ -137,18 +252,18 @@ rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cmutex_name, /*!< in: mutex name */
const char* cmutex_name, /*!< in: mutex name */
#endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline); /*!< in: file line where created */
ulint cline); /*!< in: file line where created */
/******************************************************************//**
Calling this function is obligatory only if the memory buffer containing
the rw-lock is freed. Removes an rw-lock object from the global list. The
rw-lock is checked to be in the non-locked state. */
UNIV_INTERN
void
rw_lock_free(
/*=========*/
rw_lock_free_func(
/*==============*/
rw_lock_t* lock); /*!< in: rw-lock */
#ifdef UNIV_DEBUG
/******************************************************************//**
@ -161,24 +276,6 @@ rw_lock_validate(
/*=============*/
rw_lock_t* lock); /*!< in: rw-lock */
#endif /* UNIV_DEBUG */
/**************************************************************//**
NOTE! The following macros should be used in rw s-locking, not the
corresponding function. */
#define rw_lock_s_lock(M) rw_lock_s_lock_func(\
(M), 0, __FILE__, __LINE__)
/**************************************************************//**
NOTE! The following macros should be used in rw s-locking, not the
corresponding function. */
#define rw_lock_s_lock_gen(M, P) rw_lock_s_lock_func(\
(M), (P), __FILE__, __LINE__)
/**************************************************************//**
NOTE! The following macros should be used in rw s-locking, not the
corresponding function. */
#define rw_lock_s_lock_nowait(M, F, L) rw_lock_s_lock_low(\
(M), 0, (F), (L))
/******************************************************************//**
Low-level function which tries to lock an rw-lock in s-mode. Performs no
spinning.
@ -233,33 +330,6 @@ rw_lock_s_unlock_func(
#endif
rw_lock_t* lock); /*!< in/out: rw-lock */
#ifdef UNIV_SYNC_DEBUG
# define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(P, L)
#else
# define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(L)
#endif
/*******************************************************************//**
Releases a shared mode lock. */
#define rw_lock_s_unlock(L) rw_lock_s_unlock_gen(L, 0)
/**************************************************************//**
NOTE! The following macro should be used in rw x-locking, not the
corresponding function. */
#define rw_lock_x_lock(M) rw_lock_x_lock_func(\
(M), 0, __FILE__, __LINE__)
/**************************************************************//**
NOTE! The following macro should be used in rw x-locking, not the
corresponding function. */
#define rw_lock_x_lock_gen(M, P) rw_lock_x_lock_func(\
(M), (P), __FILE__, __LINE__)
/**************************************************************//**
NOTE! The following macros should be used in rw x-locking, not the
corresponding function. */
#define rw_lock_x_lock_nowait(M) rw_lock_x_lock_func_nowait(\
(M), __FILE__, __LINE__)
/******************************************************************//**
NOTE! Use the corresponding macro, not directly this function! Lock an
rw-lock in exclusive mode for the current thread. If the rw-lock is locked
@ -290,14 +360,6 @@ rw_lock_x_unlock_func(
#endif
rw_lock_t* lock); /*!< in/out: rw-lock */
#ifdef UNIV_SYNC_DEBUG
# define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(P, L)
#else
# define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(L)
#endif
/*******************************************************************//**
Releases an exclusive mode lock. */
#define rw_lock_x_unlock(L) rw_lock_x_unlock_gen(L, 0)
/******************************************************************//**
Low-level function which locks an rw-lock in s-mode when we know that it
@ -540,6 +602,9 @@ struct rw_lock_struct {
info list of the lock */
ulint level; /*!< Level in the global latching order. */
#endif /* UNIV_SYNC_DEBUG */
#ifdef UNIV_PFS_RWLOCK
struct PSI_rwlock *pfs_psi;/*!< The instrumentation hook */
#endif
ulint count_os_wait; /*!< Count of os_waits. May not be accurate */
const char* cfile_name;/*!< File name where lock created */
/* last s-lock file/line is not guaranteed to be correct */
@ -578,6 +643,160 @@ struct rw_lock_debug_struct {
};
#endif /* UNIV_SYNC_DEBUG */
/* For performance schema instrumentation, a new set of rwlock
wrap functions are created if "UNIV_PFS_RWLOCK" is defined.
The instrumentations are not planted directly into original
functions, so that we keep the underlying function as they
are. And in case, user wants to "take out" some rwlock from
instrumentation even if performance schema (UNIV_PFS_RWLOCK)
is defined, they can do so by reinstating APIs directly link to
original underlying functions.
The instrumented function names have prefix of "pfs_rw_lock_" vs.
original name prefix of "rw_lock_". Following are list of functions
that have been instrumented:
rw_lock_create()
rw_lock_x_lock()
rw_lock_x_lock_gen()
rw_lock_x_lock_nowait()
rw_lock_x_unlock_gen()
rw_lock_s_lock()
rw_lock_s_lock_gen()
rw_lock_s_lock_nowait()
rw_lock_s_unlock_gen()
rw_lock_free()
Two function APIs rw_lock_x_unlock_direct() and rw_lock_s_unlock_direct()
do not have any caller/user, they are not instrumented.
*/
#ifdef UNIV_PFS_RWLOCK
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_create_func()
NOTE! Please use the corresponding macro rw_lock_create(), not
directly this function! */
UNIV_INLINE
void
pfs_rw_lock_create_func(
/*====================*/
PSI_rwlock_key key, /*!< in: key registered with
performance schema */
rw_lock_t* lock, /*!< in: rw lock */
#ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cmutex_name, /*!< in: mutex name */
#endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline); /*!< in: file line where created */
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_x_lock_func()
NOTE! Please use the corresponding macro rw_lock_x_lock(), not
directly this function! */
UNIV_INLINE
void
pfs_rw_lock_x_lock_func(
/*====================*/
rw_lock_t* lock, /*!< in: pointer to rw-lock */
ulint pass, /*!< in: pass value; != 0, if the lock will
be passed to another thread to unlock */
const char* file_name,/*!< in: file name where lock requested */
ulint line); /*!< in: line where requested */
/******************************************************************//**
Performance schema instrumented wrap function for
rw_lock_x_lock_func_nowait()
NOTE! Please use the corresponding macro, not directly this function!
@return TRUE if success */
UNIV_INLINE
ibool
pfs_rw_lock_x_lock_func_nowait(
/*===========================*/
rw_lock_t* lock, /*!< in: pointer to rw-lock */
const char* file_name,/*!< in: file name where lock requested */
ulint line); /*!< in: line where requested */
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_s_lock_func()
NOTE! Please use the corresponding macro rw_lock_s_lock(), not directly
this function! */
UNIV_INLINE
void
pfs_rw_lock_s_lock_func(
/*====================*/
rw_lock_t* lock, /*!< in: pointer to rw-lock */
ulint pass, /*!< in: pass value; != 0, if the lock will
be passed to another thread to unlock */
const char* file_name,/*!< in: file name where lock requested */
ulint line); /*!< in: line where requested */
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_s_lock_func()
NOTE! Please use the corresponding macro rw_lock_s_lock(), not directly
this function!
@return TRUE if success */
UNIV_INLINE
ibool
pfs_rw_lock_s_lock_low(
/*===================*/
rw_lock_t* lock, /*!< in: pointer to rw-lock */
ulint pass, /*!< in: pass value; != 0, if the
lock will be passed to another
thread to unlock */
const char* file_name, /*!< in: file name where lock requested */
ulint line); /*!< in: line where requested */
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_x_lock_func()
NOTE! Please use the corresponding macro rw_lock_x_lock(), not directly
this function! */
UNIV_INLINE
void
pfs_rw_lock_x_lock_func(
/*====================*/
rw_lock_t* lock, /*!< in: pointer to rw-lock */
ulint pass, /*!< in: pass value; != 0, if the lock will
be passed to another thread to unlock */
const char* file_name,/*!< in: file name where lock requested */
ulint line); /*!< in: line where requested */
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_s_unlock_func()
NOTE! Please use the corresponding macro rw_lock_s_unlock(), not directly
this function! */
UNIV_INLINE
void
pfs_rw_lock_s_unlock_func(
/*======================*/
#ifdef UNIV_SYNC_DEBUG
ulint pass, /*!< in: pass value; != 0, if the
lock may have been passed to another
thread to unlock */
#endif
rw_lock_t* lock); /*!< in/out: rw-lock */
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_s_unlock_func()
NOTE! Please use the corresponding macro rw_lock_x_unlock(), not directly
this function! */
UNIV_INLINE
void
pfs_rw_lock_x_unlock_func(
/*======================*/
#ifdef UNIV_SYNC_DEBUG
ulint pass, /*!< in: pass value; != 0, if the
lock may have been passed to another
thread to unlock */
#endif
rw_lock_t* lock); /*!< in/out: rw-lock */
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_free_func()
NOTE! Please use the corresponding macro rw_lock_free(), not directly
this function! */
UNIV_INLINE
void
pfs_rw_lock_free_func(
/*==================*/
rw_lock_t* lock); /*!< in: rw-lock */
#endif /* UNIV_PFS_RWLOCK */
#ifndef UNIV_NONINL
#include "sync0rw.ic"
#endif

View file

@ -622,3 +622,265 @@ rw_lock_x_unlock_direct(
rw_x_exit_count++;
#endif
}
#ifdef UNIV_PFS_RWLOCK
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_create_func().
NOTE! Please use the corresponding macro rw_lock_create(), not directly
this function! */
UNIV_INLINE
void
pfs_rw_lock_create_func(
/*====================*/
PSI_rwlock_key key, /*!< in: key registered with
performance schema */
rw_lock_t* lock, /*!< in: pointer to memory */
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cmutex_name, /*!< in: mutex name */
# endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline) /*!< in: file line where created */
{
/* Initialize the rwlock for performance schema */
lock->pfs_psi = PSI_server
? PSI_server->init_rwlock(key, lock)
: NULL;
/* The actual function to initialize an rwlock */
rw_lock_create_func(lock,
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
level,
# endif /* UNIV_SYNC_DEBUG */
cmutex_name,
# endif /* UNIV_DEBUG */
cfile_name,
cline);
}
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_x_lock_func()
NOTE! Please use the corresponding macro rw_lock_x_lock(), not directly
this function! */
UNIV_INLINE
void
pfs_rw_lock_x_lock_func(
/*====================*/
rw_lock_t* lock, /*!< in: pointer to rw-lock */
ulint pass, /*!< in: pass value; != 0, if the lock will
be passed to another thread to unlock */
const char* file_name,/*!< in: file name where lock requested */
ulint line) /*!< in: line where requested */
{
struct PSI_rwlock_locker* locker = NULL;
/* Record the entry of rw x lock request in performance schema */
if (UNIV_LIKELY(PSI_server && lock->pfs_psi)) {
locker = PSI_server->get_thread_rwlock_locker(
lock->pfs_psi, PSI_RWLOCK_WRITELOCK);
if (locker) {
PSI_server->start_rwlock_wrwait(locker,
file_name, line);
}
}
rw_lock_x_lock_func(lock, pass, file_name, line);
if (locker) {
PSI_server->end_rwlock_wrwait(locker, 0);
}
}
/******************************************************************//**
Performance schema instrumented wrap function for
rw_lock_x_lock_func_nowait()
NOTE! Please use the corresponding macro rw_lock_x_lock_func(),
not directly this function!
@return TRUE if success */
UNIV_INLINE
ibool
pfs_rw_lock_x_lock_func_nowait(
/*===========================*/
rw_lock_t* lock, /*!< in: pointer to rw-lock */
const char* file_name,/*!< in: file name where lock
requested */
ulint line) /*!< in: line where requested */
{
struct PSI_rwlock_locker* locker = NULL;
ibool ret;
/* Record the entry of rw x lock request in performance schema */
if (UNIV_LIKELY(PSI_server && lock->pfs_psi)) {
locker = PSI_server->get_thread_rwlock_locker(
lock->pfs_psi, PSI_RWLOCK_WRITELOCK);
if (locker) {
PSI_server->start_rwlock_wrwait(locker,
file_name, line);
}
}
ret = rw_lock_x_lock_func_nowait(lock, file_name, line);
if (locker) {
PSI_server->end_rwlock_wrwait(locker, 0);
}
return(ret);
}
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_free_func()
NOTE! Please use the corresponding macro rw_lock_free(), not directly
this function! */
UNIV_INLINE
void
pfs_rw_lock_free_func(
/*==================*/
rw_lock_t* lock) /*!< in: pointer to rw-lock */
{
if (UNIV_LIKELY(PSI_server && lock->pfs_psi)) {
PSI_server->destroy_rwlock(lock->pfs_psi);
lock->pfs_psi = NULL;
}
rw_lock_free_func(lock);
}
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_s_lock_func()
NOTE! Please use the corresponding macro rw_lock_s_lock(), not
directly this function! */
UNIV_INLINE
void
pfs_rw_lock_s_lock_func(
/*====================*/
rw_lock_t* lock, /*!< in: pointer to rw-lock */
ulint pass, /*!< in: pass value; != 0, if the
lock will be passed to another
thread to unlock */
const char* file_name,/*!< in: file name where lock
requested */
ulint line) /*!< in: line where requested */
{
struct PSI_rwlock_locker* locker = NULL;
/* Instrumented to inform we are aquiring a shared rwlock */
if (UNIV_LIKELY(PSI_server && lock->pfs_psi)) {
locker = PSI_server->get_thread_rwlock_locker(
lock->pfs_psi, PSI_RWLOCK_READLOCK);
if (locker) {
PSI_server->start_rwlock_rdwait(locker,
file_name, line);
}
}
rw_lock_s_lock_func(lock, pass, file_name, line);
if (locker) {
PSI_server->end_rwlock_rdwait(locker, 0);
}
}
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_s_lock_func()
NOTE! Please use the corresponding macro rw_lock_s_lock(), not
directly this function!
@return TRUE if success */
UNIV_INLINE
ibool
pfs_rw_lock_s_lock_low(
/*===================*/
rw_lock_t* lock, /*!< in: pointer to rw-lock */
ulint pass, /*!< in: pass value; != 0, if the
lock will be passed to another
thread to unlock */
const char* file_name, /*!< in: file name where lock requested */
ulint line) /*!< in: line where requested */
{
struct PSI_rwlock_locker* locker = NULL;
ibool ret;
/* Instrumented to inform we are aquiring a shared rwlock */
if (UNIV_LIKELY(PSI_server && lock->pfs_psi)) {
locker = PSI_server->get_thread_rwlock_locker(
lock->pfs_psi, PSI_RWLOCK_READLOCK);
if (locker) {
PSI_server->start_rwlock_rdwait(locker,
file_name, line);
}
}
ret = rw_lock_s_lock_low(lock, pass, file_name, line);
if (locker) {
PSI_server->end_rwlock_rdwait(locker, 0);
}
return(ret);
}
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_x_unlock_func()
NOTE! Please use the corresponding macro rw_lock_x_unlock(), not directly
this function! */
UNIV_INLINE
void
pfs_rw_lock_x_unlock_func(
/*======================*/
#ifdef UNIV_SYNC_DEBUG
ulint pass, /*!< in: pass value; != 0, if the
lock may have been passed to another
thread to unlock */
#endif
rw_lock_t* lock) /*!< in/out: rw-lock */
{
/* Inform performance schema we are unlocking the lock */
if (UNIV_LIKELY(PSI_server && lock->pfs_psi)) {
struct PSI_thread* thread;
thread = PSI_server->get_thread();
if (thread) {
PSI_server->unlock_rwlock(thread, lock->pfs_psi);
}
}
rw_lock_x_unlock_func(
#ifdef UNIV_SYNC_DEBUG
pass,
#endif
lock);
}
/******************************************************************//**
Performance schema instrumented wrap function for rw_lock_s_unlock_func()
NOTE! Please use the corresponding macro pfs_rw_lock_s_unlock(), not
directly this function! */
UNIV_INLINE
void
pfs_rw_lock_s_unlock_func(
/*======================*/
#ifdef UNIV_SYNC_DEBUG
ulint pass, /*!< in: pass value; != 0, if the
lock may have been passed to another
thread to unlock */
#endif
rw_lock_t* lock) /*!< in/out: rw-lock */
{
/* Inform performance schema we are unlocking the lock */
if (UNIV_LIKELY(PSI_server && lock->pfs_psi)) {
struct PSI_thread* thread;
thread = PSI_server->get_thread();
if (thread) {
PSI_server->unlock_rwlock(thread, lock->pfs_psi);
}
}
rw_lock_s_unlock_func(
#ifdef UNIV_SYNC_DEBUG
pass,
#endif
lock);
}
#endif /* UNIV_PFS_RWLOCK */

View file

@ -52,6 +52,53 @@ typedef LONG lock_word_t; /*!< On Windows, InterlockedExchange operates
typedef byte lock_word_t;
#endif
#ifdef UNIV_PFS_MUTEX
/* Key defines to register InnoDB mutexes with performance schema */
extern mysql_pfs_key_t autoinc_mutex_key;
extern mysql_pfs_key_t btr_search_enabled_mutex_key;
extern mysql_pfs_key_t buffer_block_mutex_key;
extern mysql_pfs_key_t buf_pool_mutex_key;
extern mysql_pfs_key_t buf_pool_zip_mutex_key;
extern mysql_pfs_key_t cache_last_read_mutex_key;
extern mysql_pfs_key_t dict_foreign_err_mutex_key;
extern mysql_pfs_key_t dict_sys_mutex_key;
extern mysql_pfs_key_t file_format_max_mutex_key;
extern mysql_pfs_key_t fil_system_mutex_key;
extern mysql_pfs_key_t flush_list_mutex_key;
extern mysql_pfs_key_t hash_table_mutex_key;
extern mysql_pfs_key_t ibuf_bitmap_mutex_key;
extern mysql_pfs_key_t ibuf_mutex_key;
extern mysql_pfs_key_t ibuf_pessimistic_insert_mutex_key;
extern mysql_pfs_key_t ios_mutex_key;
extern mysql_pfs_key_t log_sys_mutex_key;
extern mysql_pfs_key_t kernel_mutex_key;
# ifdef UNIV_MEM_DEBUG
extern mysql_pfs_key_t mem_hash_mutex_key;
# endif /* UNIV_MEM_DEBUG */
extern mysql_pfs_key_t mem_pool_mutex_key;
extern mysql_pfs_key_t mutex_list_mutex_key;
extern mysql_pfs_key_t purge_sys_mutex_key;
extern mysql_pfs_key_t recv_sys_mutex_key;
extern mysql_pfs_key_t rseg_mutex_key;
# ifdef UNIV_SYNC_DEBUG
extern mysql_pfs_key_t rw_lock_debug_mutex_key;
# endif /* UNIV_SYNC_DEBUG */
extern mysql_pfs_key_t rw_lock_list_mutex_key;
extern mysql_pfs_key_t rw_lock_mutex_key;
extern mysql_pfs_key_t srv_dict_tmpfile_mutex_key;
extern mysql_pfs_key_t srv_innodb_monitor_mutex_key;
extern mysql_pfs_key_t srv_misc_tmpfile_mutex_key;
extern mysql_pfs_key_t srv_monitor_file_mutex_key;
extern mysql_pfs_key_t syn_arr_mutex_key;
# ifdef UNIV_SYNC_DEBUG
extern mysql_pfs_key_t sync_thread_mutex_key;
# endif /* UNIV_SYNC_DEBUG */
extern mysql_pfs_key_t trx_doublewrite_mutex_key;
extern mysql_pfs_key_t thr_local_mutex_key;
extern mysql_pfs_key_t trx_undo_mutex_key;
extern mysql_pfs_key_t wq_mutex_key;
#endif /* UNIV_PFS_MUTEX */
/******************************************************************//**
Initializes the synchronization data structures. */
UNIV_INTERN
@ -64,24 +111,82 @@ UNIV_INTERN
void
sync_close(void);
/*===========*/
#undef mutex_free /* Fix for MacOS X */
#ifdef UNIV_PFS_MUTEX
/**********************************************************************
Following mutex APIs would be performance schema instrumented
if "UNIV_PFS_MUTEX" is defined:
mutex_create
mutex_enter
mutex_exit
mutex_enter_nowait
mutex_free
These mutex APIs will point to corresponding wrapper functions that contain
the performance schema instrumentation if "UNIV_PFS_MUTEX" is defined.
The instrumented wrapper functions have the prefix of "innodb_".
NOTE! The following macro should be used in mutex operation, not the
corresponding function. */
/******************************************************************//**
Creates, or rather, initializes a mutex object to a specified memory
location (which must be appropriately aligned). The mutex is initialized
in the reset state. Explicit freeing of the mutex with mutex_free is
necessary only if the memory block containing it is freed. */
#ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
# define mutex_create(M, level) \
mutex_create_func((M), #M, (level), __FILE__, __LINE__)
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
# define mutex_create(K, M, level) \
pfs_mutex_create_func((K), (M), #M, (level), __FILE__, __LINE__)
# else
# define mutex_create(K, M, level) \
pfs_mutex_create_func((K), (M), #M, __FILE__, __LINE__)
# endif/* UNIV_SYNC_DEBUG */
# else
# define mutex_create(M, level) \
# define mutex_create(K, M, level) \
pfs_mutex_create_func((K), (M), __FILE__, __LINE__)
# endif /* UNIV_DEBUG */
# define mutex_enter(M) \
pfs_mutex_enter_func((M), __FILE__, __LINE__)
# define mutex_enter_nowait(M) \
pfs_mutex_enter_nowait_func((M), __FILE__, __LINE__)
# define mutex_exit(M) pfs_mutex_exit_func(M)
# define mutex_free(M) pfs_mutex_free_func(M)
#else /* UNIV_PFS_MUTEX */
/* If "UNIV_PFS_MUTEX" is not defined, the mutex APIs point to
original non-instrumented functions */
# ifdef UNIV_DEBUG
# ifdef UNIV_SYNC_DEBUG
# define mutex_create(K, M, level) \
mutex_create_func((M), #M, (level), __FILE__, __LINE__)
# else /* UNIV_SYNC_DEBUG */
# define mutex_create(K, M, level) \
mutex_create_func((M), #M, __FILE__, __LINE__)
# endif
#else
# define mutex_create(M, level) \
# endif /* UNIV_SYNC_DEBUG */
# else /* UNIV_DEBUG */
# define mutex_create(K, M, level) \
mutex_create_func((M), __FILE__, __LINE__)
#endif
# endif /* UNIV_DEBUG */
# define mutex_enter(M) mutex_enter_func((M), __FILE__, __LINE__)
# define mutex_enter_nowait(M) \
mutex_enter_nowait_func((M), __FILE__, __LINE__)
# define mutex_exit(M) mutex_exit_func(M)
# define mutex_free(M) mutex_free_func(M)
#endif /* UNIV_PFS_MUTEX */
/******************************************************************//**
Creates, or rather, initializes a mutex object in a specified memory
@ -102,26 +207,20 @@ mutex_create_func(
const char* cfile_name, /*!< in: file name where created */
ulint cline); /*!< in: file line where created */
#undef mutex_free /* Fix for MacOS X */
/******************************************************************//**
NOTE! Use the corresponding macro mutex_free(), not directly this function!
Calling this function is obligatory only if the memory buffer containing
the mutex is freed. Removes a mutex object from the mutex list. The mutex
is checked to be in the reset state. */
UNIV_INTERN
void
mutex_free(
/*=======*/
mutex_free_func(
/*============*/
mutex_t* mutex); /*!< in: mutex */
/**************************************************************//**
NOTE! The following macro should be used in mutex locking, not the
corresponding function. */
#define mutex_enter(M) mutex_enter_func((M), __FILE__, __LINE__)
/**************************************************************//**
NOTE! The following macro should be used in mutex locking, not the
corresponding function. */
/* NOTE! currently same as mutex_enter! */
#define mutex_enter_fast(M) mutex_enter_func((M), __FILE__, __LINE__)
@ -137,12 +236,6 @@ mutex_enter_func(
mutex_t* mutex, /*!< in: pointer to mutex */
const char* file_name, /*!< in: file name where locked */
ulint line); /*!< in: line where locked */
/**************************************************************//**
NOTE! The following macro should be used in mutex locking, not the
corresponding function. */
#define mutex_enter_nowait(M) \
mutex_enter_nowait_func((M), __FILE__, __LINE__)
/********************************************************************//**
NOTE! Use the corresponding macro in the header file, not this function
directly. Tries to lock the mutex for the current thread. If the lock is not
@ -157,12 +250,86 @@ mutex_enter_nowait_func(
requested */
ulint line); /*!< in: line where requested */
/******************************************************************//**
NOTE! Use the corresponding macro mutex_exit(), not directly this function!
Unlocks a mutex owned by the current thread. */
UNIV_INLINE
void
mutex_exit(
/*=======*/
mutex_exit_func(
/*============*/
mutex_t* mutex); /*!< in: pointer to mutex */
#ifdef UNIV_PFS_MUTEX
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_create(), not directly
this function!
A wrapper function for mutex_create_func(), registers the mutex
with peformance schema if "UNIV_PFS_MUTEX" is defined when
creating the mutex */
UNIV_INLINE
void
pfs_mutex_create_func(
/*==================*/
PSI_mutex_key key, /*!< in: Performance Schema key */
mutex_t* mutex, /*!< in: pointer to memory */
# ifdef UNIV_DEBUG
const char* cmutex_name, /*!< in: mutex name */
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
# endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline); /*!< in: file line where created */
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_enter(), not directly
this function!
This is a performance schema instrumented wrapper function for
mutex_enter_func(). */
UNIV_INLINE
void
pfs_mutex_enter_func(
/*=================*/
mutex_t* mutex, /*!< in: pointer to mutex */
const char* file_name, /*!< in: file name where locked */
ulint line); /*!< in: line where locked */
/********************************************************************//**
NOTE! Please use the corresponding macro mutex_enter_nowait(), not directly
this function!
This is a performance schema instrumented wrapper function for
mutex_enter_nowait_func.
@return 0 if succeed, 1 if not */
UNIV_INLINE
ulint
pfs_mutex_enter_nowait_func(
/*========================*/
mutex_t* mutex, /*!< in: pointer to mutex */
const char* file_name, /*!< in: file name where mutex
requested */
ulint line); /*!< in: line where requested */
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_exit(), not directly
this function!
A wrap function of mutex_exit_func() with peformance schema instrumentation.
Unlocks a mutex owned by the current thread. */
UNIV_INLINE
void
pfs_mutex_exit_func(
/*================*/
mutex_t* mutex); /*!< in: pointer to mutex */
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_free(), not directly
this function!
Wrapper function for mutex_free_func(). Also destroys the performance
schema probes when freeing the mutex */
UNIV_INLINE
void
pfs_mutex_free_func(
/*================*/
mutex_t* mutex); /*!< in: mutex */
#endif /* UNIV_PFS_MUTEX */
#ifdef UNIV_SYNC_DEBUG
/******************************************************************//**
Returns TRUE if no mutex or rw-lock is currently locked.
@ -551,6 +718,10 @@ struct mutex_struct {
const char* cmutex_name; /*!< mutex name */
ulint mutex_type; /*!< 0=usual mutex, 1=rw_lock mutex */
#endif /* UNIV_DEBUG */
#ifdef UNIV_PFS_MUTEX
struct PSI_mutex* pfs_psi; /*!< The performance schema
instrumentation hook */
#endif
};
/** The global array of wait cells for implementation of the databases own

View file

@ -152,11 +152,12 @@ mutex_get_waiters(
}
/******************************************************************//**
NOTE! Use the corresponding macro mutex_exit(), not directly this function!
Unlocks a mutex owned by the current thread. */
UNIV_INLINE
void
mutex_exit(
/*=======*/
mutex_exit_func(
/*============*/
mutex_t* mutex) /*!< in: pointer to mutex */
{
ut_ad(mutex_own(mutex));
@ -220,3 +221,148 @@ mutex_enter_func(
mutex_spin_wait(mutex, file_name, line);
}
#ifdef UNIV_PFS_MUTEX
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_enter(), not directly
this function!
This is a performance schema instrumented wrapper function for
mutex_enter_func(). */
UNIV_INLINE
void
pfs_mutex_enter_func(
/*=================*/
mutex_t* mutex, /*!< in: pointer to mutex */
const char* file_name, /*!< in: file name where locked */
ulint line) /*!< in: line where locked */
{
struct PSI_mutex_locker* locker = NULL;
int result = 0;
if (UNIV_LIKELY(PSI_server && mutex->pfs_psi)) {
locker = PSI_server->get_thread_mutex_locker(
mutex->pfs_psi, PSI_MUTEX_LOCK);
if (locker) {
PSI_server->start_mutex_wait(locker, file_name, line);
}
}
mutex_enter_func(mutex, file_name, line);
if (locker) {
PSI_server->end_mutex_wait(locker, result);
}
}
/********************************************************************//**
NOTE! Please use the corresponding macro mutex_enter_nowait(), not directly
this function!
This is a performance schema instrumented wrapper function for
mutex_enter_nowait_func.
@return 0 if succeed, 1 if not */
UNIV_INLINE
ulint
pfs_mutex_enter_nowait_func(
/*========================*/
mutex_t* mutex, /*!< in: pointer to mutex */
const char* file_name, /*!< in: file name where mutex
requested */
ulint line) /*!< in: line where requested */
{
ulint ret;
struct PSI_mutex_locker* locker = NULL;
int result = 0;
if (UNIV_LIKELY(PSI_server && mutex->pfs_psi)) {
locker = PSI_server->get_thread_mutex_locker(
mutex->pfs_psi, PSI_MUTEX_LOCK);
if (locker) {
PSI_server->start_mutex_wait(locker, file_name, line);
}
}
ret = mutex_enter_nowait_func(mutex, file_name, line);
if (locker) {
PSI_server->end_mutex_wait(locker, result);
}
return(ret);
}
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_exit(), not directly
this function!
A wrap function of mutex_exit_func() with performance schema instrumentation.
Unlocks a mutex owned by the current thread. */
UNIV_INLINE
void
pfs_mutex_exit_func(
/*================*/
mutex_t* mutex) /*!< in: pointer to mutex */
{
if (UNIV_LIKELY(PSI_server && mutex->pfs_psi)) {
struct PSI_thread* thread;
thread = PSI_server->get_thread();
if (thread) {
PSI_server->unlock_mutex(thread, mutex->pfs_psi);
}
}
mutex_exit_func(mutex);
}
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_create(), not directly
this function!
A wrapper function for mutex_create_func(), registers the mutex
with performance schema if "UNIV_PFS_MUTEX" is defined when
creating the mutex */
UNIV_INLINE
void
pfs_mutex_create_func(
/*==================*/
PSI_mutex_key key, /*!< in: Performance Schema key */
mutex_t* mutex, /*!< in: pointer to memory */
# ifdef UNIV_DEBUG
const char* cmutex_name, /*!< in: mutex name */
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
# endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline) /*!< in: file line where created */
{
mutex->pfs_psi = PSI_server
? PSI_server->init_mutex(key, mutex)
: NULL;
mutex_create_func(mutex,
# ifdef UNIV_DEBUG
cmutex_name,
# ifdef UNIV_SYNC_DEBUG
level,
# endif /* UNIV_SYNC_DEBUG */
# endif /* UNIV_DEBUG */
cfile_name,
cline);
}
/******************************************************************//**
NOTE! Please use the corresponding macro mutex_free(), not directly
this function!
Wrapper function for mutex_free_func(). Also destroys the performance
schema probes when freeing the mutex */
UNIV_INLINE
void
pfs_mutex_free_func(
/*===================*/
mutex_t* mutex) /*!< in: mutex */
{
if (UNIV_LIKELY(PSI_server && mutex->pfs_psi)) {
PSI_server->destroy_mutex(mutex->pfs_psi);
mutex->pfs_psi= NULL;
}
mutex_free_func(mutex);
}
#endif /* UNIV_PFS_MUTEX */

View file

@ -144,6 +144,23 @@ Sun Studio */
#endif /* #if (defined(WIN32) || ... */
/* Following defines are to enable performance schema
instrumentation in each of four InnoDB modules if
HAVE_PSI_INTERFACE is defined. */
#ifdef HAVE_PSI_INTERFACE
# define UNIV_PFS_MUTEX
# define UNIV_PFS_RWLOCK
/* For I/O instrumentation, performance schema rely
on a native descriptor to identify the file, this
descriptor could conflict with our OS level descriptor.
Disable IO instrumentation on Windows until this is
resolved */
# ifndef __WIN__
# define UNIV_PFS_IO
# endif
# define UNIV_PFS_THREAD
#endif /* HAVE_PSI_INTERFACE */
/* DEBUG VERSION CONTROL
===================== */

View file

@ -82,6 +82,15 @@ UNIV_INTERN ulint log_fsp_current_free_limit = 0;
/* Global log system variable */
UNIV_INTERN log_t* log_sys = NULL;
#ifdef UNIV_PFS_RWLOCK
UNIV_INTERN mysql_pfs_key_t checkpoint_lock_key;
UNIV_INTERN mysql_pfs_key_t archive_lock_key;
#endif /* UNIV_PFS_RWLOCK */
#ifdef UNIV_PFS_MUTEX
UNIV_INTERN mysql_pfs_key_t log_sys_mutex_key;
#endif /* UNIV_PFS_MUTEX */
#ifdef UNIV_DEBUG
UNIV_INTERN ibool log_do_write = TRUE;
#endif /* UNIV_DEBUG */
@ -756,7 +765,7 @@ log_init(void)
{
log_sys = mem_alloc(sizeof(log_t));
mutex_create(&log_sys->mutex, SYNC_LOG);
mutex_create(log_sys_mutex_key, &log_sys->mutex, SYNC_LOG);
mutex_enter(&(log_sys->mutex));
@ -812,7 +821,8 @@ log_init(void)
log_sys->last_checkpoint_lsn = log_sys->lsn;
log_sys->n_pending_checkpoint_writes = 0;
rw_lock_create(&log_sys->checkpoint_lock, SYNC_NO_ORDER_CHECK);
rw_lock_create(checkpoint_lock_key, &log_sys->checkpoint_lock,
SYNC_NO_ORDER_CHECK);
log_sys->checkpoint_buf_ptr = mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE);
log_sys->checkpoint_buf = ut_align(log_sys->checkpoint_buf_ptr,
@ -828,7 +838,8 @@ log_init(void)
log_sys->n_pending_archive_ios = 0;
rw_lock_create(&log_sys->archive_lock, SYNC_NO_ORDER_CHECK);
rw_lock_create(archive_lock_key, &log_sys->archive_lock,
SYNC_NO_ORDER_CHECK);
log_sys->archive_buf = NULL;
@ -2354,13 +2365,15 @@ loop:
log_archived_file_name_gen(name, group->id,
group->archived_file_no + n_files);
file_handle = os_file_create(name, open_mode, OS_FILE_AIO,
file_handle = os_file_create(innodb_file_log_key,
name, open_mode,
OS_FILE_AIO,
OS_DATA_FILE, &ret);
if (!ret && (open_mode == OS_FILE_CREATE)) {
file_handle = os_file_create(
name, OS_FILE_OPEN, OS_FILE_AIO,
OS_DATA_FILE, &ret);
innodb_file_log_key, name, OS_FILE_OPEN,
OS_FILE_AIO, OS_DATA_FILE, &ret);
}
if (!ret) {

View file

@ -148,6 +148,14 @@ is bigger than the lsn we are able to scan up to, that is an indication that
the recovery failed and the database may be corrupt. */
UNIV_INTERN ib_uint64_t recv_max_page_lsn;
#ifdef UNIV_PFS_THREAD
UNIV_INTERN mysql_pfs_key_t trx_rollback_clean_thread_key;
#endif /* UNIV_PFS_THREAD */
#ifdef UNIV_PFS_MUTEX
UNIV_INTERN mysql_pfs_key_t recv_sys_mutex_key;
#endif /* UNIV_PFS_MUTEX */
/* prototypes */
#ifndef UNIV_HOTBACKUP
@ -175,7 +183,7 @@ recv_sys_create(void)
recv_sys = mem_alloc(sizeof(*recv_sys));
memset(recv_sys, 0x0, sizeof(*recv_sys));
mutex_create(&recv_sys->mutex, SYNC_RECV);
mutex_create(recv_sys_mutex_key, &recv_sys->mutex, SYNC_RECV);
recv_sys->heap = NULL;
recv_sys->addr_hash = NULL;
@ -3426,8 +3434,10 @@ recv_reset_log_files_for_backup(
sprintf(name, "%s%s%lu", log_dir,
ib_logfile_basename, (ulong)i);
log_file = os_file_create_simple(name, OS_FILE_CREATE,
OS_FILE_READ_WRITE, &success);
log_file = os_file_create_simple(innodb_file_log_key,
name, OS_FILE_CREATE,
OS_FILE_READ_WRITE,
&success);
if (!success) {
fprintf(stderr,
"InnoDB: Cannot create %s. Check that"
@ -3466,7 +3476,8 @@ recv_reset_log_files_for_backup(
LOG_BLOCK_HDR_SIZE);
sprintf(name, "%s%s%lu", log_dir, ib_logfile_basename, (ulong)0);
log_file = os_file_create_simple(name, OS_FILE_OPEN,
log_file = os_file_create_simple(innodb_file_log_key,
name, OS_FILE_OPEN,
OS_FILE_READ_WRITE, &success);
if (!success) {
fprintf(stderr, "InnoDB: Cannot open %s.\n", name);
@ -3516,7 +3527,8 @@ try_open_again:
log_archived_file_name_gen(name, group->id, group->archived_file_no);
file_handle = os_file_create(name, OS_FILE_OPEN,
file_handle = os_file_create(innodb_file_log_key,
name, OS_FILE_OPEN,
OS_FILE_LOG, OS_FILE_AIO, &ret);
if (ret == FALSE) {

View file

@ -29,7 +29,13 @@ Created 6/9/1994 Heikki Tuuri
/* The mutex which protects in the debug version the hash table
containing the list of live memory heaps, and also the global
variables below. */
UNIV_INTERN mutex_t mem_hash_mutex;
UNIV_INTERN mutex_t mem_hash_mutex;
#ifdef UNIV_PFS_MUTEX
/* Key to register mem_hash_mutex with performance schema */
UNIV_INTERN mysql_pfs_key_t mem_hash_mutex_key;
#endif /* UNIV_PFS_MUTEX */
# endif /* !UNIV_HOTBACKUP */
/* The following variables contain information about the
@ -149,7 +155,7 @@ mem_init(
/* Initialize the hash table */
ut_a(FALSE == mem_hash_initialized);
mutex_create(&mem_hash_mutex, SYNC_MEM_HASH);
mutex_create(mem_hash_mutex_key, &mem_hash_mutex, SYNC_MEM_HASH);
for (i = 0; i < MEM_HASH_SIZE; i++) {
UT_LIST_INIT(*mem_hash_get_nth_cell(i));

View file

@ -114,6 +114,11 @@ struct mem_pool_struct{
/** The common memory pool */
UNIV_INTERN mem_pool_t* mem_comm_pool = NULL;
#ifdef UNIV_PFS_MUTEX
/* Key to register mutex in mem_pool_struct with performance schema */
UNIV_INTERN mysql_pfs_key_t mem_pool_mutex_key;
#endif /* UNIV_PFS_MUTEX */
/* We use this counter to check that the mem pool mutex does not leak;
this is to track a strange assertion failure reported at
mysql@lists.mysql.com */
@ -219,7 +224,7 @@ mem_pool_create(
pool->buf = ut_malloc_low(size, FALSE, TRUE);
pool->size = size;
mutex_create(&pool->mutex, SYNC_MEM_POOL);
mutex_create(mem_pool_mutex_key, &pool->mutex, SYNC_MEM_POOL);
/* Initialize the free lists */

View file

@ -33,6 +33,11 @@ Created 10/21/1995 Heikki Tuuri
*******************************************************/
#include "os0file.h"
#ifdef UNIV_NONINL
#include "os0file.ic"
#endif
#include "ut0mem.h"
#include "srv0srv.h"
#include "srv0start.h"
@ -141,6 +146,13 @@ the completed IO request and calls completion routine on it.
/** Flag: enable debug printout for asynchronous i/o */
UNIV_INTERN ibool os_aio_print_debug = FALSE;
#ifdef UNIV_PFS_IO
/* Keys to register InnoDB I/O with performance schema */
UNIV_INTERN mysql_pfs_key_t innodb_file_data_key;
UNIV_INTERN mysql_pfs_key_t innodb_file_log_key;
UNIV_INTERN mysql_pfs_key_t innodb_file_temp_key;
#endif /* UNIV_PFS_IO */
/** The asynchronous i/o array slot structure */
typedef struct os_aio_slot_struct os_aio_slot_t;
@ -1020,13 +1032,15 @@ os_file_create_directory(
}
/****************************************************************//**
NOTE! Use the corresponding macro os_file_create_simple(), not directly
this function!
A simple function to open or create a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
os_file_t
os_file_create_simple(
/*==================*/
os_file_create_simple_func(
/*=======================*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file is
@ -1161,13 +1175,15 @@ try_again:
}
/****************************************************************//**
NOTE! Use the corresponding macro
os_file_create_simple_no_error_handling(), not directly this function!
A simple function to open or create a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
os_file_t
os_file_create_simple_no_error_handling(
/*====================================*/
os_file_create_simple_no_error_handling_func(
/*=========================================*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
@ -1316,13 +1332,15 @@ os_file_set_nocache(
}
/****************************************************************//**
NOTE! Use the corresponding macro os_file_create(), not directly
this function!
Opens an existing file or creates a new.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
os_file_t
os_file_create(
/*===========*/
os_file_create_func(
/*================*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
ulint create_mode,/*!< in: OS_FILE_OPEN if an existing file
@ -1707,13 +1725,14 @@ loop:
}
/***********************************************************************//**
NOTE! Use the corresponding macro os_file_rename(), not directly this function!
Renames a file (can also move it to another directory). It is safest that the
file is closed before calling this function.
@return TRUE if success */
UNIV_INTERN
ibool
os_file_rename(
/*===========*/
os_file_rename_func(
/*================*/
const char* oldpath,/*!< in: old file path as a null-terminated
string */
const char* newpath)/*!< in: new file path */
@ -1746,13 +1765,14 @@ os_file_rename(
}
/***********************************************************************//**
NOTE! Use the corresponding macro os_file_close(), not directly this function!
Closes a file handle. In case of error, error number can be retrieved with
os_file_get_last_error.
@return TRUE if success */
UNIV_INTERN
ibool
os_file_close(
/*==========*/
os_file_close_func(
/*===============*/
os_file_t file) /*!< in, own: handle to a file */
{
#ifdef __WIN__
@ -2048,12 +2068,13 @@ os_file_fsync(
#endif /* !__WIN__ */
/***********************************************************************//**
NOTE! Use the corresponding macro os_file_flush(), not directly this function!
Flushes the write buffers of a given file to the disk.
@return TRUE if success */
UNIV_INTERN
ibool
os_file_flush(
/*==========*/
os_file_flush_func(
/*===============*/
os_file_t file) /*!< in, own: handle to a file */
{
#ifdef __WIN__
@ -2360,12 +2381,14 @@ func_exit:
#endif
/*******************************************************************//**
NOTE! Use the corresponding macro os_file_read(), not directly this
function!
Requests a synchronous positioned read operation.
@return TRUE if request was successful, FALSE if fail */
UNIV_INTERN
ibool
os_file_read(
/*=========*/
os_file_read_func(
/*==============*/
os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
ulint offset, /*!< in: least significant 32 bits of file
@ -2483,13 +2506,15 @@ error_handling:
}
/*******************************************************************//**
NOTE! Use the corresponding macro os_file_read_no_error_handling(),
not directly this function!
Requests a synchronous positioned read operation. This function does not do
any error handling. In case of error it returns FALSE.
@return TRUE if request was successful, FALSE if fail */
UNIV_INTERN
ibool
os_file_read_no_error_handling(
/*===========================*/
os_file_read_no_error_handling_func(
/*================================*/
os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
ulint offset, /*!< in: least significant 32 bits of file
@ -2611,12 +2636,14 @@ os_file_read_string(
}
/*******************************************************************//**
NOTE! Use the corresponding macro os_file_write(), not directly
this function!
Requests a synchronous write operation.
@return TRUE if request was successful, FALSE if fail */
UNIV_INTERN
ibool
os_file_write(
/*==========*/
os_file_write_func(
/*===============*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
os_file_t file, /*!< in: handle to a file */
@ -3908,12 +3935,13 @@ os_aio_linux_dispatch(
/*******************************************************************//**
NOTE! Use the corresponding macro os_aio(), not directly this function!
Requests an asynchronous i/o operation.
@return TRUE if request was queued successfully, FALSE if fail */
UNIV_INTERN
ibool
os_aio(
/*===*/
os_aio_func(
/*========*/
ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE */
ulint mode, /*!< in: OS_AIO_NORMAL, ..., possibly ORed
to OS_AIO_SIMULATED_WAKE_LATER: the
@ -4222,6 +4250,18 @@ os_aio_windows_handle(
/* retry failed read/write operation synchronously.
No need to hold array->mutex. */
#ifdef UNIV_PFS_IO
/* This read/write does not go through os_file_read
and os_file_write APIs, need to register with
performance schema explicitly here. */
struct PSI_file_locker* locker = NULL;
register_pfs_file_io_begin(locker, slot->file, slot->len,
(slot->type == OS_FILE_WRITE)
? PSI_FILE_WRITE
: PSI_FILE_READ,
__FILE__, __LINE__);
#endif
switch (slot->type) {
case OS_FILE_WRITE:
ret = WriteFile(slot->file, slot->buf,
@ -4239,6 +4279,10 @@ os_aio_windows_handle(
ut_error;
}
#ifdef UNIV_PFS_IO
register_pfs_file_io_end(locker, len);
#endif
if (!ret && GetLastError() == ERROR_IO_PENDING) {
/* aio was queued successfully!
We want a synchronous i/o operation on a

View file

@ -212,6 +212,11 @@ os_thread_exit(
fprintf(stderr, "Thread exits, id %lu\n",
os_thread_pf(os_thread_get_curr_id()));
#endif
#ifdef UNIV_PFS_THREAD
pfs_delete_thread();
#endif
os_mutex_enter(os_sync_mutex);
os_thread_count--;
os_mutex_exit(os_sync_mutex);

View file

@ -2145,9 +2145,22 @@ row_merge_file_create(
/*==================*/
merge_file_t* merge_file) /*!< out: merge file structure */
{
#ifdef UNIV_PFS_IO
/* This temp file open does not go through normal
file APIs, add instrumentation to register with
performance schema */
struct PSI_file_locker* locker = NULL;
register_pfs_file_open_begin(locker, innodb_file_temp_key,
PSI_FILE_OPEN,
"Innodb Merge Temp File",
__FILE__, __LINE__);
#endif
merge_file->fd = innobase_mysql_tmpfile();
merge_file->offset = 0;
merge_file->n_rec = 0;
#ifdef UNIV_PFS_IO
register_pfs_file_open_end(locker, merge_file->fd);
#endif
}
/*********************************************************************//**
@ -2158,10 +2171,19 @@ row_merge_file_destroy(
/*===================*/
merge_file_t* merge_file) /*!< out: merge file structure */
{
#ifdef UNIV_PFS_IO
struct PSI_file_locker* locker = NULL;
register_pfs_file_io_begin(locker, merge_file->fd, 0, PSI_FILE_CLOSE,
__FILE__, __LINE__);
#endif
if (merge_file->fd != -1) {
close(merge_file->fd);
merge_file->fd = -1;
}
#ifdef UNIV_PFS_IO
register_pfs_file_io_end(locker, 0);
#endif
}
/*********************************************************************//**

View file

@ -423,6 +423,20 @@ UNIV_INTERN mutex_t srv_innodb_monitor_mutex;
/* Mutex for locking srv_monitor_file */
UNIV_INTERN mutex_t srv_monitor_file_mutex;
#ifdef UNIV_PFS_MUTEX
/* Key to register kernel_mutex with performance schema */
UNIV_INTERN mysql_pfs_key_t kernel_mutex_key;
/* Key to register srv_innodb_monitor_mutex with performance schema */
UNIV_INTERN mysql_pfs_key_t srv_innodb_monitor_mutex_key;
/* Key to register srv_monitor_file_mutex with performance schema */
UNIV_INTERN mysql_pfs_key_t srv_monitor_file_mutex_key;
/* Key to register srv_dict_tmpfile_mutex with performance schema */
UNIV_INTERN mysql_pfs_key_t srv_dict_tmpfile_mutex_key;
/* Key to register the mutex with performance schema */
UNIV_INTERN mysql_pfs_key_t srv_misc_tmpfile_mutex_key;
#endif /* UNIV_PFS_MUTEX */
/* Temporary file for innodb monitor output */
UNIV_INTERN FILE* srv_monitor_file;
/* Mutex for locking srv_dict_tmpfile.
@ -938,9 +952,10 @@ srv_init(void)
srv_sys = mem_alloc(sizeof(srv_sys_t));
kernel_mutex_temp = mem_alloc(sizeof(mutex_t));
mutex_create(&kernel_mutex, SYNC_KERNEL);
mutex_create(kernel_mutex_key, &kernel_mutex, SYNC_KERNEL);
mutex_create(&srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK);
mutex_create(srv_innodb_monitor_mutex_key,
&srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK);
srv_sys->threads = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
@ -1979,6 +1994,11 @@ srv_monitor_thread(
fprintf(stderr, "Lock timeout thread starts, id %lu\n",
os_thread_pf(os_thread_get_curr_id()));
#endif
#ifdef UNIV_PFS_THREAD
pfs_register_thread(srv_monitor_thread_key);
#endif
UT_NOT_USED(arg);
srv_last_monitor_time = time(NULL);
last_table_monitor_time = time(NULL);
@ -2130,6 +2150,10 @@ srv_lock_timeout_thread(
double wait_time;
ulint i;
#ifdef UNIV_PFS_THREAD
pfs_register_thread(srv_lock_timeout_thread_key);
#endif
loop:
/* When someone is waiting for a lock, we wake up every second
and check if a timeout has passed for a lock wait */
@ -2235,6 +2259,11 @@ srv_error_monitor_thread(
fprintf(stderr, "Error monitor thread starts, id %lu\n",
os_thread_pf(os_thread_get_curr_id()));
#endif
#ifdef UNIV_PFS_THREAD
pfs_register_thread(srv_error_monitor_thread_key);
#endif
loop:
srv_error_monitor_active = TRUE;
@ -2403,6 +2432,11 @@ srv_master_thread(
fprintf(stderr, "Master thread starts, id %lu\n",
os_thread_pf(os_thread_get_curr_id()));
#endif
#ifdef UNIV_PFS_THREAD
pfs_register_thread(srv_master_thread_key);
#endif
srv_main_thread_process_no = os_proc_get_number();
srv_main_thread_id = os_thread_pf(os_thread_get_curr_id());
@ -2828,6 +2862,7 @@ suspend_thread:
already when the event wait ends */
os_thread_exit(NULL);
}
/* When there is user activity, InnoDB will set the event and the

View file

@ -142,6 +142,19 @@ static char* srv_monitor_file_name;
#define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD
#define SRV_MAX_N_PENDING_SYNC_IOS 100
#ifdef UNIV_PFS_THREAD
/* Keys to register InnoDB threads with performance schema */
UNIV_INTERN mysql_pfs_key_t io_handler_thread_key;
UNIV_INTERN mysql_pfs_key_t srv_lock_timeout_thread_key;
UNIV_INTERN mysql_pfs_key_t srv_error_monitor_thread_key;
UNIV_INTERN mysql_pfs_key_t srv_monitor_thread_key;
UNIV_INTERN mysql_pfs_key_t srv_master_thread_key;
#endif /* UNIV_PFS_THREAD */
#ifdef UNIV_PFS_MUTEX
/* Key to register ios_mutex_key with performance schema */
UNIV_INTERN mysql_pfs_key_t ios_mutex_key;
#endif /* UNIV_PFS_MUTEX */
/*********************************************************************//**
Convert a numeric string that optionally ends in G or M, to a number
@ -471,6 +484,11 @@ io_handler_thread(
fprintf(stderr, "Io handler thread %lu starts, id %lu\n", segment,
os_thread_pf(os_thread_get_curr_id()));
#endif
#ifdef UNIV_PFS_THREAD
pfs_register_thread(io_handler_thread_key);
#endif /* UNIV_PFS_THREAD */
for (i = 0;; i++) {
fil_aio_wait(segment);
@ -584,7 +602,8 @@ open_or_create_log_file(
sprintf(name + dirnamelen, "%s%lu", "ib_logfile", (ulong) i);
files[i] = os_file_create(name, OS_FILE_CREATE, OS_FILE_NORMAL,
files[i] = os_file_create(innodb_file_log_key, name,
OS_FILE_CREATE, OS_FILE_NORMAL,
OS_LOG_FILE, &ret);
if (ret == FALSE) {
if (os_file_get_last_error(FALSE) != OS_FILE_ALREADY_EXISTS
@ -602,7 +621,8 @@ open_or_create_log_file(
return(DB_ERROR);
}
files[i] = os_file_create(name, OS_FILE_OPEN, OS_FILE_AIO,
files[i] = os_file_create(innodb_file_log_key, name,
OS_FILE_OPEN, OS_FILE_AIO,
OS_LOG_FILE, &ret);
if (!ret) {
fprintf(stderr,
@ -767,7 +787,8 @@ open_or_create_data_files(
/* First we try to create the file: if it already
exists, ret will get value FALSE */
files[i] = os_file_create(name, OS_FILE_CREATE,
files[i] = os_file_create(innodb_file_data_key,
name, OS_FILE_CREATE,
OS_FILE_NORMAL,
OS_DATA_FILE, &ret);
@ -794,7 +815,8 @@ open_or_create_data_files(
srv_start_raw_disk_in_use = TRUE;
srv_created_new_raw = TRUE;
files[i] = os_file_create(name, OS_FILE_OPEN_RAW,
files[i] = os_file_create(innodb_file_data_key,
name, OS_FILE_OPEN_RAW,
OS_FILE_NORMAL,
OS_DATA_FILE, &ret);
if (!ret) {
@ -827,14 +849,17 @@ open_or_create_data_files(
if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) {
files[i] = os_file_create(
innodb_file_data_key,
name, OS_FILE_OPEN_RAW,
OS_FILE_NORMAL, OS_DATA_FILE, &ret);
} else if (i == 0) {
files[i] = os_file_create(
innodb_file_data_key,
name, OS_FILE_OPEN_RETRY,
OS_FILE_NORMAL, OS_DATA_FILE, &ret);
} else {
files[i] = os_file_create(
innodb_file_data_key,
name, OS_FILE_OPEN, OS_FILE_NORMAL,
OS_DATA_FILE, &ret);
}
@ -977,7 +1002,7 @@ skip_size_check:
ios = 0;
mutex_create(&ios_mutex, SYNC_NO_ORDER_CHECK);
mutex_create(ios_mutex_key, &ios_mutex, SYNC_NO_ORDER_CHECK);
return(DB_SUCCESS);
}
@ -1238,7 +1263,8 @@ innobase_start_or_create_for_mysql(void)
return((int) err);
}
mutex_create(&srv_monitor_file_mutex, SYNC_NO_ORDER_CHECK);
mutex_create(srv_monitor_file_mutex_key,
&srv_monitor_file_mutex, SYNC_NO_ORDER_CHECK);
if (srv_innodb_status) {
srv_monitor_file_name = mem_alloc(
@ -1260,14 +1286,16 @@ innobase_start_or_create_for_mysql(void)
}
}
mutex_create(&srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION);
mutex_create(srv_dict_tmpfile_mutex_key,
&srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION);
srv_dict_tmpfile = os_file_create_tmpfile();
if (!srv_dict_tmpfile) {
return(DB_ERROR);
}
mutex_create(&srv_misc_tmpfile_mutex, SYNC_ANY_LATCH);
mutex_create(srv_misc_tmpfile_mutex_key,
&srv_misc_tmpfile_mutex, SYNC_ANY_LATCH);
srv_misc_tmpfile = os_file_create_tmpfile();
if (!srv_misc_tmpfile) {

View file

@ -138,6 +138,11 @@ struct sync_array_struct {
since creation of the array */
};
#ifdef UNIV_PFS_MUTEX
/* Key to register the mutex with performance schema */
UNIV_INTERN mysql_pfs_key_t syn_arr_mutex_key;
#endif
#ifdef UNIV_SYNC_DEBUG
/******************************************************************//**
This function is called only in the debug version. Detects a deadlock
@ -247,7 +252,8 @@ sync_array_create(
if (protection == SYNC_ARRAY_OS_MUTEX) {
arr->os_mutex = os_mutex_create(NULL);
} else if (protection == SYNC_ARRAY_MUTEX) {
mutex_create(&arr->mutex, SYNC_NO_ORDER_CHECK);
mutex_create(syn_arr_mutex_key,
&arr->mutex, SYNC_NO_ORDER_CHECK);
} else {
ut_error;
}

View file

@ -168,12 +168,22 @@ UNIV_INTERN ib_int64_t rw_x_exit_count = 0;
UNIV_INTERN rw_lock_list_t rw_lock_list;
UNIV_INTERN mutex_t rw_lock_list_mutex;
#ifdef UNIV_PFS_MUTEX
UNIV_INTERN mysql_pfs_key_t rw_lock_list_mutex_key;
UNIV_INTERN mysql_pfs_key_t rw_lock_mutex_key;
#endif /* UNIV_PFS_MUTEX */
#ifdef UNIV_SYNC_DEBUG
/* The global mutex which protects debug info lists of all rw-locks.
To modify the debug info list of an rw-lock, this mutex has to be
acquired in addition to the mutex protecting the lock. */
UNIV_INTERN mutex_t rw_lock_debug_mutex;
# ifdef UNIV_PFS_MUTEX
UNIV_INTERN mysql_pfs_key_t rw_lock_debug_mutex_key;
# endif
/* If deadlock detection does not get immediately the mutex,
it may wait for this event */
UNIV_INTERN os_event_t rw_lock_debug_event;
@ -231,7 +241,7 @@ rw_lock_create_func(
# ifdef UNIV_SYNC_DEBUG
ulint level, /*!< in: level */
# endif /* UNIV_SYNC_DEBUG */
const char* cmutex_name, /*!< in: mutex name */
const char* cmutex_name, /*!< in: mutex name */
#endif /* UNIV_DEBUG */
const char* cfile_name, /*!< in: file name where created */
ulint cline) /*!< in: file line where created */
@ -240,7 +250,8 @@ rw_lock_create_func(
created, then the following call initializes the sync system. */
#ifndef INNODB_RW_LOCKS_USE_ATOMICS
mutex_create(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK);
mutex_create(rw_lock_mutex_key, rw_lock_get_mutex(lock),
SYNC_NO_ORDER_CHECK);
lock->mutex.cfile_name = cfile_name;
lock->mutex.cline = cline;
@ -298,8 +309,8 @@ the rw-lock is freed. Removes an rw-lock object from the global list. The
rw-lock is checked to be in the non-locked state. */
UNIV_INTERN
void
rw_lock_free(
/*=========*/
rw_lock_free_func(
/*==============*/
rw_lock_t* lock) /*!< in: rw-lock */
{
ut_ad(rw_lock_validate(lock));
@ -607,7 +618,7 @@ rw_lock_x_lock_func(
{
ulint index; /*!< index of the reserved wait cell */
ulint i; /*!< spin round count */
ibool spinning = FALSE;
ibool spinning = FALSE;
ut_ad(rw_lock_validate(lock));

View file

@ -198,6 +198,10 @@ UNIV_INTERN sync_thread_t* sync_thread_level_arrays;
/** Mutex protecting sync_thread_level_arrays */
UNIV_INTERN mutex_t sync_thread_mutex;
# ifdef UNIV_PFS_MUTEX
UNIV_INTERN mysql_pfs_key_t sync_thread_mutex_key;
# endif /* UNIV_PFS_MUTEX */
#endif /* UNIV_SYNC_DEBUG */
/** Global list of database mutexes (not OS mutexes) created. */
@ -206,6 +210,10 @@ UNIV_INTERN ut_list_base_node_t mutex_list;
/** Mutex protecting the mutex_list variable */
UNIV_INTERN mutex_t mutex_list_mutex;
#ifdef UNIV_PFS_MUTEX
UNIV_INTERN mysql_pfs_key_t mutex_list_mutex_key;
#endif /* UNIV_PFS_MUTEX */
#ifdef UNIV_SYNC_DEBUG
/** Latching order checks start when this is set TRUE */
UNIV_INTERN ibool sync_order_checks_on = FALSE;
@ -302,13 +310,14 @@ mutex_create_func(
}
/******************************************************************//**
NOTE! Use the corresponding macro mutex_free(), not directly this function!
Calling this function is obligatory only if the memory buffer containing
the mutex is freed. Removes a mutex object from the mutex list. The mutex
is checked to be in the reset state. */
UNIV_INTERN
void
mutex_free(
/*=======*/
mutex_free_func(
/*============*/
mutex_t* mutex) /*!< in: mutex */
{
ut_ad(mutex_validate(mutex));
@ -1399,18 +1408,22 @@ sync_init(void)
/* Init the mutex list and create the mutex to protect it. */
UT_LIST_INIT(mutex_list);
mutex_create(&mutex_list_mutex, SYNC_NO_ORDER_CHECK);
mutex_create(mutex_list_mutex_key, &mutex_list_mutex,
SYNC_NO_ORDER_CHECK);
#ifdef UNIV_SYNC_DEBUG
mutex_create(&sync_thread_mutex, SYNC_NO_ORDER_CHECK);
mutex_create(sync_thread_mutex_key, &sync_thread_mutex,
SYNC_NO_ORDER_CHECK);
#endif /* UNIV_SYNC_DEBUG */
/* Init the rw-lock list and create the mutex to protect it. */
UT_LIST_INIT(rw_lock_list);
mutex_create(&rw_lock_list_mutex, SYNC_NO_ORDER_CHECK);
mutex_create(rw_lock_list_mutex_key, &rw_lock_list_mutex,
SYNC_NO_ORDER_CHECK);
#ifdef UNIV_SYNC_DEBUG
mutex_create(&rw_lock_debug_mutex, SYNC_NO_ORDER_CHECK);
mutex_create(rw_lock_debug_mutex_key, &rw_lock_debug_mutex,
SYNC_NO_ORDER_CHECK);
rw_lock_debug_event = os_event_create(NULL);
rw_lock_debug_waiters = FALSE;

View file

@ -53,6 +53,11 @@ static hash_table_t* thr_local_hash = NULL;
/** Thread local data */
typedef struct thr_local_struct thr_local_t;
#ifdef UNIV_PFS_MUTEX
/* Key to register the mutex with performance schema */
UNIV_INTERN mysql_pfs_key_t thr_local_mutex_key;
#endif /* UNIV_PFS_MUTEX */
/** @brief Thread local data.
The private data for each thread should be put to
the structure below and the accessor functions written
@ -244,7 +249,8 @@ thr_local_init(void)
thr_local_hash = hash_create(OS_THREAD_MAX_N + 100);
mutex_create(&thr_local_mutex, SYNC_THR_LOCAL);
mutex_create(thr_local_mutex_key,
&thr_local_mutex, SYNC_THR_LOCAL);
}
/********************************************************************

View file

@ -186,6 +186,15 @@ INFORMATION SCHEMA tables is fetched and later retrieved by the C++
code in handler/i_s.cc. */
UNIV_INTERN trx_i_s_cache_t* trx_i_s_cache = &trx_i_s_cache_static;
/* Key to register the lock/mutex with performance schema */
#ifdef UNIV_PFS_RWLOCK
UNIV_INTERN mysql_pfs_key_t trx_i_s_cache_lock_key;
#endif /* UNIV_PFS_RWLOCK */
#ifdef UNIV_PFS_MUTEX
UNIV_INTERN mysql_pfs_key_t cache_last_read_mutex_key;
#endif /* UNIV_PFS_MUTEX */
/*******************************************************************//**
For a record lock that is in waiting state retrieves the only bit that
is set, for a table lock returns ULINT_UNDEFINED.
@ -1246,11 +1255,13 @@ trx_i_s_cache_init(
release trx_i_s_cache_t::last_read_mutex
release trx_i_s_cache_t::rw_lock */
rw_lock_create(&cache->rw_lock, SYNC_TRX_I_S_RWLOCK);
rw_lock_create(trx_i_s_cache_lock_key, &cache->rw_lock,
SYNC_TRX_I_S_RWLOCK);
cache->last_read = 0;
mutex_create(&cache->last_read_mutex, SYNC_TRX_I_S_LAST_READ);
mutex_create(cache_last_read_mutex_key,
&cache->last_read_mutex, SYNC_TRX_I_S_LAST_READ);
table_cache_init(&cache->innodb_trx, sizeof(i_s_trx_row_t));
table_cache_init(&cache->innodb_locks, sizeof(i_s_locks_row_t));

View file

@ -51,6 +51,16 @@ UNIV_INTERN trx_purge_t* purge_sys = NULL;
which needs no purge */
UNIV_INTERN trx_undo_rec_t trx_purge_dummy_rec;
#ifdef UNIV_PFS_RWLOCK
/* Key to register trx_purge_latch with performance schema */
UNIV_INTERN mysql_pfs_key_t trx_purge_latch_key;
#endif /* UNIV_PFS_RWLOCK */
#ifdef UNIV_PFS_MUTEX
/* Key to register purge_sys_mutex with performance schema */
UNIV_INTERN mysql_pfs_key_t purge_sys_mutex_key;
#endif /* UNIV_PFS_MUTEX */
/*****************************************************************//**
Checks if trx_id is >= purge_view: then it is guaranteed that its update
undo log still exists in the system.
@ -227,9 +237,11 @@ trx_purge_sys_create(void)
purge_sys->purge_undo_no = ut_dulint_zero;
purge_sys->next_stored = FALSE;
rw_lock_create(&purge_sys->latch, SYNC_PURGE_LATCH);
rw_lock_create(trx_purge_latch_key,
&purge_sys->latch, SYNC_PURGE_LATCH);
mutex_create(&purge_sys->mutex, SYNC_PURGE_SYS);
mutex_create(purge_sys_mutex_key,
&purge_sys->mutex, SYNC_PURGE_SYS);
purge_sys->heap = mem_heap_create(256);

View file

@ -615,6 +615,10 @@ trx_rollback_or_clean_all_recovered(
/*!< in: a dummy parameter required by
os_thread_create */
{
#ifdef UNIV_PFS_THREAD
pfs_register_thread(trx_rollback_clean_thread_key);
#endif /* UNIV_PFS_THREAD */
trx_rollback_or_clean_recovered(TRUE);
/* We count the number of threads in os_thread_exit(). A created

View file

@ -34,6 +34,11 @@ Created 3/26/1996 Heikki Tuuri
#include "srv0srv.h"
#include "trx0purge.h"
#ifdef UNIV_PFS_MUTEX
/* Key to register rseg_mutex_key with performance schema */
UNIV_INTERN mysql_pfs_key_t rseg_mutex_key;
#endif /* UNIV_PFS_MUTEX */
/******************************************************************//**
Looks for a rollback segment, based on the rollback segment id.
@return rollback segment */
@ -207,7 +212,7 @@ trx_rseg_mem_create(
rseg->zip_size = zip_size;
rseg->page_no = page_no;
mutex_create(&rseg->mutex, SYNC_RSEG);
mutex_create(rseg_mutex_key, &rseg->mutex, SYNC_RSEG);
UT_LIST_ADD_LAST(rseg_list, trx_sys->rseg_list, rseg);

View file

@ -126,6 +126,12 @@ static const char* file_format_name_map[] = {
static const ulint FILE_FORMAT_NAME_N
= sizeof(file_format_name_map) / sizeof(file_format_name_map[0]);
#ifdef UNIV_PFS_MUTEX
/* Key to register the mutex with performance schema */
UNIV_INTERN mysql_pfs_key_t trx_doublewrite_mutex_key;
UNIV_INTERN mysql_pfs_key_t file_format_max_mutex_key;
#endif /* UNIV_PFS_MUTEX */
#ifndef UNIV_HOTBACKUP
/** This is used to track the maximum file format id known to InnoDB. It's
updated via SET GLOBAL innodb_file_format_check = 'x' or when we open
@ -179,7 +185,8 @@ trx_doublewrite_init(
os_do_not_call_flush_at_each_write = TRUE;
#endif /* UNIV_DO_FLUSH */
mutex_create(&trx_doublewrite->mutex, SYNC_DOUBLEWRITE);
mutex_create(trx_doublewrite_mutex_key,
&trx_doublewrite->mutex, SYNC_DOUBLEWRITE);
trx_doublewrite->first_free = 0;
@ -1283,7 +1290,8 @@ void
trx_sys_file_format_init(void)
/*==========================*/
{
mutex_create(&file_format_max.mutex, SYNC_FILE_FORMAT_TAG);
mutex_create(file_format_max_mutex_key,
&file_format_max.mutex, SYNC_FILE_FORMAT_TAG);
/* We don't need a mutex here, as this function should only
be called once at start up. */
@ -1376,8 +1384,9 @@ trx_sys_read_file_format_id(
dulint file_format_id;
*format_id = ULINT_UNDEFINED;
file = os_file_create_simple_no_error_handling(
innodb_file_data_key,
pathname,
OS_FILE_OPEN,
OS_FILE_READ_ONLY,
@ -1456,8 +1465,9 @@ trx_sys_read_pertable_file_format_id(
ib_uint32_t flags;
*format_id = ULINT_UNDEFINED;
file = os_file_create_simple_no_error_handling(
innodb_file_data_key,
pathname,
OS_FILE_OPEN,
OS_FILE_READ_ONLY,

View file

@ -51,6 +51,11 @@ UNIV_INTERN sess_t* trx_dummy_sess = NULL;
the kernel mutex */
UNIV_INTERN ulint trx_n_mysql_transactions = 0;
#ifdef UNIV_PFS_MUTEX
/* Key to register the mutex with performance schema */
UNIV_INTERN mysql_pfs_key_t trx_undo_mutex_key;
#endif /* UNIV_PFS_MUTEX */
/*************************************************************//**
Set detailed error message for the transaction. */
UNIV_INTERN
@ -129,7 +134,7 @@ trx_create(
trx->mysql_log_file_name = NULL;
trx->mysql_log_offset = 0;
mutex_create(&trx->undo_mutex, SYNC_TRX_UNDO);
mutex_create(trx_undo_mutex_key, &trx->undo_mutex, SYNC_TRX_UNDO);
trx->rseg = NULL;

View file

@ -25,6 +25,11 @@ A work queue
Created 4/26/2006 Osku Salerma
************************************************************************/
#ifdef UNIV_PFS_MUTEX
/* Key to register wq_mutex with performance schema */
UNIV_INTERN mysql_pfs_key_t wq_mutex_key;
#endif /* UNIV_PFS_MUTEX */
/****************************************************************//**
Create a new work queue.
@return work queue */
@ -35,7 +40,7 @@ ib_wqueue_create(void)
{
ib_wqueue_t* wq = mem_alloc(sizeof(ib_wqueue_t));
mutex_create(&wq->mutex, SYNC_WORK_QUEUE);
mutex_create(wq_mutex_key, &wq->mutex, SYNC_WORK_QUEUE);
wq->items = ib_list_create();
wq->event = os_event_create(NULL);