From 42671d18aed8d98b445a1abea8de56c0a2613b7c Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sat, 31 May 2003 03:12:03 +0300 Subject: Many files: Free all OS sync primitives and allocated memory in InnoDB shutdown --- innobase/include/os0sync.h | 36 +++++++++--- innobase/include/srv0srv.h | 6 ++ innobase/include/srv0start.h | 7 ++- innobase/os/os0sync.c | 128 ++++++++++++++++++++++++++++++++++++++++--- innobase/os/os0thread.c | 12 ++-- innobase/srv/srv0srv.c | 69 ++++------------------- innobase/srv/srv0start.c | 32 +++++------ innobase/sync/sync0sync.c | 27 +++++++-- innobase/ut/ut0mem.c | 2 + 9 files changed, 213 insertions(+), 106 deletions(-) diff --git a/innobase/include/os0sync.h b/innobase/include/os0sync.h index d52444d02ec..3096c9256ed 100644 --- a/innobase/include/os0sync.h +++ b/innobase/include/os0sync.h @@ -10,15 +10,16 @@ Created 9/6/1995 Heikki Tuuri #define os0sync_h #include "univ.i" +#include "ut0lst.h" #ifdef __WIN__ - #define os_fast_mutex_t CRITICAL_SECTION -typedef void* os_event_t; - +typedef HANDLE os_event_t; #else - 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 { os_fast_mutex_t os_mutex; /* this mutex protects the next fields */ @@ -26,9 +27,9 @@ struct os_event_struct { not reserved */ pthread_cond_t cond_var; /* condition variable is used in 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 typedef struct os_mutex_struct os_mutex_str_t; @@ -38,13 +39,30 @@ typedef os_mutex_str_t* os_mutex_t; #define OS_SYNC_TIME_EXCEEDED 1 -/* Mutex protecting the thread count */ -extern os_mutex_t os_thread_count_mutex; +/* Mutex protecting the thread count and event and OS 'slow' mutex lists */ +extern os_mutex_t os_sync_mutex; /* This is incremented by 1 in os_thread_create and decremented by 1 in 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 just have two states: signaled and nonsignaled. diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index 8355496762c..24e692dedab 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -209,6 +209,12 @@ 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 local storage. */ diff --git a/innobase/include/srv0start.h b/innobase/include/srv0start.h index aec3ebfeea9..8d2c3fa12c5 100644 --- a/innobase/include/srv0start.h +++ b/innobase/include/srv0start.h @@ -86,11 +86,12 @@ extern ibool srv_startup_is_before_trx_rollback_phase; extern ibool srv_is_being_shut_down; /* 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; -#define SRV_SHUTDOWN_CLEANUP 1 -#define SRV_SHUTDOWN_LAST_PHASE 2 +#define SRV_SHUTDOWN_CLEANUP 1 +#define SRV_SHUTDOWN_LAST_PHASE 2 +#define SRV_SHUTDOWN_EXIT_THREADS 3 #endif diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c index abcfa254710..ce9f21ec9a1 100644 --- a/innobase/os/os0sync.c +++ b/innobase/os/os0sync.c @@ -28,14 +28,74 @@ struct os_mutex_struct{ do not assume that the OS mutex supports recursive locking, though 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 */ -os_mutex_t os_thread_count_mutex; +/* Mutex protecting the thread count and the lists of OS mutexes +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 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 @@ -51,8 +111,8 @@ os_event_create( the event is created without a name */ { #ifdef __WIN__ - HANDLE event; - + os_event_t event; + event = CreateEvent(NULL, /* No security attributes */ TRUE, /* Manual reset */ FALSE, /* Initial state nonsignaled */ @@ -83,6 +143,14 @@ os_event_create( #endif 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); #endif } @@ -100,7 +168,7 @@ os_event_create_auto( the event is created without a name */ { #ifdef __WIN__ - HANDLE event; + os_event_t event; event = CreateEvent(NULL, /* No security attributes */ FALSE, /* Auto-reset */ @@ -114,6 +182,8 @@ os_event_create_auto( UT_NOT_USED(name); + ut_a(0); + return(NULL); #endif } @@ -193,6 +263,14 @@ os_event_free( os_fast_mutex_free(&(event->os_mutex)); 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); #endif } @@ -310,8 +388,7 @@ os_event_wait_multiple( ut_a(event_array); ut_a(n > 0); - index = WaitForMultipleObjects(n, - event_array, + index = WaitForMultipleObjects(n, event_array, FALSE, /* Wait for any 1 event */ INFINITE); /* Infinite wait time limit */ @@ -360,6 +437,16 @@ os_mutex_create( mutex_str->handle = mutex; 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); #else os_fast_mutex_t* os_mutex; @@ -376,6 +463,16 @@ os_mutex_create( mutex_str->handle = os_mutex; 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); #endif } @@ -447,9 +544,22 @@ os_mutex_free( #ifdef __WIN__ 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_free(mutex); #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); ut_free(mutex->handle); ut_free(mutex); @@ -474,6 +584,7 @@ os_fast_mutex_init( #else ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST)); #endif + os_mutex_count++; #endif } @@ -521,5 +632,6 @@ os_fast_mutex_free( DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex); #else ut_a(0 == pthread_mutex_destroy(fast_mutex)); + os_mutex_count--; #endif } diff --git a/innobase/os/os0thread.c b/innobase/os/os0thread.c index a68f6a3b8bc..1722051a841 100644 --- a/innobase/os/os0thread.c +++ b/innobase/os/os0thread.c @@ -101,9 +101,9 @@ os_thread_create( os_thread_t thread; ulint win_thread_id; - os_mutex_enter(os_thread_count_mutex); + os_mutex_enter(os_sync_mutex); os_thread_count++; - os_mutex_exit(os_thread_count_mutex); + os_mutex_exit(os_sync_mutex); thread = CreateThread(NULL, /* no security attributes */ 0, /* default size stack */ @@ -147,9 +147,9 @@ os_thread_create( exit(1); } #endif - os_mutex_enter(os_thread_count_mutex); + os_mutex_enter(os_sync_mutex); os_thread_count++; - os_mutex_exit(os_thread_count_mutex); + os_mutex_exit(os_sync_mutex); #if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10) ret = pthread_create(&pthread, pthread_attr_default, start_f, arg); @@ -185,9 +185,9 @@ os_thread_exit( void* exit_value) /* in: exit value; in Windows this void* is cast as a DWORD */ { - os_mutex_enter(os_thread_count_mutex); + os_mutex_enter(os_sync_mutex); os_thread_count--; - os_mutex_exit(os_thread_count_mutex); + os_mutex_exit(os_sync_mutex); #ifdef __WIN__ ExitThread((DWORD)exit_value); diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index a44bc0147e4..da2966a7124 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -1693,80 +1693,33 @@ srv_init(void) ut_a(conc_slot->event); } } - + /************************************************************************* -Initializes the synchronization primitives, memory system, and the thread -local storage. */ +Frees the OS fast mutex created in srv_init(). */ void -srv_general_init(void) -/*==================*/ +srv_free(void) +/*==========*/ { - os_thread_count_mutex = os_mutex_create(NULL); - - sync_init(); - mem_init(srv_mem_pool_size); - thr_local_init(); + os_fast_mutex_free(&srv_conc_mutex); } - -#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. */ void -srv_general_free(void) +srv_general_init(void) /*==================*/ { - sync_close(); - - os_mutex_free(os_thread_count_mutex); + os_sync_init(); + sync_init(); + mem_init(srv_mem_pool_size); + thr_local_init(); } -#endif /* __NETWARE__ */ - /*======================= 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 diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index d34c18b1a25..f03355b825c 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1442,9 +1442,7 @@ innobase_start_or_create_for_mysql(void) os_fast_mutex_unlock(&srv_os_test_mutex); -#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY) - os_fast_mutex_free(&srv_os_test_mutex); /* all platforms? */ -#endif /* __NETWARE__ */ + os_fast_mutex_free(&srv_os_test_mutex); if (srv_print_verbose_log) { ut_print_timestamp(stderr); @@ -1484,7 +1482,7 @@ innobase_shutdown_for_mysql(void) 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 */ logs_empty_and_mark_files_at_shutdown(); @@ -1496,7 +1494,7 @@ innobase_shutdown_for_mysql(void) 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; @@ -1521,7 +1519,7 @@ innobase_shutdown_for_mysql(void) 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) { /* All the threads have exited or are just exiting; @@ -1530,14 +1528,14 @@ innobase_shutdown_for_mysql(void) they have exited? Now we just sleep 0.1 seconds and hope that is enough! */ - os_mutex_exit(os_thread_count_mutex); + os_mutex_exit(os_sync_mutex); os_thread_sleep(100000); break; } - os_mutex_exit(os_thread_count_mutex); + os_mutex_exit(os_sync_mutex); os_thread_sleep(100000); } @@ -1548,19 +1546,21 @@ innobase_shutdown_for_mysql(void) 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(); + os_sync_free(); - /* TODO: Where should this be called? */ - srv_general_free(); -#endif + /* 5. Free all allocated memory (and the os_fast_mutex created in + ut0mem.c */ -#if defined(NOT_WORKING_YET) || defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY) - /* NetWare requires this free */ ut_free_all_mem(); -#endif + if (srv_print_verbose_log) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Shutdown completed\n"); diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c index 20d68ba5a9f..32615ce88ac 100644 --- a/innobase/sync/sync0sync.c +++ b/innobase/sync/sync0sync.c @@ -235,8 +235,7 @@ mutex_create_func( mutex->cline = cline; /* Check that lock_word is aligned; this is important on Intel */ - - ut_a(((ulint)(&(mutex->lock_word))) % 4 == 0); + ut_ad(((ulint)(&(mutex->lock_word))) % 4 == 0); /* NOTE! The very first mutexes are not put to the mutex list */ @@ -266,11 +265,14 @@ mutex_free( ut_a(mutex_get_lock_word(mutex) == 0); ut_a(mutex_get_waiters(mutex) == 0); - mutex_enter(&mutex_list_mutex); + if (mutex != &mutex_list_mutex && mutex != &sync_thread_mutex) { - UT_LIST_REMOVE(list, mutex_list, mutex); + mutex_enter(&mutex_list_mutex); - mutex_exit(&mutex_list_mutex); + UT_LIST_REMOVE(list, mutex_list, mutex); + + mutex_exit(&mutex_list_mutex); + } #if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER) os_fast_mutex_free(&(mutex->os_fast_mutex)); @@ -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 sync_close(void) /*===========*/ { + mutex_t* mutex; + 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); } /*********************************************************************** diff --git a/innobase/ut/ut0mem.c b/innobase/ut/ut0mem.c index dbd3e7e4737..174ae4cc6bb 100644 --- a/innobase/ut/ut0mem.c +++ b/innobase/ut/ut0mem.c @@ -190,6 +190,8 @@ ut_free_all_mem(void) os_fast_mutex_unlock(&ut_list_mutex); ut_a(ut_total_allocated_memory == 0); + + os_fast_mutex_free(&ut_list_mutex); } /************************************************************************** -- cgit v1.2.1