diff options
author | unknown <monty@narttu.mysql.fi> | 2003-06-04 19:21:51 +0300 |
---|---|---|
committer | unknown <monty@narttu.mysql.fi> | 2003-06-04 19:21:51 +0300 |
commit | 13f7e49494559bba3195ccf3abdb349fbe79b6dc (patch) | |
tree | 6b8e47374bf313429416a26678bc409946f34772 /innobase | |
parent | b388eb004df7112b2ae0986457fc9d01131b71ea (diff) | |
parent | b5860aed7b1d11f2d3ac909cde1438c86af26cb5 (diff) | |
download | mariadb-git-13f7e49494559bba3195ccf3abdb349fbe79b6dc.tar.gz |
Merge with 4.0.13
BitKeeper/etc/logging_ok:
auto-union
BUILD/SETUP.sh:
Auto merged
BitKeeper/deleted/.del-internals.texi~62b6f580a41c2a43:
Auto merged
client/mysqltest.c:
Auto merged
include/config-win.h:
Auto merged
include/my_global.h:
Auto merged
include/mysql_com.h:
Auto merged
innobase/include/srv0srv.h:
Auto merged
innobase/log/log0log.c:
Auto merged
innobase/os/os0file.c:
Auto merged
innobase/srv/srv0srv.c:
Auto merged
innobase/srv/srv0start.c:
Auto merged
innobase/ut/ut0mem.c:
Auto merged
mysql-test/mysql-test-run.sh:
Auto merged
mysql-test/r/alter_table.result:
Auto merged
mysql-test/r/errors.result:
Auto merged
mysql-test/r/loaddata.result:
Auto merged
mysql-test/r/rpl_insert_id.result:
Auto merged
mysql-test/r/rpl_loaddata.result:
Auto merged
mysql-test/std_data/rpl_loaddata2.dat:
Auto merged
mysql-test/t/alter_table.test:
Auto merged
mysql-test/t/loaddata.test:
Auto merged
mysql-test/t/query_cache.test:
Auto merged
mysql-test/t/raid.test:
Auto merged
mysql-test/t/rpl_insert_id.test:
Auto merged
mysql-test/t/rpl_loaddata.test:
Auto merged
sql/field.cc:
Auto merged
sql/ha_innodb.cc:
Auto merged
sql/sql_cache.cc:
Auto merged
sql/sql_table.cc:
Auto merged
sql/sql_update.cc:
Auto merged
sql/time.cc:
Auto merged
configure.in:
No changes
libmysqld/lib_sql.cc:
No changes
Diffstat (limited to 'innobase')
-rw-r--r-- | innobase/include/os0file.h | 7 | ||||
-rw-r--r-- | innobase/include/os0sync.h | 41 | ||||
-rw-r--r-- | innobase/include/os0thread.h | 7 | ||||
-rw-r--r-- | innobase/include/srv0srv.h | 6 | ||||
-rw-r--r-- | innobase/include/srv0start.h | 7 | ||||
-rw-r--r-- | innobase/include/univ.i | 4 | ||||
-rw-r--r-- | innobase/log/log0log.c | 27 | ||||
-rw-r--r-- | innobase/os/os0file.c | 82 | ||||
-rw-r--r-- | innobase/os/os0sync.c | 148 | ||||
-rw-r--r-- | innobase/os/os0thread.c | 31 | ||||
-rw-r--r-- | innobase/row/row0ins.c | 5 | ||||
-rw-r--r-- | innobase/srv/srv0srv.c | 74 | ||||
-rw-r--r-- | innobase/srv/srv0start.c | 95 | ||||
-rw-r--r-- | innobase/sync/sync0sync.c | 27 | ||||
-rw-r--r-- | innobase/ut/ut0mem.c | 2 |
15 files changed, 430 insertions, 133 deletions
diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h index a7624a90d5e..86f27a2d3eb 100644 --- a/innobase/include/os0file.h +++ b/innobase/include/os0file.h @@ -301,6 +301,13 @@ os_aio( are ignored */ void* message2); /**************************************************************************** +Wakes up all async i/o threads so that they know to exit themselves in +shutdown. */ + +void +os_aio_wake_all_threads_at_shutdown(void); +/*=====================================*/ +/**************************************************************************** Waits until there are no pending writes in os_aio_write_array. There can be other, synchronous, pending writes. */ diff --git a/innobase/include/os0sync.h b/innobase/include/os0sync.h index b2d613c4619..bad8e6e120a 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,6 +39,29 @@ typedef os_mutex_str_t* os_mutex_t; #define OS_SYNC_TIME_EXCEEDED 1 +/* 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; + +/* 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. */ + +void +os_sync_free(void); +/*==============*/ /************************************************************* Creates an event semaphore, i.e., a semaphore which may just have two states: signaled and nonsignaled. @@ -85,7 +109,10 @@ os_event_free( /*==========*/ os_event_t event); /* in: event to free */ /************************************************************** -Waits for an event object until it is in the signaled state. */ +Waits for an event object until it is in the signaled state. If +srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the +waiting thread when the event becomes signaled (or immediately if the +event is already in the signaled state). */ void os_event_wait( diff --git a/innobase/include/os0thread.h b/innobase/include/os0thread.h index 629cfef23a8..92187f315c2 100644 --- a/innobase/include/os0thread.h +++ b/innobase/include/os0thread.h @@ -41,7 +41,6 @@ typedef os_thread_t os_thread_id_t; /* In Unix we use the thread the thread */ #endif - /* Define a function pointer type to use in a typecast */ typedef void* (*os_posix_f_t) (void*); @@ -83,12 +82,13 @@ os_thread_create( os_thread_id_t* thread_id); /* out: id of the created thread */ /********************************************************************* -A thread calling this function ends its execution. */ +Exits the current thread. */ void os_thread_exit( /*===========*/ - ulint code); /* in: exit code */ + void* exit_value); /* in: exit value; in Windows this void* + is cast as a DWORD */ /********************************************************************* Returns the thread identifier of current thread. */ @@ -144,7 +144,6 @@ ulint os_thread_get_last_error(void); /*==========================*/ - #ifndef UNIV_NONINL #include "os0thread.ic" #endif diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index 121e9c44a24..8fd0fc2dd6d 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -212,6 +212,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/include/univ.i b/innobase/include/univ.i index e29f3ec92e1..4854e5a7b78 100644 --- a/innobase/include/univ.i +++ b/innobase/include/univ.i @@ -187,7 +187,11 @@ management to ensure correct alignment for doubles etc. */ /* Another basic type we use is unsigned long integer which is intended to be equal to the word size of the machine. */ +#ifdef _WIN64 +typedef unsigned __int64 ulint; +#else typedef unsigned long int ulint; +#endif typedef long int lint; diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c index e717d897e41..6892e6fc6c1 100644 --- a/innobase/log/log0log.c +++ b/innobase/log/log0log.c @@ -375,7 +375,7 @@ log_pad_current_log_block(void) log_close(); log_release(); - ut_a((ut_dulint_get_low(lsn) % OS_FILE_LOG_BLOCK_SIZE) + ut_ad((ut_dulint_get_low(lsn) % OS_FILE_LOG_BLOCK_SIZE) == LOG_BLOCK_HDR_SIZE); } @@ -998,6 +998,8 @@ log_group_file_header_flush( { byte* buf; ulint dest_offset; + + UT_NOT_USED(type); ut_ad(mutex_own(&(log_sys->mutex))); @@ -1068,8 +1070,8 @@ log_group_write_buf( ulint i; ut_ad(mutex_own(&(log_sys->mutex))); - ut_a(len % OS_FILE_LOG_BLOCK_SIZE == 0); - ut_a(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0); + ut_ad(len % OS_FILE_LOG_BLOCK_SIZE == 0); + ut_ad(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0); if (new_data_offset == 0) { write_header = TRUE; @@ -2901,10 +2903,9 @@ logs_empty_and_mark_files_at_shutdown(void) dulint lsn; ulint arch_log_no; - if (srv_print_verbose_log) - { - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: Starting shutdown...\n"); + if (srv_print_verbose_log) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Starting shutdown...\n"); } /* Wait until the master thread and all other operations are idle: our algorithm only works if the server is idle at shutdown */ @@ -3006,15 +3007,17 @@ loop: goto loop; } + /* Make some checks that the server really is quiet */ + ut_a(buf_all_freed()); + ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn)); + fil_write_flushed_lsn_to_data_files(lsn, arch_log_no); fil_flush_file_spaces(FIL_TABLESPACE); - if (srv_print_verbose_log) - { - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: Shutdown completed\n"); - } + /* Make some checks that the server really is quiet */ + ut_a(buf_all_freed()); + ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn)); } /********************************************************** diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 53224eb59c5..9da5c6a47a5 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -295,7 +295,8 @@ os_file_handle_error( /* out: TRUE if we should retry the operation */ os_file_t file, /* in: file pointer */ - char* name) /* in: name of a file or NULL */ + char* name, /* in: name of a file or NULL */ + const char* operation) /* in: type of operation */ { ulint err; @@ -337,7 +338,8 @@ os_file_handle_error( if (name) { fprintf(stderr, "InnoDB: File name %s\n", name); } - + fprintf(stderr, "InnoDB: system call %s\n", operation); + fprintf(stderr, "InnoDB: Cannot continue operation.\n"); fflush(stderr); @@ -419,7 +421,9 @@ try_again: if (file == INVALID_HANDLE_VALUE) { *success = FALSE; - retry = os_file_handle_error(file, name); + retry = os_file_handle_error(file, name, + create_mode == OS_FILE_OPEN ? + "open" : "create"); if (retry) { goto try_again; @@ -460,7 +464,10 @@ try_again: if (file == -1) { *success = FALSE; - retry = os_file_handle_error(file, name); + retry = os_file_handle_error(file, name, + create_mode == OS_FILE_OPEN ? + "open" : "create"); + if (retry) { goto try_again; @@ -568,7 +575,9 @@ try_again: if (file == INVALID_HANDLE_VALUE) { *success = FALSE; - retry = os_file_handle_error(file, name); + retry = os_file_handle_error(file, name, + create_mode == OS_FILE_OPEN ? + "open" : "create"); if (retry) { goto try_again; @@ -615,7 +624,9 @@ try_again: if (file == -1) { *success = FALSE; - retry = os_file_handle_error(file, name); + retry = os_file_handle_error(file, name, + create_mode == OS_FILE_OPEN ? + "open" : "create"); if (retry) { goto try_again; @@ -649,7 +660,7 @@ os_file_close( return(TRUE); } - os_file_handle_error(file, NULL); + os_file_handle_error(file, NULL, "close"); return(FALSE); #else int ret; @@ -657,7 +668,7 @@ os_file_close( ret = close(file); if (ret == -1) { - os_file_handle_error(file, NULL); + os_file_handle_error(file, NULL, "close"); return(FALSE); } @@ -825,7 +836,7 @@ os_file_flush( return(TRUE); } - os_file_handle_error(file, NULL); + os_file_handle_error(file, NULL, "flush"); /* It is a fatal error if a file flush does not succeed, because then the database can get corrupt on disk */ @@ -858,7 +869,7 @@ os_file_flush( fprintf(stderr, " InnoDB: Error: the OS said file flush did not succeed\n"); - os_file_handle_error(file, NULL); + os_file_handle_error(file, NULL, "flush"); /* It is a fatal error if a file flush does not succeed, because then the database can get corrupt on disk */ @@ -1099,7 +1110,7 @@ try_again: #ifdef __WIN__ error_handling: #endif - retry = os_file_handle_error(file, NULL); + retry = os_file_handle_error(file, NULL, "read"); if (retry) { goto try_again; @@ -1295,7 +1306,6 @@ os_aio_array_create( #endif ut_a(n > 0); ut_a(n_segments > 0); - ut_a(n % n_segments == 0); array = ut_malloc(sizeof(os_aio_array_t)); @@ -1404,6 +1414,50 @@ os_aio_init( pthread_sigmask(SIG_BLOCK, &sigset, NULL); */ #endif } + +#ifdef WIN_ASYNC_IO +/**************************************************************************** +Wakes up all async i/o threads in the array in Windows async i/o at +shutdown. */ +static +void +os_aio_array_wake_win_aio_at_shutdown( +/*==================================*/ + os_aio_array_t* array) /* in: aio array */ +{ + ulint i; + + for (i = 0; i < array->n_slots; i++) { + + os_event_set(*(array->events + i)); + } +} +#endif + +/**************************************************************************** +Wakes up all async i/o threads so that they know to exit themselves in +shutdown. */ + +void +os_aio_wake_all_threads_at_shutdown(void) +/*=====================================*/ +{ + ulint i; + +#ifdef WIN_ASYNC_IO + /* This code wakes up all ai/o threads in Windows native aio */ + os_aio_array_wake_win_aio_at_shutdown(os_aio_read_array); + os_aio_array_wake_win_aio_at_shutdown(os_aio_write_array); + os_aio_array_wake_win_aio_at_shutdown(os_aio_ibuf_array); + os_aio_array_wake_win_aio_at_shutdown(os_aio_log_array); +#endif + /* This loop wakes up all simulated ai/o threads */ + + for (i = 0; i < os_aio_n_segments; i++) { + + os_event_set(os_aio_segment_wait_events[i]); + } +} /**************************************************************************** Waits until there are no pending writes in os_aio_write_array. There can @@ -1971,7 +2025,7 @@ try_again: os_aio_array_free_slot(array, slot); - retry = os_file_handle_error(file, name); + retry = os_file_handle_error(file, name, "aio"); if (retry) { @@ -2070,7 +2124,7 @@ os_aio_windows_handle( ut_a(TRUE == os_file_flush(slot->file)); } } else { - os_file_handle_error(slot->file, slot->name); + os_file_handle_error(slot->file, slot->name, "aio"); ret_val = FALSE; } diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c index 407b280f805..4f322ee82b2 100644 --- a/innobase/os/os0sync.c +++ b/innobase/os/os0sync.c @@ -17,6 +17,7 @@ Created 9/6/1995 Heikki Tuuri #endif #include "ut0mem.h" +#include "srv0start.h" /* Type definition for an operating system mutex struct */ struct os_mutex_struct{ @@ -26,9 +27,75 @@ struct os_mutex_struct{ recursively lock the mutex: we do not assume that the OS mutex 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 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; + +/* 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. */ + +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 just have two states: signaled and nonsignaled. @@ -43,8 +110,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 */ @@ -75,6 +142,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 } @@ -92,7 +167,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 */ @@ -106,6 +181,8 @@ os_event_create_auto( UT_NOT_USED(name); + ut_a(0); + return(NULL); #endif } @@ -185,12 +262,23 @@ 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 } /************************************************************** -Waits for an event object until it is in the signaled state. */ +Waits for an event object until it is in the signaled state. If +srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the +waiting thread when the event becomes signaled (or immediately if the +event is already in the signaled state). */ void os_event_wait( @@ -206,12 +294,20 @@ os_event_wait( err = WaitForSingleObject(event, INFINITE); ut_a(err == WAIT_OBJECT_0); + + if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { + os_thread_exit(NULL); + } #else os_fast_mutex_lock(&(event->os_mutex)); loop: if (event->is_set == TRUE) { os_fast_mutex_unlock(&(event->os_mutex)); + if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { + + os_thread_exit(NULL); + } /* Ok, we may return */ return; @@ -291,14 +387,17 @@ 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 */ ut_a(index >= WAIT_OBJECT_0); ut_a(index < WAIT_OBJECT_0 + n); + if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { + os_thread_exit(NULL); + } + return(index - WAIT_OBJECT_0); #else ut_a(n == 0); @@ -337,6 +436,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; @@ -353,6 +462,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 } @@ -424,9 +543,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); @@ -451,6 +583,7 @@ os_fast_mutex_init( #else ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST)); #endif + os_mutex_count++; #endif } @@ -498,5 +631,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 b0076921e43..02ea2c227a7 100644 --- a/innobase/os/os0thread.c +++ b/innobase/os/os0thread.c @@ -1,6 +1,5 @@ /****************************************************** -The interface to the operating system -process and thread control primitives +The interface to the operating system thread control primitives (c) 1995 Innobase Oy @@ -17,6 +16,7 @@ Created 9/8/1995 Heikki Tuuri #endif #include "srv0srv.h" +#include "os0sync.h" /******************************************************************* Compares two thread ids for equality. */ @@ -102,6 +102,10 @@ os_thread_create( os_thread_t thread; ulint win_thread_id; + os_mutex_enter(os_sync_mutex); + os_thread_count++; + os_mutex_exit(os_sync_mutex); + thread = CreateThread(NULL, /* no security attributes */ 0, /* default size stack */ (LPTHREAD_START_ROUTINE)start_f, @@ -144,6 +148,9 @@ os_thread_create( exit(1); } #endif + os_mutex_enter(os_sync_mutex); + os_thread_count++; + os_mutex_exit(os_sync_mutex); #if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10) ret = pthread_create(&pthread, pthread_attr_default, start_f, arg); @@ -171,6 +178,26 @@ os_thread_create( } /********************************************************************* +Exits the current thread. */ + +void +os_thread_exit( +/*===========*/ + void* exit_value) /* in: exit value; in Windows this void* + is cast as a DWORD */ +{ + os_mutex_enter(os_sync_mutex); + os_thread_count--; + os_mutex_exit(os_sync_mutex); + +#ifdef __WIN__ + ExitThread((DWORD)exit_value); +#else + pthread_exit(exit_value); +#endif +} + +/********************************************************************* Returns handle to the current thread. */ os_thread_t diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 3af9e1b752b..e96c08a715b 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -1275,6 +1275,10 @@ row_ins_unique_report_err( dtuple_t* entry, /* in: index entry to insert in the index */ dict_index_t* index) /* in: index */ { +#ifdef notdefined + /* Disable reporting to test if the slowdown of REPLACE in 4.0.13 was + caused by this! */ + char* buf = dict_unique_err_buf; /* The foreign err mutex protects also dict_unique_err_buf */ @@ -1303,6 +1307,7 @@ row_ins_unique_report_err( ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN); mutex_exit(&dict_foreign_err_mutex); +#endif } /******************************************************************* diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 7cd831fe239..9353766248d 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -1705,76 +1705,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) +/*==========*/ { - 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_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 @@ -2734,6 +2691,8 @@ loop: srv_error_monitor_active = FALSE; + os_thread_exit(NULL); + #ifndef __WIN__ return(NULL); #else @@ -3173,6 +3132,13 @@ suspend_thread: os_event_wait(event); + if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { + /* This is only extra safety, the thread should exit + already when the event wait ends */ + + os_thread_exit(NULL); + } + /* When there is user activity, InnoDB will set the event and the main thread goes back to loop: */ diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index 536aa5b67e4..9a2bf72130b 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1481,9 +1481,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); @@ -1509,6 +1507,8 @@ innobase_shutdown_for_mysql(void) /*=============================*/ /* out: DB_SUCCESS or error code */ { + ulint i; + if (!srv_was_started) { if (srv_is_being_started) { ut_print_timestamp(stderr); @@ -1521,7 +1521,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(); @@ -1533,30 +1533,77 @@ innobase_shutdown_for_mysql(void) srv_conc_n_threads); } -#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY) - /* - TODO: Fix this temporary solution - We are having a race condition occure with io_handler_thread threads. - When they yield in os_aio_simulated_handle during shutdown, this - thread was able to free the memory early. - */ - os_thread_yield(); + /* 2. Make all threads created by InnoDB to exit */ + + srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS; + + /* All threads end up waiting for certain events. Put those events + to the signaled state. Then the threads will exit themselves in + os_thread_event_wait(). */ + + for (i = 0; i < 1000; i++) { + /* NOTE: IF YOU CREATE THREADS IN INNODB, YOU MUST EXIT THEM + HERE OR EARLIER */ + + /* 1. Let the lock timeout thread exit */ + os_event_set(srv_lock_timeout_thread_event); + + /* 2. srv error monitor thread exits automatically, no need + to do anything here */ + + /* 3. We wake the master thread so that it exits */ + srv_wake_master_thread(); + + /* 4. Exit the i/o threads */ + + os_aio_wake_all_threads_at_shutdown(); + + os_mutex_enter(os_sync_mutex); + + if (os_thread_count == 0) { + /* All the threads have exited or are just exiting; + NOTE that the threads may not have completed their + exit yet. Should we use pthread_join() to make sure + they have exited? Now we just sleep 0.1 seconds and + hope that is enough! */ + + os_mutex_exit(os_sync_mutex); + + os_thread_sleep(100000); + + break; + } + + os_mutex_exit(os_sync_mutex); + + os_thread_sleep(100000); + } + + if (i == 1000) { + fprintf(stderr, +"InnoDB: Warning: %lu threads created by InnoDB had not exited at shutdown!\n", + os_thread_count); + } + + /* 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(); + + /* 5. Free all allocated memory (and the os_fast_mutex created in + ut0mem.c */ - /* TODO: Where should this be called? */ - srv_general_free(); -#endif - /* - TODO: We should exit the i/o-handler and other utility threads - before freeing all memory. Now this can potentially cause a seg - fault! - */ -#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"); + } return((int) DB_SUCCESS); } 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 23deed0fa55..2609b8f5241 100644 --- a/innobase/ut/ut0mem.c +++ b/innobase/ut/ut0mem.c @@ -225,6 +225,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); } /************************************************************************** |