Many files:

  Free all OS sync primitives and allocated memory in InnoDB shutdown
parent cfda0a16
...@@ -10,15 +10,16 @@ Created 9/6/1995 Heikki Tuuri ...@@ -10,15 +10,16 @@ Created 9/6/1995 Heikki Tuuri
#define os0sync_h #define os0sync_h
#include "univ.i" #include "univ.i"
#include "ut0lst.h"
#ifdef __WIN__ #ifdef __WIN__
#define os_fast_mutex_t CRITICAL_SECTION #define os_fast_mutex_t CRITICAL_SECTION
typedef void* os_event_t; typedef HANDLE os_event_t;
#else #else
typedef pthread_mutex_t os_fast_mutex_t; typedef pthread_mutex_t os_fast_mutex_t;
typedef struct os_event_struct os_event_struct_t;
typedef os_event_struct_t* os_event_t;
struct os_event_struct { struct os_event_struct {
os_fast_mutex_t os_mutex; /* this mutex protects the next os_fast_mutex_t os_mutex; /* this mutex protects the next
fields */ fields */
...@@ -26,9 +27,9 @@ struct os_event_struct { ...@@ -26,9 +27,9 @@ struct os_event_struct {
not reserved */ not reserved */
pthread_cond_t cond_var; /* condition variable is used in pthread_cond_t cond_var; /* condition variable is used in
waiting for the event */ waiting for the event */
UT_LIST_NODE_T(os_event_struct_t) os_event_list;
/* list of all created events */
}; };
typedef struct os_event_struct os_event_struct_t;
typedef os_event_struct_t* os_event_t;
#endif #endif
typedef struct os_mutex_struct os_mutex_str_t; typedef struct os_mutex_struct os_mutex_str_t;
...@@ -38,13 +39,30 @@ typedef os_mutex_str_t* os_mutex_t; ...@@ -38,13 +39,30 @@ typedef os_mutex_str_t* os_mutex_t;
#define OS_SYNC_TIME_EXCEEDED 1 #define OS_SYNC_TIME_EXCEEDED 1
/* Mutex protecting the thread count */ /* Mutex protecting the thread count and event and OS 'slow' mutex lists */
extern os_mutex_t os_thread_count_mutex; extern os_mutex_t os_sync_mutex;
/* This is incremented by 1 in os_thread_create and decremented by 1 in /* This is incremented by 1 in os_thread_create and decremented by 1 in
os_thread_exit */ os_thread_exit */
extern ulint os_thread_count; extern ulint os_thread_count;
/* The following are approximate counters for debugging in Unix */
extern ulint os_event_count;
extern ulint os_mutex_count;
/*************************************************************
Initializes global event and OS 'slow' mutex lists. */
void
os_sync_init(void);
/*==============*/
/*************************************************************
Frees created events (not in Windows) and OS 'slow' mutexes. OS 'fast'
mutexes must be freed with sync_free() before this. */
void
os_sync_free(void);
/*==============*/
/************************************************************* /*************************************************************
Creates an event semaphore, i.e., a semaphore which may Creates an event semaphore, i.e., a semaphore which may
just have two states: signaled and nonsignaled. just have two states: signaled and nonsignaled.
......
...@@ -209,6 +209,12 @@ void ...@@ -209,6 +209,12 @@ void
srv_init(void); srv_init(void);
/*==========*/ /*==========*/
/************************************************************************* /*************************************************************************
Frees the OS fast mutex created in srv_init(). */
void
srv_free(void);
/*==========*/
/*************************************************************************
Initializes the synchronization primitives, memory system, and the thread Initializes the synchronization primitives, memory system, and the thread
local storage. */ local storage. */
......
...@@ -86,11 +86,12 @@ extern ibool srv_startup_is_before_trx_rollback_phase; ...@@ -86,11 +86,12 @@ extern ibool srv_startup_is_before_trx_rollback_phase;
extern ibool srv_is_being_shut_down; extern ibool srv_is_being_shut_down;
/* At a shutdown the value first climbs from 0 to SRV_SHUTDOWN_CLEANUP /* At a shutdown the value first climbs from 0 to SRV_SHUTDOWN_CLEANUP
and then to SRV_SHUTDOWN_LAST_PHASE */ and then to SRV_SHUTDOWN_LAST_PHASE, and so on */
extern ulint srv_shutdown_state; extern ulint srv_shutdown_state;
#define SRV_SHUTDOWN_CLEANUP 1 #define SRV_SHUTDOWN_CLEANUP 1
#define SRV_SHUTDOWN_LAST_PHASE 2 #define SRV_SHUTDOWN_LAST_PHASE 2
#define SRV_SHUTDOWN_EXIT_THREADS 3
#endif #endif
...@@ -28,15 +28,75 @@ struct os_mutex_struct{ ...@@ -28,15 +28,75 @@ struct os_mutex_struct{
do not assume that the OS mutex do not assume that the OS mutex
supports recursive locking, though supports recursive locking, though
NT seems to do that */ NT seems to do that */
UT_LIST_NODE_T(os_mutex_str_t) os_mutex_list;
/* list of all 'slow' OS mutexes created */
}; };
/* Mutex protecting the thread count */ /* Mutex protecting the thread count and the lists of OS mutexes
os_mutex_t os_thread_count_mutex; and events */
os_mutex_t os_sync_mutex;
ibool os_sync_mutex_inited = FALSE;
/* This is incremented by 1 in os_thread_create and decremented by 1 in /* This is incremented by 1 in os_thread_create and decremented by 1 in
os_thread_exit */ os_thread_exit */
ulint os_thread_count = 0; ulint os_thread_count = 0;
/* The list of all events created (not in Windows) */
UT_LIST_BASE_NODE_T(os_event_struct_t) os_event_list;
/* The list of all OS 'slow' mutexes */
UT_LIST_BASE_NODE_T(os_mutex_str_t) os_mutex_list;
/* The following are approximate counters for debugging in Unix */
ulint os_event_count = 0;
ulint os_mutex_count = 0;
/*************************************************************
Initializes global event and OS 'slow' mutex lists. */
void
os_sync_init(void)
/*==============*/
{
UT_LIST_INIT(os_event_list);
UT_LIST_INIT(os_mutex_list);
os_sync_mutex = os_mutex_create(NULL);
os_sync_mutex_inited = TRUE;
}
/*************************************************************
Frees created events (not in Windows) and OS 'slow' mutexes. OS 'fast'
mutexes must be freed with sync_free() before this. */
void
os_sync_free(void)
/*==============*/
{
os_event_t event;
os_mutex_t mutex;
event = UT_LIST_GET_FIRST(os_event_list);
while (event) {
os_event_free(event);
event = UT_LIST_GET_FIRST(os_event_list);
}
mutex = UT_LIST_GET_FIRST(os_mutex_list);
while (mutex) {
os_mutex_free(mutex);
mutex = UT_LIST_GET_FIRST(os_mutex_list);
}
}
/************************************************************* /*************************************************************
Creates an event semaphore, i.e., a semaphore which may Creates an event semaphore, i.e., a semaphore which may
just have two states: signaled and nonsignaled. just have two states: signaled and nonsignaled.
...@@ -51,7 +111,7 @@ os_event_create( ...@@ -51,7 +111,7 @@ os_event_create(
the event is created without a name */ the event is created without a name */
{ {
#ifdef __WIN__ #ifdef __WIN__
HANDLE event; os_event_t event;
event = CreateEvent(NULL, /* No security attributes */ event = CreateEvent(NULL, /* No security attributes */
TRUE, /* Manual reset */ TRUE, /* Manual reset */
...@@ -83,6 +143,14 @@ os_event_create( ...@@ -83,6 +143,14 @@ os_event_create(
#endif #endif
event->is_set = FALSE; event->is_set = FALSE;
os_mutex_enter(os_sync_mutex);
UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
os_event_count++;
os_mutex_exit(os_sync_mutex);
return(event); return(event);
#endif #endif
} }
...@@ -100,7 +168,7 @@ os_event_create_auto( ...@@ -100,7 +168,7 @@ os_event_create_auto(
the event is created without a name */ the event is created without a name */
{ {
#ifdef __WIN__ #ifdef __WIN__
HANDLE event; os_event_t event;
event = CreateEvent(NULL, /* No security attributes */ event = CreateEvent(NULL, /* No security attributes */
FALSE, /* Auto-reset */ FALSE, /* Auto-reset */
...@@ -114,6 +182,8 @@ os_event_create_auto( ...@@ -114,6 +182,8 @@ os_event_create_auto(
UT_NOT_USED(name); UT_NOT_USED(name);
ut_a(0);
return(NULL); return(NULL);
#endif #endif
} }
...@@ -193,6 +263,14 @@ os_event_free( ...@@ -193,6 +263,14 @@ os_event_free(
os_fast_mutex_free(&(event->os_mutex)); os_fast_mutex_free(&(event->os_mutex));
ut_a(0 == pthread_cond_destroy(&(event->cond_var))); ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
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); ut_free(event);
#endif #endif
} }
...@@ -310,8 +388,7 @@ os_event_wait_multiple( ...@@ -310,8 +388,7 @@ os_event_wait_multiple(
ut_a(event_array); ut_a(event_array);
ut_a(n > 0); ut_a(n > 0);
index = WaitForMultipleObjects(n, index = WaitForMultipleObjects(n, event_array,
event_array,
FALSE, /* Wait for any 1 event */ FALSE, /* Wait for any 1 event */
INFINITE); /* Infinite wait time INFINITE); /* Infinite wait time
limit */ limit */
...@@ -360,6 +437,16 @@ os_mutex_create( ...@@ -360,6 +437,16 @@ os_mutex_create(
mutex_str->handle = mutex; mutex_str->handle = mutex;
mutex_str->count = 0; mutex_str->count = 0;
if (os_sync_mutex_inited) {
os_mutex_enter(os_sync_mutex);
}
UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
if (os_sync_mutex_inited) {
os_mutex_exit(os_sync_mutex);
}
return(mutex_str); return(mutex_str);
#else #else
os_fast_mutex_t* os_mutex; os_fast_mutex_t* os_mutex;
...@@ -376,6 +463,16 @@ os_mutex_create( ...@@ -376,6 +463,16 @@ os_mutex_create(
mutex_str->handle = os_mutex; mutex_str->handle = os_mutex;
mutex_str->count = 0; mutex_str->count = 0;
if (os_sync_mutex_inited) {
os_mutex_enter(os_sync_mutex);
}
UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
if (os_sync_mutex_inited) {
os_mutex_exit(os_sync_mutex);
}
return(mutex_str); return(mutex_str);
#endif #endif
} }
...@@ -447,9 +544,22 @@ os_mutex_free( ...@@ -447,9 +544,22 @@ os_mutex_free(
#ifdef __WIN__ #ifdef __WIN__
ut_a(mutex); ut_a(mutex);
os_mutex_enter(os_sync_mutex);
UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
os_mutex_exit(os_sync_mutex);
ut_a(CloseHandle(mutex->handle)); ut_a(CloseHandle(mutex->handle));
ut_free(mutex); ut_free(mutex);
#else #else
os_mutex_enter(os_sync_mutex);
UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
os_mutex_exit(os_sync_mutex);
os_fast_mutex_free(mutex->handle); os_fast_mutex_free(mutex->handle);
ut_free(mutex->handle); ut_free(mutex->handle);
ut_free(mutex); ut_free(mutex);
...@@ -474,6 +584,7 @@ os_fast_mutex_init( ...@@ -474,6 +584,7 @@ os_fast_mutex_init(
#else #else
ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST)); ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST));
#endif #endif
os_mutex_count++;
#endif #endif
} }
...@@ -521,5 +632,6 @@ os_fast_mutex_free( ...@@ -521,5 +632,6 @@ os_fast_mutex_free(
DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex); DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex);
#else #else
ut_a(0 == pthread_mutex_destroy(fast_mutex)); ut_a(0 == pthread_mutex_destroy(fast_mutex));
os_mutex_count--;
#endif #endif
} }
...@@ -101,9 +101,9 @@ os_thread_create( ...@@ -101,9 +101,9 @@ os_thread_create(
os_thread_t thread; os_thread_t thread;
ulint win_thread_id; ulint win_thread_id;
os_mutex_enter(os_thread_count_mutex); os_mutex_enter(os_sync_mutex);
os_thread_count++; os_thread_count++;
os_mutex_exit(os_thread_count_mutex); os_mutex_exit(os_sync_mutex);
thread = CreateThread(NULL, /* no security attributes */ thread = CreateThread(NULL, /* no security attributes */
0, /* default size stack */ 0, /* default size stack */
...@@ -147,9 +147,9 @@ os_thread_create( ...@@ -147,9 +147,9 @@ os_thread_create(
exit(1); exit(1);
} }
#endif #endif
os_mutex_enter(os_thread_count_mutex); os_mutex_enter(os_sync_mutex);
os_thread_count++; os_thread_count++;
os_mutex_exit(os_thread_count_mutex); os_mutex_exit(os_sync_mutex);
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10) #if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
ret = pthread_create(&pthread, pthread_attr_default, start_f, arg); ret = pthread_create(&pthread, pthread_attr_default, start_f, arg);
...@@ -185,9 +185,9 @@ os_thread_exit( ...@@ -185,9 +185,9 @@ os_thread_exit(
void* exit_value) /* in: exit value; in Windows this void* void* exit_value) /* in: exit value; in Windows this void*
is cast as a DWORD */ is cast as a DWORD */
{ {
os_mutex_enter(os_thread_count_mutex); os_mutex_enter(os_sync_mutex);
os_thread_count--; os_thread_count--;
os_mutex_exit(os_thread_count_mutex); os_mutex_exit(os_sync_mutex);
#ifdef __WIN__ #ifdef __WIN__
ExitThread((DWORD)exit_value); ExitThread((DWORD)exit_value);
......
...@@ -1695,78 +1695,31 @@ srv_init(void) ...@@ -1695,78 +1695,31 @@ srv_init(void)
} }
/************************************************************************* /*************************************************************************
Initializes the synchronization primitives, memory system, and the thread Frees the OS fast mutex created in srv_init(). */
local storage. */
void void
srv_general_init(void) srv_free(void)
/*==================*/ /*==========*/
{ {
os_thread_count_mutex = os_mutex_create(NULL); os_fast_mutex_free(&srv_conc_mutex);
sync_init();
mem_init(srv_mem_pool_size);
thr_local_init();
} }
#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
/* NetWare requires some cleanup of mutexes */
/************************************************************************* /*************************************************************************
Deinitializes the synchronization primitives, memory system, and the thread Initializes the synchronization primitives, memory system, and the thread
local storage. */ local storage. */
void void
srv_general_free(void) srv_general_init(void)
/*==================*/ /*==================*/
{ {
sync_close(); os_sync_init();
sync_init();
os_mutex_free(os_thread_count_mutex); mem_init(srv_mem_pool_size);
thr_local_init();
} }
#endif /* __NETWARE__ */
/*======================= InnoDB Server FIFO queue =======================*/ /*======================= InnoDB Server FIFO queue =======================*/
#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
/* NetWare requires some cleanup of mutexes */
/*************************************************************************
Deinitializes the server. */
void
srv_free(void)
/*==========*/
{
srv_conc_slot_t* conc_slot;
srv_slot_t* slot;
ulint i;
for (i = 0; i < OS_THREAD_MAX_N; i++)
{
slot = srv_table_get_nth_slot(i);
os_event_free(slot->event);
}
/* TODO: free(srv_sys->threads); */
for (i = 0; i < OS_THREAD_MAX_N; i++)
{
slot = srv_mysql_table + i;
os_event_free(slot->event);
}
/* TODO: free(srv_mysql_table); */
for (i = 0; i < OS_THREAD_MAX_N; i++)
{
conc_slot = srv_conc_slots + i;
os_event_free(conc_slot->event);
}
}
#endif /* __NETWARE__ */
/************************************************************************* /*************************************************************************
Puts an OS thread to wait if there are too many concurrent threads Puts an OS thread to wait if there are too many concurrent threads
......
...@@ -1442,9 +1442,7 @@ innobase_start_or_create_for_mysql(void) ...@@ -1442,9 +1442,7 @@ innobase_start_or_create_for_mysql(void)
os_fast_mutex_unlock(&srv_os_test_mutex); os_fast_mutex_unlock(&srv_os_test_mutex);
#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY) os_fast_mutex_free(&srv_os_test_mutex);
os_fast_mutex_free(&srv_os_test_mutex); /* all platforms? */
#endif /* __NETWARE__ */
if (srv_print_verbose_log) { if (srv_print_verbose_log) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
...@@ -1484,7 +1482,7 @@ innobase_shutdown_for_mysql(void) ...@@ -1484,7 +1482,7 @@ innobase_shutdown_for_mysql(void)
return(DB_SUCCESS); return(DB_SUCCESS);
} }
/* Flush buffer pool to disk, write the current lsn to /* 1. Flush buffer pool to disk, write the current lsn to
the tablespace header(s), and copy all log data to archive */ the tablespace header(s), and copy all log data to archive */
logs_empty_and_mark_files_at_shutdown(); logs_empty_and_mark_files_at_shutdown();
...@@ -1496,7 +1494,7 @@ innobase_shutdown_for_mysql(void) ...@@ -1496,7 +1494,7 @@ innobase_shutdown_for_mysql(void)
srv_conc_n_threads); srv_conc_n_threads);
} }
/* Now we will exit all threads InnoDB created */ /* 2. Make all threads created by InnoDB to exit */
srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS; srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS;
...@@ -1521,7 +1519,7 @@ innobase_shutdown_for_mysql(void) ...@@ -1521,7 +1519,7 @@ innobase_shutdown_for_mysql(void)
os_aio_wake_all_threads_at_shutdown(); os_aio_wake_all_threads_at_shutdown();
os_mutex_enter(os_thread_count_mutex); os_mutex_enter(os_sync_mutex);
if (os_thread_count == 0) { if (os_thread_count == 0) {
/* All the threads have exited or are just exiting; /* All the threads have exited or are just exiting;
...@@ -1530,14 +1528,14 @@ innobase_shutdown_for_mysql(void) ...@@ -1530,14 +1528,14 @@ innobase_shutdown_for_mysql(void)
they have exited? Now we just sleep 0.1 seconds and they have exited? Now we just sleep 0.1 seconds and
hope that is enough! */ hope that is enough! */
os_mutex_exit(os_thread_count_mutex); os_mutex_exit(os_sync_mutex);
os_thread_sleep(100000); os_thread_sleep(100000);
break; break;
} }
os_mutex_exit(os_thread_count_mutex); os_mutex_exit(os_sync_mutex);
os_thread_sleep(100000); os_thread_sleep(100000);
} }
...@@ -1548,19 +1546,21 @@ innobase_shutdown_for_mysql(void) ...@@ -1548,19 +1546,21 @@ innobase_shutdown_for_mysql(void)
os_thread_count); os_thread_count);
} }
#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY) /* 3. Free all InnoDB's own mutexes */
sync_close();
/* 4. Free all OS synchronization primitives (in Windows currently
events are not freed) */
/* TODO: Where should this be called? */
srv_free(); srv_free();
os_sync_free();
/* TODO: Where should this be called? */ /* 5. Free all allocated memory (and the os_fast_mutex created in
srv_general_free(); ut0mem.c */
#endif
#if defined(NOT_WORKING_YET) || defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
/* NetWare requires this free */
ut_free_all_mem(); ut_free_all_mem();
#endif
if (srv_print_verbose_log) { if (srv_print_verbose_log) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Shutdown completed\n"); fprintf(stderr, " InnoDB: Shutdown completed\n");
......
...@@ -235,8 +235,7 @@ mutex_create_func( ...@@ -235,8 +235,7 @@ mutex_create_func(
mutex->cline = cline; mutex->cline = cline;
/* Check that lock_word is aligned; this is important on Intel */ /* Check that lock_word is aligned; this is important on Intel */
ut_ad(((ulint)(&(mutex->lock_word))) % 4 == 0);
ut_a(((ulint)(&(mutex->lock_word))) % 4 == 0);
/* NOTE! The very first mutexes are not put to the mutex list */ /* NOTE! The very first mutexes are not put to the mutex list */
...@@ -266,11 +265,14 @@ mutex_free( ...@@ -266,11 +265,14 @@ mutex_free(
ut_a(mutex_get_lock_word(mutex) == 0); ut_a(mutex_get_lock_word(mutex) == 0);
ut_a(mutex_get_waiters(mutex) == 0); ut_a(mutex_get_waiters(mutex) == 0);
if (mutex != &mutex_list_mutex && mutex != &sync_thread_mutex) {
mutex_enter(&mutex_list_mutex); mutex_enter(&mutex_list_mutex);
UT_LIST_REMOVE(list, mutex_list, mutex); UT_LIST_REMOVE(list, mutex_list, mutex);
mutex_exit(&mutex_list_mutex); mutex_exit(&mutex_list_mutex);
}
#if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER) #if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER)
os_fast_mutex_free(&(mutex->os_fast_mutex)); os_fast_mutex_free(&(mutex->os_fast_mutex));
...@@ -1230,13 +1232,26 @@ sync_init(void) ...@@ -1230,13 +1232,26 @@ sync_init(void)
} }
/********************************************************************** /**********************************************************************
Frees the resources in synchronization data structures. */ Frees the resources in InnoDB's own synchronization data structures. Use
os_sync_free() after calling this. */
void void
sync_close(void) sync_close(void)
/*===========*/ /*===========*/
{ {
mutex_t* mutex;
sync_array_free(sync_primary_wait_array); sync_array_free(sync_primary_wait_array);
mutex = UT_LIST_GET_FIRST(mutex_list);
while (mutex) {
mutex_free(mutex);
mutex = UT_LIST_GET_FIRST(mutex_list);
}
mutex_free(&mutex_list_mutex);
mutex_free(&sync_thread_mutex);
} }
/*********************************************************************** /***********************************************************************
......
...@@ -190,6 +190,8 @@ ut_free_all_mem(void) ...@@ -190,6 +190,8 @@ ut_free_all_mem(void)
os_fast_mutex_unlock(&ut_list_mutex); os_fast_mutex_unlock(&ut_list_mutex);
ut_a(ut_total_allocated_memory == 0); ut_a(ut_total_allocated_memory == 0);
os_fast_mutex_free(&ut_list_mutex);
} }
/************************************************************************** /**************************************************************************
......
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