Commit 8610f05a authored by jyang's avatar jyang

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ä
parent 29a1b47c
......@@ -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 \
......
......@@ -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));
......
......@@ -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);
}
......
......@@ -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)) {
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
......
This diff is collapsed.
......@@ -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);
......
This diff is collapsed.
This diff is collapsed.
......@@ -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 */
......
......@@ -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 */
......
This diff is collapsed.
......@@ -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 */
This diff is collapsed.
......@@ -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 */
......@@ -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
===================== */
......
......@@ -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) {
......
......@@ -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) {
......
......@@ -30,6 +30,12 @@ Created 6/9/1994 Heikki Tuuri
containing the list of live memory heaps, and also the global
variables below. */
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));
......
......@@ -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 */
......
......@@ -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
......
......@@ -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);
......
......@@ -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
}
/*********************************************************************//**
......
......@@ -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
......
......@@ -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) {
......
......@@ -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;
}
......
......@@ -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;
......@@ -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));
......
......@@ -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;
......
......@@ -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);
}
/********************************************************************
......
......@@ -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));
......
......@@ -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);
......
......@@ -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
......
......@@ -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);
......
......@@ -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. */
......@@ -1378,6 +1386,7 @@ trx_sys_read_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,
......@@ -1458,6 +1467,7 @@ trx_sys_read_pertable_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,
......
......@@ -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;
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment