mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
os0thread.h, os0sync.ic, os0sync.h, os0thread.c, os0sync.c, os0file.c:
Release all event semaphores at shutdown also in Windows srv0start.c, srv0srv.c: make test sometimes failed because lock timeout thread exited without decrementing the InnoDB thread counter
This commit is contained in:
@ -13,13 +13,26 @@ Created 9/6/1995 Heikki Tuuri
|
||||
#include "ut0lst.h"
|
||||
|
||||
#ifdef __WIN__
|
||||
|
||||
#define os_fast_mutex_t CRITICAL_SECTION
|
||||
typedef HANDLE os_event_t;
|
||||
|
||||
typedef HANDLE os_native_event_t;
|
||||
|
||||
typedef struct os_event_struct os_event_struct_t;
|
||||
typedef os_event_struct_t* os_event_t;
|
||||
|
||||
struct os_event_struct {
|
||||
os_native_event_t handle;
|
||||
/* Windows event */
|
||||
UT_LIST_NODE_T(os_event_struct_t) os_event_list;
|
||||
/* list of all created events */
|
||||
};
|
||||
#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 */
|
||||
@ -39,16 +52,16 @@ 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 */
|
||||
/* Mutex protecting counts and the 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;
|
||||
extern ulint os_fast_mutex_count;
|
||||
|
||||
/*************************************************************
|
||||
Initializes global event and OS 'slow' mutex lists. */
|
||||
@ -57,15 +70,14 @@ void
|
||||
os_sync_init(void);
|
||||
/*==============*/
|
||||
/*************************************************************
|
||||
Frees created events (not in Windows) and OS 'slow' mutexes. */
|
||||
Frees created events 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.
|
||||
The created event is manual reset: it must be reset
|
||||
Creates an event semaphore, i.e., a semaphore which may just have two states:
|
||||
signaled and nonsignaled. The created event is manual reset: it must be reset
|
||||
explicitly by calling sync_os_reset_event. */
|
||||
|
||||
os_event_t
|
||||
@ -74,10 +86,10 @@ os_event_create(
|
||||
/* out: the event handle */
|
||||
char* name); /* in: the name of the event, if NULL
|
||||
the event is created without a name */
|
||||
#ifdef __WIN__
|
||||
/*************************************************************
|
||||
Creates an auto-reset event semaphore, i.e., an event
|
||||
which is automatically reset when a single thread is
|
||||
released. */
|
||||
Creates an auto-reset event semaphore, i.e., an event which is automatically
|
||||
reset when a single thread is released. Works only in Windows. */
|
||||
|
||||
os_event_t
|
||||
os_event_create_auto(
|
||||
@ -85,6 +97,7 @@ os_event_create_auto(
|
||||
/* out: the event handle */
|
||||
char* name); /* in: the name of the event, if NULL
|
||||
the event is created without a name */
|
||||
#endif
|
||||
/**************************************************************
|
||||
Sets an event semaphore to the signaled state: lets waiting threads
|
||||
proceed. */
|
||||
@ -120,7 +133,7 @@ os_event_wait(
|
||||
os_event_t event); /* in: event to wait */
|
||||
/**************************************************************
|
||||
Waits for an event object until it is in the signaled state or
|
||||
a timeout is exceeded. */
|
||||
a timeout is exceeded. In Unix the timeout is always infinite. */
|
||||
|
||||
ulint
|
||||
os_event_wait_time(
|
||||
@ -131,8 +144,9 @@ os_event_wait_time(
|
||||
os_event_t event, /* in: event to wait */
|
||||
ulint time); /* in: timeout in microseconds, or
|
||||
OS_SYNC_INFINITE_TIME */
|
||||
#ifdef __WIN__
|
||||
/**************************************************************
|
||||
Waits for any event in an event array. Returns if even a single
|
||||
Waits for any event in an OS native event array. Returns if even a single
|
||||
one is signaled or becomes signaled. */
|
||||
|
||||
ulint
|
||||
@ -140,14 +154,15 @@ os_event_wait_multiple(
|
||||
/*===================*/
|
||||
/* out: index of the event
|
||||
which was signaled */
|
||||
ulint n, /* in: number of events in the
|
||||
ulint n, /* in: number of events in the
|
||||
array */
|
||||
os_event_t* event_array); /* in: pointer to an array of event
|
||||
os_native_event_t* native_event_array);
|
||||
/* in: pointer to an array of event
|
||||
handles */
|
||||
#endif
|
||||
/*************************************************************
|
||||
Creates an operating system mutex semaphore.
|
||||
Because these are slow, the mutex semaphore of the database
|
||||
itself (sync_mutex_t) should be used where possible. */
|
||||
Creates an operating system mutex semaphore. Because these are slow, the
|
||||
mutex semaphore of InnoDB itself (mutex_t) should be used where possible. */
|
||||
|
||||
os_mutex_t
|
||||
os_mutex_create(
|
||||
|
@ -44,4 +44,3 @@ os_fast_mutex_trylock(
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,9 @@ os_thread_pf(
|
||||
/********************************************************************
|
||||
Creates a new thread of execution. The execution starts from
|
||||
the function given. The start function takes a void* parameter
|
||||
and returns a ulint. */
|
||||
and returns a ulint.
|
||||
NOTE: We count the number of threads in os_thread_exit(). A created
|
||||
thread should always use that to exit and not use return() to exit. */
|
||||
|
||||
os_thread_t
|
||||
os_thread_create(
|
||||
|
@ -80,6 +80,8 @@ struct os_aio_slot_struct{
|
||||
which pending aio operation was
|
||||
completed */
|
||||
#ifdef WIN_ASYNC_IO
|
||||
os_event_t event; /* event object we need in the
|
||||
OVERLAPPED struct */
|
||||
OVERLAPPED control; /* Windows control block for the
|
||||
aio request */
|
||||
#elif defined(POSIX_ASYNC_IO)
|
||||
@ -107,11 +109,14 @@ struct os_aio_array_struct{
|
||||
ulint n_reserved;/* Number of reserved slots in the
|
||||
aio array outside the ibuf segment */
|
||||
os_aio_slot_t* slots; /* Pointer to the slots in the array */
|
||||
os_event_t* events; /* Pointer to an array of event handles
|
||||
where we copied the handles from slots,
|
||||
in the same order. This can be used in
|
||||
WaitForMultipleObjects; used only in
|
||||
#ifdef __WIN__
|
||||
os_native_event_t* native_events;
|
||||
/* Pointer to an array of OS native event
|
||||
handles where we copied the handles from
|
||||
slots, in the same order. This can be used
|
||||
in WaitForMultipleObjects; used only in
|
||||
Windows */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Array of events used in simulated aio */
|
||||
@ -295,8 +300,7 @@ 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 */
|
||||
const char* operation) /* in: type of operation */
|
||||
char* name) /* in: name of a file or NULL */
|
||||
{
|
||||
ulint err;
|
||||
|
||||
@ -338,7 +342,6 @@ 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");
|
||||
|
||||
@ -421,9 +424,7 @@ try_again:
|
||||
if (file == INVALID_HANDLE_VALUE) {
|
||||
*success = FALSE;
|
||||
|
||||
retry = os_file_handle_error(file, name,
|
||||
create_mode == OS_FILE_OPEN ?
|
||||
"open" : "create");
|
||||
retry = os_file_handle_error(file, name);
|
||||
|
||||
if (retry) {
|
||||
goto try_again;
|
||||
@ -464,10 +465,7 @@ try_again:
|
||||
if (file == -1) {
|
||||
*success = FALSE;
|
||||
|
||||
retry = os_file_handle_error(file, name,
|
||||
create_mode == OS_FILE_OPEN ?
|
||||
"open" : "create");
|
||||
|
||||
retry = os_file_handle_error(file, name);
|
||||
|
||||
if (retry) {
|
||||
goto try_again;
|
||||
@ -575,9 +573,7 @@ try_again:
|
||||
if (file == INVALID_HANDLE_VALUE) {
|
||||
*success = FALSE;
|
||||
|
||||
retry = os_file_handle_error(file, name,
|
||||
create_mode == OS_FILE_OPEN ?
|
||||
"open" : "create");
|
||||
retry = os_file_handle_error(file, name);
|
||||
|
||||
if (retry) {
|
||||
goto try_again;
|
||||
@ -624,9 +620,7 @@ try_again:
|
||||
if (file == -1) {
|
||||
*success = FALSE;
|
||||
|
||||
retry = os_file_handle_error(file, name,
|
||||
create_mode == OS_FILE_OPEN ?
|
||||
"open" : "create");
|
||||
retry = os_file_handle_error(file, name);
|
||||
|
||||
if (retry) {
|
||||
goto try_again;
|
||||
@ -660,7 +654,7 @@ os_file_close(
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
os_file_handle_error(file, NULL, "close");
|
||||
os_file_handle_error(file, NULL);
|
||||
return(FALSE);
|
||||
#else
|
||||
int ret;
|
||||
@ -668,7 +662,7 @@ os_file_close(
|
||||
ret = close(file);
|
||||
|
||||
if (ret == -1) {
|
||||
os_file_handle_error(file, NULL, "close");
|
||||
os_file_handle_error(file, NULL);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
@ -836,7 +830,7 @@ os_file_flush(
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
os_file_handle_error(file, NULL, "flush");
|
||||
os_file_handle_error(file, NULL);
|
||||
|
||||
/* It is a fatal error if a file flush does not succeed, because then
|
||||
the database can get corrupt on disk */
|
||||
@ -869,7 +863,7 @@ os_file_flush(
|
||||
fprintf(stderr,
|
||||
" InnoDB: Error: the OS said file flush did not succeed\n");
|
||||
|
||||
os_file_handle_error(file, NULL, "flush");
|
||||
os_file_handle_error(file, NULL);
|
||||
|
||||
/* It is a fatal error if a file flush does not succeed, because then
|
||||
the database can get corrupt on disk */
|
||||
@ -1110,7 +1104,7 @@ try_again:
|
||||
#ifdef __WIN__
|
||||
error_handling:
|
||||
#endif
|
||||
retry = os_file_handle_error(file, NULL, "read");
|
||||
retry = os_file_handle_error(file, NULL);
|
||||
|
||||
if (retry) {
|
||||
goto try_again;
|
||||
@ -1319,19 +1313,22 @@ os_aio_array_create(
|
||||
array->n_segments = n_segments;
|
||||
array->n_reserved = 0;
|
||||
array->slots = ut_malloc(n * sizeof(os_aio_slot_t));
|
||||
array->events = ut_malloc(n * sizeof(os_event_t));
|
||||
|
||||
#ifdef __WIN__
|
||||
array->native_events = ut_malloc(n * sizeof(os_native_event_t));
|
||||
#endif
|
||||
for (i = 0; i < n; i++) {
|
||||
slot = os_aio_array_get_nth_slot(array, i);
|
||||
|
||||
slot->pos = i;
|
||||
slot->reserved = FALSE;
|
||||
#ifdef WIN_ASYNC_IO
|
||||
slot->event = os_event_create(NULL);
|
||||
|
||||
over = &(slot->control);
|
||||
|
||||
over->hEvent = os_event_create(NULL);
|
||||
over->hEvent = slot->event->handle;
|
||||
|
||||
*((array->events) + i) = over->hEvent;
|
||||
*((array->native_events) + i) = over->hEvent;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1429,7 +1426,7 @@ os_aio_array_wake_win_aio_at_shutdown(
|
||||
|
||||
for (i = 0; i < array->n_slots; i++) {
|
||||
|
||||
os_event_set(*(array->events + i));
|
||||
os_event_set((array->slots + i)->event);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -1689,7 +1686,7 @@ loop:
|
||||
control = &(slot->control);
|
||||
control->Offset = (DWORD)offset;
|
||||
control->OffsetHigh = (DWORD)offset_high;
|
||||
os_event_reset(control->hEvent);
|
||||
os_event_reset(slot->event);
|
||||
|
||||
#elif defined(POSIX_ASYNC_IO)
|
||||
|
||||
@ -1747,7 +1744,7 @@ os_aio_array_free_slot(
|
||||
}
|
||||
|
||||
#ifdef WIN_ASYNC_IO
|
||||
os_event_reset(slot->control.hEvent);
|
||||
os_event_reset(slot->event);
|
||||
#endif
|
||||
os_mutex_exit(array->mutex);
|
||||
}
|
||||
@ -1916,7 +1913,8 @@ os_aio(
|
||||
wait in the Windows case. */
|
||||
|
||||
if (type == OS_FILE_READ) {
|
||||
return(os_file_read(file, buf, offset, offset_high, n));
|
||||
return(os_file_read(file, buf, offset,
|
||||
offset_high, n));
|
||||
}
|
||||
|
||||
ut_a(type == OS_FILE_WRITE);
|
||||
@ -1994,8 +1992,7 @@ try_again:
|
||||
#ifdef WIN_ASYNC_IO
|
||||
if (os_aio_use_native_aio) {
|
||||
if ((ret && len == n)
|
||||
|| (!ret && GetLastError() == ERROR_IO_PENDING)) {
|
||||
|
||||
|| (!ret && GetLastError() == ERROR_IO_PENDING)) {
|
||||
/* aio was queued successfully! */
|
||||
|
||||
if (mode == OS_AIO_SYNC) {
|
||||
@ -2025,7 +2022,7 @@ try_again:
|
||||
|
||||
os_aio_array_free_slot(array, slot);
|
||||
|
||||
retry = os_file_handle_error(file, name, "aio");
|
||||
retry = os_file_handle_error(file, name);
|
||||
|
||||
if (retry) {
|
||||
|
||||
@ -2091,15 +2088,15 @@ os_aio_windows_handle(
|
||||
n = array->n_slots / array->n_segments;
|
||||
|
||||
if (array == os_aio_sync_array) {
|
||||
srv_io_thread_op_info[orig_seg] = "wait Windows aio for 1 page";
|
||||
|
||||
ut_ad(pos < array->n_slots);
|
||||
os_event_wait(array->events[pos]);
|
||||
srv_io_thread_op_info[orig_seg] =
|
||||
"wait Windows aio for 1 page";
|
||||
os_event_wait(os_aio_array_get_nth_slot(array, pos)->event);
|
||||
i = pos;
|
||||
} else {
|
||||
srv_io_thread_op_info[orig_seg] =
|
||||
"wait Windows aio";
|
||||
i = os_event_wait_multiple(n, (array->events) + segment * n);
|
||||
i = os_event_wait_multiple(n,
|
||||
(array->native_events) + segment * n);
|
||||
}
|
||||
|
||||
os_mutex_enter(array->mutex);
|
||||
@ -2124,7 +2121,7 @@ os_aio_windows_handle(
|
||||
ut_a(TRUE == os_file_flush(slot->file));
|
||||
}
|
||||
} else {
|
||||
os_file_handle_error(slot->file, slot->name, "aio");
|
||||
os_file_handle_error(slot->file, slot->name);
|
||||
|
||||
ret_val = FALSE;
|
||||
}
|
||||
|
@ -32,24 +32,23 @@ struct os_mutex_struct{
|
||||
/* list of all 'slow' OS mutexes created */
|
||||
};
|
||||
|
||||
/* Mutex protecting the thread count and the lists of OS mutexes
|
||||
and events */
|
||||
/* Mutex protecting counts 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) */
|
||||
/* The list of all events created */
|
||||
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;
|
||||
ulint os_event_count = 0;
|
||||
ulint os_mutex_count = 0;
|
||||
ulint os_fast_mutex_count = 0;
|
||||
|
||||
|
||||
/*************************************************************
|
||||
@ -68,7 +67,7 @@ os_sync_init(void)
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
Frees created events (not in Windows) and OS 'slow' mutexes. */
|
||||
Frees created events and OS 'slow' mutexes. */
|
||||
|
||||
void
|
||||
os_sync_free(void)
|
||||
@ -97,10 +96,9 @@ os_sync_free(void)
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
Creates an event semaphore, i.e., a semaphore which may
|
||||
just have two states: signaled and nonsignaled.
|
||||
The created event is manual reset: it must be reset
|
||||
explicitly by calling sync_os_reset_event. */
|
||||
Creates an event semaphore, i.e., a semaphore which may just have two
|
||||
states: signaled and nonsignaled. The created event is manual reset: it
|
||||
must be reset explicitly by calling sync_os_reset_event. */
|
||||
|
||||
os_event_t
|
||||
os_event_create(
|
||||
@ -112,20 +110,18 @@ os_event_create(
|
||||
#ifdef __WIN__
|
||||
os_event_t event;
|
||||
|
||||
event = CreateEvent(NULL, /* No security attributes */
|
||||
event = ut_malloc(sizeof(struct os_event_struct));
|
||||
|
||||
event->handle = CreateEvent(NULL,/* No security attributes */
|
||||
TRUE, /* Manual reset */
|
||||
FALSE, /* Initial state nonsignaled */
|
||||
name);
|
||||
if (!event) {
|
||||
if (!event->handle) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Could not create a Windows event semaphore; Windows error %lu\n",
|
||||
(ulint)GetLastError());
|
||||
}
|
||||
|
||||
ut_a(event);
|
||||
|
||||
return(event);
|
||||
#else
|
||||
#else /* Unix */
|
||||
os_event_t event;
|
||||
|
||||
UT_NOT_USED(name);
|
||||
@ -141,7 +137,9 @@ os_event_create(
|
||||
ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
|
||||
#endif
|
||||
event->is_set = FALSE;
|
||||
#endif /* __WIN__ */
|
||||
|
||||
/* Put to the list of events */
|
||||
os_mutex_enter(os_sync_mutex);
|
||||
|
||||
UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
|
||||
@ -151,13 +149,12 @@ os_event_create(
|
||||
os_mutex_exit(os_sync_mutex);
|
||||
|
||||
return(event);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __WIN__
|
||||
/*************************************************************
|
||||
Creates an auto-reset event semaphore, i.e., an event
|
||||
which is automatically reset when a single thread is
|
||||
released. */
|
||||
Creates an auto-reset event semaphore, i.e., an event which is automatically
|
||||
reset when a single thread is released. Works only in Windows. */
|
||||
|
||||
os_event_t
|
||||
os_event_create_auto(
|
||||
@ -166,26 +163,33 @@ os_event_create_auto(
|
||||
char* name) /* in: the name of the event, if NULL
|
||||
the event is created without a name */
|
||||
{
|
||||
#ifdef __WIN__
|
||||
os_event_t event;
|
||||
|
||||
event = CreateEvent(NULL, /* No security attributes */
|
||||
event = ut_malloc(sizeof(struct os_event_struct));
|
||||
|
||||
event->handle = CreateEvent(NULL,/* No security attributes */
|
||||
FALSE, /* Auto-reset */
|
||||
FALSE, /* Initial state nonsignaled */
|
||||
name);
|
||||
ut_a(event);
|
||||
|
||||
if (!event->handle) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Could not create a Windows auto event semaphore; Windows error %lu\n",
|
||||
(ulint)GetLastError());
|
||||
}
|
||||
|
||||
/* Put to the list of events */
|
||||
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);
|
||||
#else
|
||||
/* Does nothing in Posix because we do not need this with MySQL */
|
||||
|
||||
UT_NOT_USED(name);
|
||||
|
||||
ut_a(0);
|
||||
|
||||
return(NULL);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/**************************************************************
|
||||
Sets an event semaphore to the signaled state: lets waiting threads
|
||||
@ -198,7 +202,7 @@ os_event_set(
|
||||
{
|
||||
#ifdef __WIN__
|
||||
ut_a(event);
|
||||
ut_a(SetEvent(event));
|
||||
ut_a(SetEvent(event->handle));
|
||||
#else
|
||||
ut_a(event);
|
||||
|
||||
@ -227,7 +231,7 @@ os_event_reset(
|
||||
#ifdef __WIN__
|
||||
ut_a(event);
|
||||
|
||||
ut_a(ResetEvent(event));
|
||||
ut_a(ResetEvent(event->handle));
|
||||
#else
|
||||
ut_a(event);
|
||||
|
||||
@ -255,12 +259,14 @@ os_event_free(
|
||||
#ifdef __WIN__
|
||||
ut_a(event);
|
||||
|
||||
ut_a(CloseHandle(event));
|
||||
ut_a(CloseHandle(event->handle));
|
||||
#else
|
||||
ut_a(event);
|
||||
|
||||
os_fast_mutex_free(&(event->os_mutex));
|
||||
ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
|
||||
#endif
|
||||
/* Remove from the list of events */
|
||||
|
||||
os_mutex_enter(os_sync_mutex);
|
||||
|
||||
@ -271,7 +277,6 @@ os_event_free(
|
||||
os_mutex_exit(os_sync_mutex);
|
||||
|
||||
ut_free(event);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
@ -291,7 +296,7 @@ os_event_wait(
|
||||
ut_a(event);
|
||||
|
||||
/* Specify an infinite time limit for waiting */
|
||||
err = WaitForSingleObject(event, INFINITE);
|
||||
err = WaitForSingleObject(event->handle, INFINITE);
|
||||
|
||||
ut_a(err == WAIT_OBJECT_0);
|
||||
|
||||
@ -324,7 +329,7 @@ loop:
|
||||
|
||||
/**************************************************************
|
||||
Waits for an event object until it is in the signaled state or
|
||||
a timeout is exceeded. */
|
||||
a timeout is exceeded. In Unix the timeout is always infinite. */
|
||||
|
||||
ulint
|
||||
os_event_wait_time(
|
||||
@ -341,9 +346,9 @@ os_event_wait_time(
|
||||
ut_a(event);
|
||||
|
||||
if (time != OS_SYNC_INFINITE_TIME) {
|
||||
err = WaitForSingleObject(event, time / 1000);
|
||||
err = WaitForSingleObject(event->handle, time / 1000);
|
||||
} else {
|
||||
err = WaitForSingleObject(event, INFINITE);
|
||||
err = WaitForSingleObject(event->handle, INFINITE);
|
||||
}
|
||||
|
||||
if (err == WAIT_OBJECT_0) {
|
||||
@ -367,8 +372,9 @@ os_event_wait_time(
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __WIN__
|
||||
/**************************************************************
|
||||
Waits for any event in an event array. Returns if even a single
|
||||
Waits for any event in an OS native event array. Returns if even a single
|
||||
one is signaled or becomes signaled. */
|
||||
|
||||
ulint
|
||||
@ -376,18 +382,18 @@ os_event_wait_multiple(
|
||||
/*===================*/
|
||||
/* out: index of the event
|
||||
which was signaled */
|
||||
ulint n, /* in: number of events in the
|
||||
ulint n, /* in: number of events in the
|
||||
array */
|
||||
os_event_t* event_array) /* in: pointer to an array of event
|
||||
os_native_event_t* native_event_array)
|
||||
/* in: pointer to an array of event
|
||||
handles */
|
||||
{
|
||||
#ifdef __WIN__
|
||||
DWORD index;
|
||||
|
||||
ut_a(event_array);
|
||||
ut_a(native_event_array);
|
||||
ut_a(n > 0);
|
||||
|
||||
index = WaitForMultipleObjects(n, event_array,
|
||||
index = WaitForMultipleObjects(n, native_event_array,
|
||||
FALSE, /* Wait for any 1 event */
|
||||
INFINITE); /* Infinite wait time
|
||||
limit */
|
||||
@ -399,21 +405,12 @@ os_event_wait_multiple(
|
||||
}
|
||||
|
||||
return(index - WAIT_OBJECT_0);
|
||||
#else
|
||||
ut_a(n == 0);
|
||||
|
||||
/* In Posix we can only wait for a single event */
|
||||
|
||||
os_event_wait(*event_array);
|
||||
|
||||
return(0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************
|
||||
Creates an operating system mutex semaphore.
|
||||
Because these are slow, the mutex semaphore of the database
|
||||
itself (sync_mutex_t) should be used where possible. */
|
||||
Creates an operating system mutex semaphore. Because these are slow, the
|
||||
mutex semaphore of InnoDB itself (mutex_t) should be used where possible. */
|
||||
|
||||
os_mutex_t
|
||||
os_mutex_create(
|
||||
@ -430,50 +427,35 @@ os_mutex_create(
|
||||
FALSE, /* Initial state: no owner */
|
||||
name);
|
||||
ut_a(mutex);
|
||||
#else
|
||||
os_fast_mutex_t* mutex;
|
||||
os_mutex_t mutex_str;
|
||||
|
||||
UT_NOT_USED(name);
|
||||
|
||||
mutex = ut_malloc(sizeof(os_fast_mutex_t));
|
||||
|
||||
os_fast_mutex_init(mutex);
|
||||
#endif
|
||||
mutex_str = ut_malloc(sizeof(os_mutex_str_t));
|
||||
|
||||
mutex_str->handle = mutex;
|
||||
mutex_str->count = 0;
|
||||
|
||||
if (os_sync_mutex_inited) {
|
||||
/* When creating os_sync_mutex itself we cannot reserve it */
|
||||
os_mutex_enter(os_sync_mutex);
|
||||
}
|
||||
|
||||
UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
|
||||
|
||||
os_mutex_count++;
|
||||
|
||||
if (os_sync_mutex_inited) {
|
||||
os_mutex_exit(os_sync_mutex);
|
||||
}
|
||||
|
||||
return(mutex_str);
|
||||
#else
|
||||
os_fast_mutex_t* os_mutex;
|
||||
os_mutex_t mutex_str;
|
||||
|
||||
UT_NOT_USED(name);
|
||||
|
||||
os_mutex = ut_malloc(sizeof(os_fast_mutex_t));
|
||||
|
||||
os_fast_mutex_init(os_mutex);
|
||||
|
||||
mutex_str = ut_malloc(sizeof(os_mutex_str_t));
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
@ -513,21 +495,14 @@ os_mutex_exit(
|
||||
/*==========*/
|
||||
os_mutex_t mutex) /* in: mutex to release */
|
||||
{
|
||||
#ifdef __WIN__
|
||||
ut_a(mutex);
|
||||
|
||||
ut_a(mutex->count == 1);
|
||||
|
||||
(mutex->count)--;
|
||||
|
||||
#ifdef __WIN__
|
||||
ut_a(ReleaseMutex(mutex->handle));
|
||||
#else
|
||||
ut_a(mutex);
|
||||
|
||||
ut_a(mutex->count == 1);
|
||||
|
||||
(mutex->count)--;
|
||||
|
||||
os_fast_mutex_unlock(mutex->handle);
|
||||
#endif
|
||||
}
|
||||
@ -540,25 +515,21 @@ os_mutex_free(
|
||||
/*==========*/
|
||||
os_mutex_t mutex) /* in: mutex to free */
|
||||
{
|
||||
#ifdef __WIN__
|
||||
ut_a(mutex);
|
||||
|
||||
os_mutex_enter(os_sync_mutex);
|
||||
|
||||
UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
|
||||
|
||||
os_mutex_count--;
|
||||
|
||||
os_mutex_exit(os_sync_mutex);
|
||||
|
||||
#ifdef __WIN__
|
||||
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);
|
||||
@ -583,8 +554,19 @@ os_fast_mutex_init(
|
||||
#else
|
||||
ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST));
|
||||
#endif
|
||||
os_mutex_count++;
|
||||
#endif
|
||||
if (os_sync_mutex_inited) {
|
||||
/* When creating os_sync_mutex itself (in Unix) we cannot
|
||||
reserve it */
|
||||
|
||||
os_mutex_enter(os_sync_mutex);
|
||||
}
|
||||
|
||||
os_fast_mutex_count++;
|
||||
|
||||
if (os_sync_mutex_inited) {
|
||||
os_mutex_exit(os_sync_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
@ -631,6 +613,10 @@ os_fast_mutex_free(
|
||||
DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex);
|
||||
#else
|
||||
ut_a(0 == pthread_mutex_destroy(fast_mutex));
|
||||
os_mutex_count--;
|
||||
#endif
|
||||
os_mutex_enter(os_sync_mutex);
|
||||
|
||||
os_fast_mutex_count--;
|
||||
|
||||
os_mutex_exit(os_sync_mutex);
|
||||
}
|
||||
|
@ -186,6 +186,10 @@ os_thread_exit(
|
||||
void* exit_value) /* in: exit value; in Windows this void*
|
||||
is cast as a DWORD */
|
||||
{
|
||||
#ifdef UNIV_DEBUG_THREAD_CREATION
|
||||
printf("A thread exits.\n");
|
||||
printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
|
||||
#endif
|
||||
os_mutex_enter(os_sync_mutex);
|
||||
os_thread_count--;
|
||||
os_mutex_exit(os_sync_mutex);
|
||||
|
@ -856,6 +856,7 @@ srv_release_max_if_no_queries(void)
|
||||
mutex_exit(&kernel_mutex);
|
||||
}
|
||||
|
||||
#ifdef notdefined
|
||||
/***********************************************************************
|
||||
Releases one utility thread if no queries are active and
|
||||
the high-water mark 2 for the utility is exceeded. */
|
||||
@ -890,7 +891,6 @@ srv_release_one_if_no_queries(void)
|
||||
mutex_exit(&kernel_mutex);
|
||||
}
|
||||
|
||||
#ifdef notdefined
|
||||
/***********************************************************************
|
||||
Decrements the utility meter by the value given and suspends the calling
|
||||
thread, which must be an utility thread of the type given, if necessary. */
|
||||
@ -1001,6 +1001,8 @@ srv_communication_init(
|
||||
ut_a(ret == 0);
|
||||
}
|
||||
|
||||
#ifdef notdefined
|
||||
|
||||
/*************************************************************************
|
||||
Implements the recovery utility. */
|
||||
static
|
||||
@ -1060,6 +1062,7 @@ srv_purge_thread(
|
||||
|
||||
return(0);
|
||||
}
|
||||
#endif /* notdefined */
|
||||
|
||||
/*************************************************************************
|
||||
Creates the utility threads. */
|
||||
@ -1090,6 +1093,7 @@ srv_create_utility_threads(void)
|
||||
ut_a(thread); */
|
||||
}
|
||||
|
||||
#ifdef notdefined
|
||||
/*************************************************************************
|
||||
Implements the communication threads. */
|
||||
static
|
||||
@ -1139,6 +1143,7 @@ srv_com_thread(
|
||||
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
Creates the communication threads. */
|
||||
@ -1159,6 +1164,7 @@ srv_create_com_threads(void)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef notdefined
|
||||
/*************************************************************************
|
||||
Implements the worker threads. */
|
||||
static
|
||||
@ -1203,6 +1209,7 @@ srv_worker_thread(
|
||||
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
Creates the worker threads. */
|
||||
@ -2456,6 +2463,10 @@ srv_lock_timeout_and_monitor_thread(
|
||||
char* buf;
|
||||
ulint i;
|
||||
|
||||
#ifdef UNIV_DEBUG_THREAD_CREATION
|
||||
printf("Lock timeout thread starts\n");
|
||||
printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
|
||||
#endif
|
||||
UT_NOT_USED(arg);
|
||||
srv_last_monitor_time = time(NULL);
|
||||
last_table_monitor_time = time(NULL);
|
||||
@ -2596,6 +2607,10 @@ loop:
|
||||
exit_func:
|
||||
srv_lock_timeout_and_monitor_active = FALSE;
|
||||
|
||||
/* We count the number of threads in os_thread_exit(). A created
|
||||
thread should always use that to exit and not use return() to exit. */
|
||||
|
||||
os_thread_exit(NULL);
|
||||
#ifndef __WIN__
|
||||
return(NULL);
|
||||
#else
|
||||
@ -2621,6 +2636,10 @@ srv_error_monitor_thread(
|
||||
ulint cnt = 0;
|
||||
|
||||
UT_NOT_USED(arg);
|
||||
#ifdef UNIV_DEBUG_THREAD_CREATION
|
||||
printf("Error monitor thread starts\n");
|
||||
printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
|
||||
#endif
|
||||
loop:
|
||||
srv_error_monitor_active = TRUE;
|
||||
|
||||
@ -2657,6 +2676,9 @@ loop:
|
||||
|
||||
srv_error_monitor_active = FALSE;
|
||||
|
||||
/* We count the number of threads in os_thread_exit(). A created
|
||||
thread should always use that to exit and not use return() to exit. */
|
||||
|
||||
os_thread_exit(NULL);
|
||||
|
||||
#ifndef __WIN__
|
||||
@ -2737,6 +2759,10 @@ srv_master_thread(
|
||||
|
||||
UT_NOT_USED(arg);
|
||||
|
||||
#ifdef UNIV_DEBUG_THREAD_CREATION
|
||||
printf("Master thread starts\n");
|
||||
printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
|
||||
#endif
|
||||
srv_main_thread_process_no = os_proc_get_number();
|
||||
srv_main_thread_id = os_thread_pf(os_thread_get_curr_id());
|
||||
|
||||
@ -2972,6 +2998,15 @@ background_loop:
|
||||
|
||||
n_tables_to_drop = row_drop_tables_for_mysql_in_background();
|
||||
|
||||
if (n_tables_to_drop > 0) {
|
||||
/* Do not monopolize the CPU even if there are tables waiting
|
||||
in the background drop queue. (It is essentially a bug if
|
||||
MySQL tries to drop a table while there are still open handles
|
||||
to it and we had to put it to the background drop queue.) */
|
||||
|
||||
os_thread_sleep(100000);
|
||||
}
|
||||
|
||||
srv_main_thread_op_info = (char*)"purging";
|
||||
|
||||
if (srv_fast_shutdown && srv_shutdown_state > 0) {
|
||||
@ -3110,6 +3145,13 @@ suspend_thread:
|
||||
|
||||
goto loop;
|
||||
|
||||
/* We count the number of threads in os_thread_exit(). A created
|
||||
thread should always use that to exit and not use return() to exit.
|
||||
The thread actually never comes here because it is exited in an
|
||||
os_event_wait(). */
|
||||
|
||||
os_thread_exit(NULL);
|
||||
|
||||
#ifndef __WIN__
|
||||
return(NULL);
|
||||
#else
|
||||
|
@ -414,8 +414,10 @@ io_handler_thread(
|
||||
|
||||
segment = *((ulint*)arg);
|
||||
|
||||
/* printf("Io handler thread %lu starts\n", segment); */
|
||||
|
||||
#ifdef UNIV_DEBUG_THREAD_CREATION
|
||||
printf("Io handler thread %lu starts\n", segment);
|
||||
printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
|
||||
#endif
|
||||
for (i = 0;; i++) {
|
||||
fil_aio_wait(segment);
|
||||
|
||||
@ -424,6 +426,13 @@ io_handler_thread(
|
||||
mutex_exit(&ios_mutex);
|
||||
}
|
||||
|
||||
/* We count the number of threads in os_thread_exit(). A created
|
||||
thread should always use that to exit and not use return() to exit.
|
||||
The thread actually never comes here because it is exited in an
|
||||
os_event_wait(). */
|
||||
|
||||
os_thread_exit(NULL);
|
||||
|
||||
#ifndef __WIN__
|
||||
return(NULL);
|
||||
#else
|
||||
@ -1546,21 +1555,32 @@ innobase_shutdown_for_mysql(void)
|
||||
os_thread_count);
|
||||
}
|
||||
|
||||
/* 3. Free all InnoDB's own mutexes */
|
||||
/* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside
|
||||
them */
|
||||
|
||||
sync_close();
|
||||
|
||||
/* 4. Free all OS synchronization primitives (in Windows currently
|
||||
events are not freed) */
|
||||
/* 4. Free the os_conc_mutex and all os_events and os_mutexes */
|
||||
|
||||
srv_free();
|
||||
os_sync_free();
|
||||
|
||||
/* 5. Free all allocated memory (and the os_fast_mutex created in
|
||||
/* 5. Free all allocated memory and the os_fast_mutex created in
|
||||
ut0mem.c */
|
||||
|
||||
ut_free_all_mem();
|
||||
|
||||
if (os_thread_count != 0
|
||||
|| os_event_count != 0
|
||||
|| os_mutex_count != 0
|
||||
|| os_fast_mutex_count != 0) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Warning: some resources were not cleaned up in shutdown:\n"
|
||||
"InnoDB: threads %lu, events %lu, os_mutexes %lu, os_fast_mutexes %lu\n",
|
||||
os_thread_count, os_event_count, os_mutex_count,
|
||||
os_fast_mutex_count);
|
||||
}
|
||||
|
||||
if (srv_print_verbose_log) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr, " InnoDB: Shutdown completed\n");
|
||||
|
Reference in New Issue
Block a user