From 13493078e9aea37f6714b3921921aa10864c8b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 16 Feb 2017 19:40:03 +0200 Subject: MDEV-11802 innodb.innodb_bug14676111 fails The function trx_purge_stop() was calling os_event_reset(purge_sys->event) before calling rw_lock_x_lock(&purge_sys->latch). The os_event_set() call in srv_purge_coordinator_suspend() is protected by that X-latch. It would seem a good idea to consistently protect both os_event_set() and os_event_reset() calls with a common mutex or rw-lock in those cases where os_event_set() and os_event_reset() are used like condition variables, tied to changes of shared state. For each os_event_t, we try to document the mutex or rw-lock that is being used. For some events, frequent calls to os_event_set() seem to try to avoid hangs. Some events are never waited for infinitely, only timed waits, and os_event_set() is used for early termination of these waits. os_aio_simulated_put_read_threads_to_sleep(): Define as a null macro on other systems than Windows. TODO: remove this altogether and disable innodb_use_native_aio on Windows. os_aio_segment_wait_events[]: Initialize only if innodb_use_native_aio=0. --- storage/xtradb/os/os0file.cc | 60 ++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 27 deletions(-) (limited to 'storage/xtradb/os') diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc index baaac6ee321..bf957d24ea7 100644 --- a/storage/xtradb/os/os0file.cc +++ b/storage/xtradb/os/os0file.cc @@ -2,6 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Percona Inc. +Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Percona Inc.. Those modifications are @@ -209,11 +210,15 @@ struct os_aio_array_t{ os_event_t not_full; /*!< The event which is set to the signaled state when there is space in - the aio outside the ibuf segment */ + the aio outside the ibuf segment; + os_event_set() and os_event_reset() + are protected by os_aio_array_t::mutex */ os_event_t is_empty; /*!< The event which is set to the signaled state when there are no - pending i/os in this array */ + pending i/os in this array; + os_event_set() and os_event_reset() + are protected by os_aio_array_t::mutex */ ulint n_slots;/*!< Total number of slots in the aio array. This must be divisible by n_threads. */ @@ -255,8 +260,8 @@ struct os_aio_array_t{ #define OS_AIO_IO_SETUP_RETRY_ATTEMPTS 5 #endif -/** Array of events used in simulated aio */ -static os_event_t* os_aio_segment_wait_events = NULL; +/** Array of events used in simulated aio. */ +static os_event_t* os_aio_segment_wait_events; /** The aio arrays for non-ibuf i/o and ibuf i/o, as well as sync aio. These are NULL when the module has not yet been initialized. @{ */ @@ -4216,13 +4221,6 @@ os_aio_init( os_aio_validate(); - os_aio_segment_wait_events = static_cast( - ut_malloc(n_segments * sizeof *os_aio_segment_wait_events)); - - for (ulint i = 0; i < n_segments; ++i) { - os_aio_segment_wait_events[i] = os_event_create(); - } - os_last_printout = ut_time(); #ifdef _WIN32 @@ -4232,8 +4230,18 @@ os_aio_init( ut_a(completion_port && read_completion_port); #endif - return(TRUE); + if (srv_use_native_aio) { + return(TRUE); + } + + os_aio_segment_wait_events = static_cast( + ut_malloc(n_segments * sizeof *os_aio_segment_wait_events)); + for (ulint i = 0; i < n_segments; ++i) { + os_aio_segment_wait_events[i] = os_event_create(); + } + + return(TRUE); } /*********************************************************************** @@ -4261,8 +4269,10 @@ os_aio_free(void) os_aio_array_free(os_aio_read_array); - for (ulint i = 0; i < os_aio_n_segments; i++) { - os_event_free(os_aio_segment_wait_events[i]); + if (!srv_use_native_aio) { + for (ulint i = 0; i < os_aio_n_segments; i++) { + os_event_free(os_aio_segment_wait_events[i]); + } } #if !defined(HAVE_ATOMIC_BUILTINS) || UNIV_WORD_SIZE < 8 @@ -4322,22 +4332,17 @@ os_aio_wake_all_threads_at_shutdown(void) if (os_aio_log_array != 0) { os_aio_array_wake_win_aio_at_shutdown(os_aio_log_array); } - #elif defined(LINUX_NATIVE_AIO) - /* When using native AIO interface the io helper threads wait on io_getevents with a timeout value of 500ms. At each wake up these threads check the server status. No need to do anything to wake them up. */ +#endif /* !WIN_ASYNC_AIO */ if (srv_use_native_aio) { return; } - /* Fall through to simulated AIO handler wakeup if we are - not using native AIO. */ -#endif /* !WIN_ASYNC_AIO */ - /* This loop wakes up all simulated ai/o threads */ for (ulint i = 0; i < os_aio_n_segments; i++) { @@ -4705,6 +4710,7 @@ os_aio_simulated_wake_handler_threads(void) } } +#ifdef _WIN32 /**********************************************************************//** This function can be called if one wants to post a batch of reads and prefers an i/o-handler thread to handle them all at once later. You must @@ -4712,15 +4718,14 @@ call os_aio_simulated_wake_handler_threads later to ensure the threads are not left sleeping! */ UNIV_INTERN void -os_aio_simulated_put_read_threads_to_sleep(void) -/*============================================*/ +os_aio_simulated_put_read_threads_to_sleep() { /* The idea of putting background IO threads to sleep is only for Windows when using simulated AIO. Windows XP seems to schedule background threads too eagerly to allow for coalescing during readahead requests. */ -#ifdef __WIN__ + os_aio_array_t* array; if (srv_use_native_aio) { @@ -4739,8 +4744,8 @@ readahead requests. */ os_event_reset(os_aio_segment_wait_events[i]); } } -#endif /* __WIN__ */ } +#endif /* _WIN32 */ #if defined(LINUX_NATIVE_AIO) /*******************************************************************//** @@ -5910,11 +5915,12 @@ os_aio_print( srv_io_thread_op_info[i], srv_io_thread_function[i]); -#ifndef __WIN__ - if (os_aio_segment_wait_events[i]->is_set()) { +#ifndef _WIN32 + if (!srv_use_native_aio + && os_aio_segment_wait_events[i]->is_set()) { fprintf(file, " ev set"); } -#endif /* __WIN__ */ +#endif /* _WIN32 */ fprintf(file, "\n"); } -- cgit v1.2.1