summaryrefslogtreecommitdiff
path: root/innobase/os
diff options
context:
space:
mode:
Diffstat (limited to 'innobase/os')
-rw-r--r--innobase/os/os0file.c82
-rw-r--r--innobase/os/os0sync.c148
-rw-r--r--innobase/os/os0thread.c31
3 files changed, 238 insertions, 23 deletions
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