diff --git a/mysql-test/suite/sys_vars/r/innodb_sync_pool_size_basic.result b/mysql-test/suite/sys_vars/r/innodb_sync_pool_size_basic.result new file mode 100644 index 000000000000..8852de56822e --- /dev/null +++ b/mysql-test/suite/sys_vars/r/innodb_sync_pool_size_basic.result @@ -0,0 +1,53 @@ +'#---------------------BS_STVARS_022_01----------------------#' +SELECT @@GLOBAL.innodb_sync_pool_size; +@@GLOBAL.innodb_sync_pool_size +1024 +1024 Expected +'#---------------------BS_STVARS_022_02----------------------#' +SET @@GLOBAL.innodb_sync_pool_size=1; +ERROR HY000: Variable 'innodb_sync_pool_size' is a read only variable +Expected error 'Read only variable' +SELECT @@GLOBAL.innodb_sync_pool_size; +@@GLOBAL.innodb_sync_pool_size +1024 +1024 Expected +'#---------------------BS_STVARS_022_03----------------------#' +SELECT @@GLOBAL.innodb_sync_pool_size = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='innodb_sync_pool_size'; +@@GLOBAL.innodb_sync_pool_size = VARIABLE_VALUE +1 +1 Expected +SELECT @@GLOBAL.innodb_sync_pool_size; +@@GLOBAL.innodb_sync_pool_size +1024 +1024 Expected +SELECT VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='innodb_sync_pool_size'; +VARIABLE_VALUE +1024 +1024 Expected +'#---------------------BS_STVARS_022_04----------------------#' +SELECT @@innodb_sync_pool_size = @@GLOBAL.innodb_sync_pool_size; +@@innodb_sync_pool_size = @@GLOBAL.innodb_sync_pool_size +1 +1 Expected +'#---------------------BS_STVARS_022_05----------------------#' +SELECT @@innodb_sync_pool_size; +@@innodb_sync_pool_size +1024 +1024 Expected +SELECT @@local.innodb_sync_pool_size; +ERROR HY000: Variable 'innodb_sync_pool_size' is a GLOBAL variable +Expected error 'Variable is a GLOBAL variable' +SELECT @@SESSION.innodb_sync_pool_size; +ERROR HY000: Variable 'innodb_sync_pool_size' is a GLOBAL variable +Expected error 'Variable is a GLOBAL variable' +SELECT @@GLOBAL.innodb_sync_pool_size; +@@GLOBAL.innodb_sync_pool_size +1024 +1024 Expected +SELECT innodb_sync_pool_size = @@SESSION.innodb_sync_pool_size; +ERROR 42S22: Unknown column 'innodb_sync_pool_size' in 'field list' +Expected error 'Unknown column' diff --git a/mysql-test/suite/sys_vars/t/innodb_sync_pool_size_basic.test b/mysql-test/suite/sys_vars/t/innodb_sync_pool_size_basic.test new file mode 100644 index 000000000000..d8c956ebea64 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/innodb_sync_pool_size_basic.test @@ -0,0 +1,93 @@ +################## mysql-test\t\innodb_sync_pool_size_basic.test ############## +# # +# Variable Name: innodb_sync_pool_size # +# Scope: Global # +# Access Type: Static # +# Data Type: numeric # +# # +# # +# Creation Date: 2012-02-27 # +# Author : Steaphan Greene # +# # +# # +# Description: Test Cases of Dynamic System Variable innodb_sync_pool_size # +# that checks the behavior of this variable. # +# # +############################################################################### + +--source include/have_innodb.inc + +--echo '#---------------------BS_STVARS_022_01----------------------#' +#################################################################### +# Displaying default value # +#################################################################### +SELECT @@GLOBAL.innodb_sync_pool_size; +--echo 1024 Expected + + +--echo '#---------------------BS_STVARS_022_02----------------------#' +#################################################################### +# Check if Value can set # +#################################################################### + +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET @@GLOBAL.innodb_sync_pool_size=1; +--echo Expected error 'Read only variable' + +SELECT @@GLOBAL.innodb_sync_pool_size; +--echo 1024 Expected + + + + +--echo '#---------------------BS_STVARS_022_03----------------------#' +################################################################# +# Check if the value in GLOBAL Table matches value in variable # +################################################################# + +SELECT @@GLOBAL.innodb_sync_pool_size = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='innodb_sync_pool_size'; +--echo 1 Expected + +SELECT @@GLOBAL.innodb_sync_pool_size; +--echo 1024 Expected + +SELECT VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='innodb_sync_pool_size'; +--echo 1024 Expected + + + +--echo '#---------------------BS_STVARS_022_04----------------------#' +################################################################################ +# Check if accessing variable with and without GLOBAL point to same variable # +################################################################################ +SELECT @@innodb_sync_pool_size = @@GLOBAL.innodb_sync_pool_size; +--echo 1 Expected + + + +--echo '#---------------------BS_STVARS_022_05----------------------#' +################################################################################ +# Check if innodb_sync_pool_size can be accessed with and without @@ sign # +################################################################################ + +SELECT @@innodb_sync_pool_size; +--echo 1024 Expected + +--Error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@local.innodb_sync_pool_size; +--echo Expected error 'Variable is a GLOBAL variable' + +--Error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@SESSION.innodb_sync_pool_size; +--echo Expected error 'Variable is a GLOBAL variable' + +SELECT @@GLOBAL.innodb_sync_pool_size; +--echo 1024 Expected + +--Error ER_BAD_FIELD_ERROR +SELECT innodb_sync_pool_size = @@SESSION.innodb_sync_pool_size; +--echo Expected error 'Unknown column' diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 3b67b49a9e90..acdf2a8a5a92 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -134,6 +134,7 @@ static ulong innobase_write_io_threads; static long innobase_buffer_pool_instances = 1; static long long innobase_buffer_pool_size, innobase_log_file_size; +static unsigned long innobase_sync_pool_size; /** Percentage of the buffer pool to reserve for 'old' blocks. Connected to buf_LRU_old_ratio. */ @@ -3292,6 +3293,7 @@ innobase_init( #endif /* defined(__WIN__) && !defined(_WIN64) */ } srv_buf_pool_size = (ulint) innobase_buffer_pool_size; + srv_sync_pool_size = (ulint) innobase_sync_pool_size; srv_buf_pool_instances = (ulint) innobase_buffer_pool_instances; srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size; @@ -16375,6 +16377,12 @@ static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size, "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.", NULL, NULL, 128*1024*1024L, 5*1024*1024L, LONGLONG_MAX, 1024*1024L); +static MYSQL_SYSVAR_ULONG(sync_pool_size, innobase_sync_pool_size, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "The size of the shared sync pool buffer InnoDB uses to store system lock" + "and condition variables.", + NULL, NULL, 1024UL, 1UL, 1024UL * 1024UL, 1UL); + #if defined UNIV_DEBUG || defined UNIV_PERF_DEBUG static MYSQL_SYSVAR_ULONG(page_hash_locks, srv_n_page_hash_locks, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, @@ -16900,6 +16908,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(autoextend_increment), MYSQL_SYSVAR(buffer_pool_size), MYSQL_SYSVAR(buffer_pool_populate), + MYSQL_SYSVAR(sync_pool_size), MYSQL_SYSVAR(buffer_pool_instances), MYSQL_SYSVAR(buffer_pool_filename), MYSQL_SYSVAR(buffer_pool_dump_now), diff --git a/storage/innobase/include/os0sync.h b/storage/innobase/include/os0sync.h index 367c2a319243..cc707e756948 100644 --- a/storage/innobase/include/os0sync.h +++ b/storage/innobase/include/os0sync.h @@ -70,6 +70,14 @@ typedef CONDITION_VARIABLE os_cond_t; typedef pthread_mutex_t fast_mutex_t; /** Native condition variable */ typedef pthread_cond_t os_cond_t; + +#define BIT63 (1ULL << 63) +#define INC_SIGNAL_COUNT(ev) { ++(ev)->stats; } +#define SIGNAL_COUNT(ev) (static_cast((ev)->stats & ~BIT63)) +#define SET_IS_SET(ev) { (ev)->stats |= BIT63; } +#define CLEAR_IS_SET(ev) { (ev)->stats &= ~BIT63; } +#define IS_SET(ev) (((ev)->stats & BIT63) != 0) + #endif /** Structure that includes Performance Schema Probe pfs_psi @@ -82,26 +90,50 @@ struct os_fast_mutex_t { #endif }; +/** Operating system event */ +typedef struct os_event_struct os_event_struct_t; +/** Operating system event wrapper */ +typedef struct os_event_wrapper_struct os_event_wrapper_struct_t; /** Operating system event handle */ -typedef struct os_event* os_event_t; +typedef os_event_wrapper_struct_t* os_event_t; + +typedef struct os_event_support_struct { + os_fast_mutex_t os_mutex; /*!< this mutex protects the next + fields */ + os_cond_t cond_var; /*!< condition variable is used in + waiting for the event */ +} os_event_support_t; + +extern os_event_support_t* os_support; /** An asynchronous signal sent between threads */ -struct os_event { +struct os_event_struct { #ifdef __WIN__ HANDLE handle; /*!< kernel event object, slow, used on older Windows */ #endif - os_fast_mutex_t os_mutex; /*!< this mutex protects the next - fields */ - ibool is_set; /*!< this is TRUE when the event is + ib_uint64_t stats; /*!< msb: "is_set" (boolean bit field) + This is TRUE when the event is in the signaled state, i.e., a thread does not stop if it tries to wait for this event */ - ib_int64_t signal_count; /*!< this is incremented each time + /*!< rest: "signal_count" (63-bit uint) + this is incremented each time the event becomes signaled */ - os_cond_t cond_var; /*!< condition variable is used in - waiting for the event */ - UT_LIST_NODE_T(os_event_t) os_event_list; + os_event_support_t* sup; /*!< Pointer to OS-support data + For events created by os_event_create() + this will point to an allocated set of + data exclusively for this event. + For events created by os_event_create2() + this will point to one of the shared + sync data pool elements + allocated by os_sync_init() + */ +}; + +struct os_event_wrapper_struct { + struct os_event_struct ev; /*!< Actual event struct */ + UT_LIST_NODE_T(os_event_wrapper_struct_t) os_event_list; /*!< list of all created events */ }; @@ -146,14 +178,20 @@ UNIV_INTERN os_event_t os_event_create(void); /*==================*/ +UNIV_INTERN +void +os_event_create2( +/*============*/ + os_event_struct_t* event); /*!< in: pointer to pre-allocated struct */ /**********************************************************//** Sets an event semaphore to the signaled state: lets waiting threads proceed. */ +#define os_event_set(e) os_event_set2(&((e)->ev)) UNIV_INTERN void -os_event_set( +os_event_set2( /*=========*/ - os_event_t event); /*!< in: event to set */ + os_event_struct_t* event); /*!< in: event to set */ /**********************************************************//** Resets an event semaphore to the nonsignaled state. Waiting threads will stop to wait for the event. @@ -161,18 +199,25 @@ The return value should be passed to os_even_wait_low() if it is desired that this thread should not wait in case of an intervening call to os_event_set() between this os_event_reset() and the os_event_wait_low() call. See comments for os_event_wait_low(). */ +#define os_event_reset(e) os_event_reset2(&((e)->ev)) UNIV_INTERN ib_int64_t -os_event_reset( +os_event_reset2( /*===========*/ - os_event_t event); /*!< in: event to reset */ + os_event_struct_t* event); /*!< in: event to reset */ /**********************************************************//** Frees an event object. */ UNIV_INTERN void os_event_free( /*==========*/ - os_event_t event); /*!< in: event to free */ + os_event_t event); /*!< in: wrapped event to free */ + +UNIV_INTERN +void +os_event_free2( +/*************/ + os_event_struct_t* event); /*!< in: event to free */ /**********************************************************//** Waits for an event object until it is in the signaled state. @@ -191,11 +236,12 @@ thread C calls os_event_wait() [infinite wait!] Where such a scenario is possible, to avoid infinite wait, the value returned by os_event_reset() should be passed in as reset_sig_count. */ +#define os_event_wait_low(e,c) os_event_wait_low2(&((e)->ev),c) UNIV_INTERN void -os_event_wait_low( +os_event_wait_low2( /*==============*/ - os_event_t event, /*!< in: event to wait */ + os_event_struct_t* event, /*!< in: event to wait */ ib_int64_t reset_sig_count);/*!< in: zero or the value returned by previous call of os_event_reset(). */ @@ -207,11 +253,12 @@ os_event_wait_low( Waits for an event object until it is in the signaled state or a timeout is exceeded. In Unix the timeout is always infinite. @return 0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */ +#define os_event_wait_time_low(e,t,u) os_event_wait_time_low2(&((e)->ev),t,u) UNIV_INTERN ulint -os_event_wait_time_low( +os_event_wait_time_low2( /*===================*/ - os_event_t event, /*!< in: event to wait */ + os_event_struct_t* event, /*!< in: event to wait */ ulint time_in_usec, /*!< in: timeout in microseconds, or OS_SYNC_INFINITE_TIME */ diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index ffaa0b24720e..a35db7d75829 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -293,6 +293,7 @@ extern ulong srv_flush_neighbors; /*!< whether or not to flush neighbors of a block */ extern ulint srv_buf_pool_old_size; /*!< previously requested size */ extern ulint srv_buf_pool_curr_size; /*!< current size in bytes */ +extern ulint srv_sync_pool_size; /*!< requested size (number) */ extern ulint srv_mem_pool_size; extern ulint srv_lock_table_size; diff --git a/storage/innobase/include/sync0rw.h b/storage/innobase/include/sync0rw.h index 6b1e99bbbeec..5139175bdbd4 100644 --- a/storage/innobase/include/sync0rw.h +++ b/storage/innobase/include/sync0rw.h @@ -101,6 +101,7 @@ struct rw_lock_debug_t; #endif /* UNIV_SYNC_DEBUG */ typedef UT_LIST_BASE_NODE_T(rw_lock_t) rw_lock_list_t; +extern ulint rw_lock_count; extern rw_lock_list_t rw_lock_list; extern ib_mutex_t rw_lock_list_mutex; @@ -594,8 +595,9 @@ struct rw_lock_t { /*!< Thread id of writer thread. Is only guaranteed to have sane and non-stale value iff recursive flag is set. */ - os_event_t event; /*!< Used by sync0arr.cc for thread queueing */ - os_event_t wait_ex_event; + os_event_struct_t event; + /*!< Used by sync0arr.cc for thread queueing */ + os_event_struct_t wait_ex_event; /*!< Event for next-writer to wait on. A thread must decrement lock_word before waiting. */ #ifndef INNODB_RW_LOCKS_USE_ATOMICS diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic index f2d4215a0511..89753f5fe75f 100644 --- a/storage/innobase/include/sync0rw.ic +++ b/storage/innobase/include/sync0rw.ic @@ -460,7 +460,7 @@ rw_lock_s_unlock_func( /* wait_ex waiter exists. It may not be asleep, but we signal anyway. We do not wake other waiters, because they can't exist without wait_ex waiter and wait_ex waiter goes first.*/ - os_event_set(lock->wait_ex_event); + os_event_set2(&lock->wait_ex_event); sync_array_object_signalled(); } @@ -517,7 +517,7 @@ rw_lock_x_unlock_func( exist when there is a writer. */ if (lock->waiters) { rw_lock_reset_waiter_flag(lock); - os_event_set(lock->event); + os_event_set2(&lock->event); sync_array_object_signalled(); } } diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h index 95d9ef664987..2b4b618cdc7b 100644 --- a/storage/innobase/include/sync0sync.h +++ b/storage/innobase/include/sync0sync.h @@ -738,7 +738,8 @@ implementation of a mutual exclusion semaphore. */ /** InnoDB mutex */ struct ib_mutex_t { - os_event_t event; /*!< Used by sync0arr.cc for the wait queue */ + os_event_struct_t event; + /*!< Used by sync0arr.cc for the wait queue */ volatile lock_word_t lock_word; /*!< lock_word is the target of the atomic test-and-set instruction when atomic operations are enabled. */ diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 4fe5504e59a3..bb875fdd10f2 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -5756,7 +5756,7 @@ os_aio_print( srv_io_thread_function[i]); #ifndef __WIN__ - if (os_aio_segment_wait_events[i]->is_set) { + if (IS_SET(&os_aio_segment_wait_events[i]->ev)) { fprintf(file, " ev set"); } #endif /* __WIN__ */ diff --git a/storage/innobase/os/os0sync.cc b/storage/innobase/os/os0sync.cc index 0f5a4572ba53..10b0ba50963a 100644 --- a/storage/innobase/os/os0sync.cc +++ b/storage/innobase/os/os0sync.cc @@ -25,6 +25,7 @@ Created 9/6/1995 Heikki Tuuri *******************************************************/ #include "os0sync.h" +#include "sync0rw.h" #ifdef UNIV_NONINL #include "os0sync.ic" #endif @@ -58,12 +59,14 @@ static ibool os_sync_mutex_inited = FALSE; /** TRUE when os_sync_free() is being executed */ static ibool os_sync_free_called = FALSE; +UNIV_INTERN os_event_support_t* os_support = NULL; + /** This is incremented by 1 in os_thread_create and decremented by 1 in os_thread_exit */ UNIV_INTERN ulint os_thread_count = 0; /** The list of all events created */ -static UT_LIST_BASE_NODE_T(os_event) os_event_list; +static UT_LIST_BASE_NODE_T(os_event_wrapper_struct_t) os_event_list; /** The list of all OS 'slow' mutexes */ static UT_LIST_BASE_NODE_T(os_mutex_t) os_mutex_list; @@ -282,6 +285,21 @@ os_cond_module_init(void) #endif } +/*********************************************************//** +Initializes underlying os_support structure for events. */ +static +void +os_support_init(os_event_support_t *ev_sup) +/*==============*/ +{ +#ifndef PFS_SKIP_EVENT_MUTEX + os_fast_mutex_init(event_os_mutex_key, &(ev_sup->os_mutex)); +#else + os_fast_mutex_init(PFS_NOT_INSTRUMENTED, &(ev_sup->os_mutex)); +#endif + os_cond_init(&(ev_sup->cond_var)); +} + /*********************************************************//** Initializes global event and OS 'slow' mutex lists. */ UNIV_INTERN @@ -300,6 +318,12 @@ os_sync_init(void) os_sync_mutex = os_mutex_create(); + os_support = (os_event_support_t*)ut_malloc(sizeof(os_event_support_t) + * srv_sync_pool_size); + for(unsigned int i = 0; i < srv_sync_pool_size; ++i) { + os_support_init(os_support + i); + } + os_sync_mutex_inited = TRUE; } @@ -338,6 +362,34 @@ os_sync_free(void) mutex = UT_LIST_GET_FIRST(os_mutex_list); } os_sync_free_called = FALSE; + + /* This is the code that should run to clean up + int i = 0; + for(; i < srv_sync_pool_size; ++i) { + os_fast_mutex_free(&os_support[i].os_mutex); + os_cond_destroy(&os_support[i].cond_var); + } + ...but we do this instead, since we don't clean up the events pool, + and so should not remove the pthread data they all point to: */ + os_fast_mutex_count -= srv_sync_pool_size; + + if (UNIV_UNLIKELY(os_sync_mutex_inited)) { + os_mutex_enter(os_sync_mutex); + } + + /* Account for the events, and their fast_mutexes, + * within the (never de-initialized) rw_lock structs */ + os_event_count -= rw_lock_count*2; + rw_lock_count = 0; /* Not used after here, just reset for neatness. */ + + if (UNIV_UNLIKELY(os_sync_mutex_inited)) { + os_mutex_exit(os_sync_mutex); + } + +#ifdef UNIV_DEBUG_VALGRIND + if (os_support != NULL) + ut_free(os_support); +#endif } /*********************************************************//** @@ -350,8 +402,37 @@ os_event_t os_event_create(void) /*==================*/ { - os_event_t event; + os_event_t event = (os_event_t)ut_malloc( + sizeof(struct os_event_wrapper_struct)); + os_event_create2(&event->ev); + + /*Note: this overwrites the "sup" element, that was pointed to a + shared sync data pool element by os_event_create2, with a + dynamically-allocated set of data exclusively for this event. */ + event->ev.sup = (os_event_support_t*)ut_malloc(sizeof(os_event_support_t)); + + os_support_init(event->ev.sup); + + if (UNIV_LIKELY(os_sync_mutex_inited)) { + os_mutex_enter(os_sync_mutex); + } + + /* Put to the list of events */ + UT_LIST_ADD_FIRST(os_event_list, os_event_list, event); + + if (UNIV_LIKELY(os_sync_mutex_inited)) { + os_mutex_exit(os_sync_mutex); + } + + return(event); +} +UNIV_INTERN +void +os_event_create2( +/*=============*/ + os_event_struct_t* event)/*!< in: pre-allocated struct, or NULL */ +{ #ifdef __WIN__ if(!srv_use_native_conditions) { @@ -367,44 +448,34 @@ os_event_create(void) } else /* Windows with condition variables */ #endif { - event = static_cast(ut_malloc(sizeof *event)); - -#ifndef PFS_SKIP_EVENT_MUTEX - os_fast_mutex_init(event_os_mutex_key, &event->os_mutex); -#else - os_fast_mutex_init(PFS_NOT_INSTRUMENTED, &event->os_mutex); -#endif - - os_cond_init(&(event->cond_var)); - - event->is_set = FALSE; - /* We return this value in os_event_reset(), which can then be be used to pass to the os_event_wait_low(). The value of zero is reserved in os_event_wait_low() for the case when the caller does not want to pass any signal_count value. To distinguish between the two cases we initialize signal_count to 1 here. */ - event->signal_count = 1; + event->stats = 1; } /* The os_sync_mutex can be NULL because during startup an event can be created [ because it's embedded in the mutex/rwlock ] before this module has been initialized */ - if (os_sync_mutex != NULL) { + if (UNIV_LIKELY(os_sync_mutex_inited)) { os_mutex_enter(os_sync_mutex); } - /* Put to the list of events */ - UT_LIST_ADD_FIRST(os_event_list, os_event_list, event); - + /* Note: this sets the "sup" element to point to a shared sync data + pool element. The event itself is not shared, but the underlying + OS data used by them is. Using a smaller shared pool of these + elements saves a great deal of memory. This is only done for the + buffer pool events. The other events call os_event_create(), and + this will be overwritten if this was called via os_event_create. */ + event->sup = os_support + (os_event_count % srv_sync_pool_size); os_event_count++; - if (os_sync_mutex != NULL) { + if (UNIV_LIKELY(os_sync_mutex_inited)) { os_mutex_exit(os_sync_mutex); } - - return(event); } /**********************************************************//** @@ -412,9 +483,9 @@ Sets an event semaphore to the signaled state: lets waiting threads proceed. */ UNIV_INTERN void -os_event_set( -/*=========*/ - os_event_t event) /*!< in: event to set */ +os_event_set2( +/*==========*/ + os_event_struct_t* event) /*!< in: event to set */ { ut_a(event); @@ -425,17 +496,17 @@ os_event_set( } #endif - os_fast_mutex_lock(&(event->os_mutex)); + os_fast_mutex_lock(&(event->sup->os_mutex)); - if (event->is_set) { + if (IS_SET(event)) { /* Do nothing */ } else { - event->is_set = TRUE; - event->signal_count += 1; - os_cond_broadcast(&(event->cond_var)); + INC_SIGNAL_COUNT(event); + SET_IS_SET(event); + os_cond_broadcast(&(event->sup->cond_var)); } - os_fast_mutex_unlock(&(event->os_mutex)); + os_fast_mutex_unlock(&(event->sup->os_mutex)); } /**********************************************************//** @@ -448,9 +519,9 @@ os_event_wait_low() call. See comments for os_event_wait_low(). @return current signal_count. */ UNIV_INTERN ib_int64_t -os_event_reset( +os_event_reset2( /*===========*/ - os_event_t event) /*!< in: event to reset */ + os_event_struct_t* event) /*!< in: event to reset */ { ib_int64_t ret = 0; @@ -463,16 +534,16 @@ os_event_reset( } #endif - os_fast_mutex_lock(&(event->os_mutex)); + os_fast_mutex_lock(&(event->sup->os_mutex)); - if (!event->is_set) { + if (!IS_SET(event)) { /* Do nothing */ } else { - event->is_set = FALSE; + CLEAR_IS_SET(event); } - ret = event->signal_count; + ret = SIGNAL_COUNT(event); - os_fast_mutex_unlock(&(event->os_mutex)); + os_fast_mutex_unlock(&(event->sup->os_mutex)); return(ret); } @@ -494,16 +565,16 @@ os_event_free_internal( ut_a(event); /* This is to avoid freeing the mutex twice */ - os_fast_mutex_free(&(event->os_mutex)); + os_fast_mutex_free(&(event->ev.sup->os_mutex)); - os_cond_destroy(&(event->cond_var)); + os_cond_destroy(&(event->ev.sup->cond_var)); } /* Remove from the list of events */ UT_LIST_REMOVE(os_event_list, os_event_list, event); os_event_count--; - + ut_free(event->ev.sup); ut_free(event); } @@ -515,6 +586,29 @@ os_event_free( /*==========*/ os_event_t event) /*!< in: event to free */ +{ + os_fast_mutex_free(&(event->ev.sup->os_mutex)); + os_cond_destroy(&(event->ev.sup->cond_var)); + ut_free(event->ev.sup); + + os_event_free2(&event->ev); + + os_mutex_enter(os_sync_mutex); + + UT_LIST_REMOVE(os_event_list, os_event_list, event); + + os_mutex_exit(os_sync_mutex); + + ut_free(event); +} + +/**********************************************************//** +Cleans up an event object. */ +UNIV_INTERN +void +os_event_free2( +/*===========*/ + os_event_struct_t* event) /*!< in: event to free */ { ut_a(event); #ifdef __WIN__ @@ -523,21 +617,15 @@ os_event_free( } else /*Windows with condition variables */ #endif { - os_fast_mutex_free(&(event->os_mutex)); - - os_cond_destroy(&(event->cond_var)); + event->sup = NULL; } /* Remove from the list of events */ os_mutex_enter(os_sync_mutex); - UT_LIST_REMOVE(os_event_list, os_event_list, event); - os_event_count--; os_mutex_exit(os_sync_mutex); - - ut_free(event); } /**********************************************************//** @@ -559,9 +647,9 @@ value returned by os_event_reset() should be passed in as reset_sig_count. */ UNIV_INTERN void -os_event_wait_low( +os_event_wait_low2( /*==============*/ - os_event_t event, /*!< in: event to wait */ + os_event_struct_t* event, /*!< in: event to wait */ ib_int64_t reset_sig_count)/*!< in: zero or the value returned by previous call of os_event_reset(). */ @@ -582,21 +670,21 @@ os_event_wait_low( } #endif - os_fast_mutex_lock(&event->os_mutex); + os_fast_mutex_lock(&event->sup->os_mutex); if (!reset_sig_count) { - reset_sig_count = event->signal_count; + reset_sig_count = SIGNAL_COUNT(event); } - while (!event->is_set && event->signal_count == reset_sig_count) { - os_cond_wait(&(event->cond_var), &(event->os_mutex)); + while (!IS_SET(event) && SIGNAL_COUNT(event) == reset_sig_count) { + os_cond_wait(&(event->sup->cond_var), &(event->sup->os_mutex)); /* Solaris manual said that spurious wakeups may occur: we have to check if the event really has been signaled after we came here to wait */ } - os_fast_mutex_unlock(&event->os_mutex); + os_fast_mutex_unlock(&event->sup->os_mutex); } /**********************************************************//** @@ -605,9 +693,9 @@ a timeout is exceeded. @return 0 if success, OS_SYNC_TIME_EXCEEDED if timeout was exceeded */ UNIV_INTERN ulint -os_event_wait_time_low( +os_event_wait_time_low2( /*===================*/ - os_event_t event, /*!< in: event to wait */ + os_event_struct_t* event, /*!< in: event to wait */ ulint time_in_usec, /*!< in: timeout in microseconds, or OS_SYNC_INFINITE_TIME */ @@ -683,20 +771,20 @@ os_event_wait_time_low( #endif /* __WIN__ */ - os_fast_mutex_lock(&event->os_mutex); + os_fast_mutex_lock(&event->sup->os_mutex); if (!reset_sig_count) { - reset_sig_count = event->signal_count; + reset_sig_count = SIGNAL_COUNT(event); } do { - if (event->is_set || event->signal_count != reset_sig_count) { + if (IS_SET(event) || SIGNAL_COUNT(event) != reset_sig_count) { break; } timed_out = os_cond_wait_timed( - &event->cond_var, &event->os_mutex, + &event->sup->cond_var, &event->sup->os_mutex, #ifndef __WIN__ &abstime #else @@ -706,7 +794,7 @@ os_event_wait_time_low( } while (!timed_out); - os_fast_mutex_unlock(&event->os_mutex); + os_fast_mutex_unlock(&event->sup->os_mutex); return(timed_out ? OS_SYNC_TIME_EXCEEDED : 0); } diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 6a88947aa20f..6b88620fe914 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -233,6 +233,8 @@ UNIV_INTERN ulong srv_flush_neighbors = 1; UNIV_INTERN ulint srv_buf_pool_old_size; /* current size in kilobytes */ UNIV_INTERN ulint srv_buf_pool_curr_size = 0; +/* requested size (number) */ +UNIV_INTERN ulint srv_sync_pool_size = 1024; /* size in bytes */ UNIV_INTERN ulint srv_mem_pool_size = ULINT_MAX; UNIV_INTERN ulint srv_lock_table_size = ULINT_MAX; diff --git a/storage/innobase/sync/sync0arr.cc b/storage/innobase/sync/sync0arr.cc index 00c6138a66c2..3131dfd256e7 100644 --- a/storage/innobase/sync/sync0arr.cc +++ b/storage/innobase/sync/sync0arr.cc @@ -286,7 +286,7 @@ sync_array_validate( /*******************************************************************//** Returns the event that the thread owning the cell waits for. */ static -os_event_t +os_event_struct_t* sync_cell_get_event( /*================*/ sync_cell_t* cell) /*!< in: non-empty sync array cell */ @@ -294,11 +294,11 @@ sync_cell_get_event( ulint type = cell->request_type; if (type == SYNC_MUTEX) { - return(((ib_mutex_t*) cell->wait_object)->event); + return(&((ib_mutex_t*) cell->wait_object)->event); } else if (type == RW_LOCK_WAIT_EX) { - return(((rw_lock_t*) cell->wait_object)->wait_ex_event); + return(&((rw_lock_t*) cell->wait_object)->wait_ex_event); } else { /* RW_LOCK_SHARED and RW_LOCK_EX wait on the same event */ - return(((rw_lock_t*) cell->wait_object)->event); + return(&((rw_lock_t*) cell->wait_object)->event); } } @@ -318,7 +318,7 @@ sync_array_reserve_cell( ulint* index) /*!< out: index of the reserved cell */ { sync_cell_t* cell; - os_event_t event; + os_event_struct_t* event; ulint i; ut_a(object); @@ -360,7 +360,7 @@ sync_array_reserve_cell( the value of signal_count at which the event was reset. */ event = sync_cell_get_event(cell); - cell->signal_count = os_event_reset(event); + cell->signal_count = os_event_reset2(event); cell->reservation_time = ut_time(); @@ -387,7 +387,7 @@ sync_array_wait_event( ulint index) /*!< in: index of the reserved cell */ { sync_cell_t* cell; - os_event_t event; + os_event_struct_t* event; ut_a(arr); @@ -421,7 +421,7 @@ sync_array_wait_event( #endif sync_array_exit(arr); - os_event_wait_low(event, cell->signal_count); + os_event_wait_low2(event, cell->signal_count); sync_array_free_cell(arr, index); } @@ -852,11 +852,11 @@ sync_array_wake_threads_if_sema_free_low( count++; if (sync_arr_cell_can_wake_up(cell)) { - os_event_t event; + os_event_struct_t* event; event = sync_cell_get_event(cell); - os_event_set(event); + os_event_set2(event); } } } diff --git a/storage/innobase/sync/sync0rw.cc b/storage/innobase/sync/sync0rw.cc index 2d3d16e90653..2400d920482e 100644 --- a/storage/innobase/sync/sync0rw.cc +++ b/storage/innobase/sync/sync0rw.cc @@ -42,6 +42,7 @@ Created 9/11/1995 Heikki Tuuri #include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */ #include "ha_prototypes.h" +UNIV_INTERN ulint rw_lock_count = 0; /* IMPLEMENTATION OF THE RW_LOCK ============================= @@ -264,8 +265,8 @@ rw_lock_create_func( lock->last_x_file_name = "not yet reserved"; lock->last_s_line = 0; lock->last_x_line = 0; - lock->event = os_event_create(); - lock->wait_ex_event = os_event_create(); + os_event_create2(&lock->event); + os_event_create2(&lock->wait_ex_event); mutex_enter(&rw_lock_list_mutex); @@ -273,6 +274,7 @@ rw_lock_create_func( || UT_LIST_GET_FIRST(rw_lock_list)->magic_n == RW_LOCK_MAGIC_N); UT_LIST_ADD_FIRST(list, rw_lock_list, lock); + rw_lock_count++; mutex_exit(&rw_lock_list_mutex); } @@ -301,9 +303,9 @@ rw_lock_free_func( mutex = rw_lock_get_mutex(lock); #endif /* !INNODB_RW_LOCKS_USE_ATOMICS */ - os_event_free(lock->event); + os_event_free2(&lock->event); - os_event_free(lock->wait_ex_event); + os_event_free2(&lock->wait_ex_event); ut_ad(UT_LIST_GET_PREV(list, lock) == NULL || UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N); @@ -311,6 +313,7 @@ rw_lock_free_func( || UT_LIST_GET_NEXT(list, lock)->magic_n == RW_LOCK_MAGIC_N); UT_LIST_REMOVE(list, rw_lock_list, lock); + rw_lock_count--; mutex_exit(&rw_lock_list_mutex); diff --git a/storage/innobase/sync/sync0sync.cc b/storage/innobase/sync/sync0sync.cc index 4df35053d0d5..a6eb926344fb 100644 --- a/storage/innobase/sync/sync0sync.cc +++ b/storage/innobase/sync/sync0sync.cc @@ -279,7 +279,7 @@ mutex_create_func( os_fast_mutex_init(PFS_NOT_INSTRUMENTED, &mutex->os_fast_mutex); mutex->lock_word = 0; #endif - mutex->event = os_event_create(); + os_event_create2(&mutex->event); mutex_set_waiters(mutex, 0); #ifdef UNIV_DEBUG mutex->magic_n = MUTEX_MAGIC_N; @@ -361,7 +361,7 @@ mutex_free_func( mutex_exit(&mutex_list_mutex); } - os_event_free(mutex->event); + os_event_free2(&mutex->event); #ifdef UNIV_MEM_DEBUG func_exit: #endif /* UNIV_MEM_DEBUG */ @@ -594,7 +594,7 @@ mutex_signal_object( /* The memory order of resetting the waiters field and signaling the object is important. See LEMMA 1 above. */ - os_event_set(mutex->event); + os_event_set2(&mutex->event); sync_array_object_signalled(); }