Commit 0ae3a4dc authored by unknown's avatar unknown

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


innobase/srv/srv0srv.c:
  make test sometimes failed because lock timeout thread exited without decrementing the InnoDB thread counter
innobase/srv/srv0start.c:
  make test sometimes failed because lock timeout thread exited without decrementing the InnoDB thread counter
innobase/os/os0file.c:
  Release all event semaphores at shutdown also in Windows
innobase/os/os0sync.c:
  Release all event semaphores at shutdown also in Windows
innobase/os/os0thread.c:
  Release all event semaphores at shutdown also in Windows
innobase/include/os0sync.h:
  Release all event semaphores at shutdown also in Windows
innobase/include/os0sync.ic:
  Release all event semaphores at shutdown also in Windows
innobase/include/os0thread.h:
  Release all event semaphores at shutdown also in Windows
parent 3f7dfc4d
...@@ -13,13 +13,26 @@ Created 9/6/1995 Heikki Tuuri ...@@ -13,13 +13,26 @@ Created 9/6/1995 Heikki Tuuri
#include "ut0lst.h" #include "ut0lst.h"
#ifdef __WIN__ #ifdef __WIN__
#define os_fast_mutex_t CRITICAL_SECTION #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 #else
typedef pthread_mutex_t os_fast_mutex_t; typedef pthread_mutex_t os_fast_mutex_t;
typedef struct os_event_struct os_event_struct_t; typedef struct os_event_struct os_event_struct_t;
typedef os_event_struct_t* os_event_t; typedef os_event_struct_t* os_event_t;
struct os_event_struct { struct os_event_struct {
os_fast_mutex_t os_mutex; /* this mutex protects the next os_fast_mutex_t os_mutex; /* this mutex protects the next
fields */ fields */
...@@ -39,16 +52,16 @@ typedef os_mutex_str_t* os_mutex_t; ...@@ -39,16 +52,16 @@ typedef os_mutex_str_t* os_mutex_t;
#define OS_SYNC_TIME_EXCEEDED 1 #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; extern os_mutex_t os_sync_mutex;
/* This is incremented by 1 in os_thread_create and decremented by 1 in /* This is incremented by 1 in os_thread_create and decremented by 1 in
os_thread_exit */ 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_event_count;
extern ulint os_mutex_count; extern ulint os_mutex_count;
extern ulint os_fast_mutex_count;
/************************************************************* /*************************************************************
Initializes global event and OS 'slow' mutex lists. */ Initializes global event and OS 'slow' mutex lists. */
...@@ -57,15 +70,14 @@ void ...@@ -57,15 +70,14 @@ void
os_sync_init(void); os_sync_init(void);
/*==============*/ /*==============*/
/************************************************************* /*************************************************************
Frees created events (not in Windows) and OS 'slow' mutexes. */ Frees created events and OS 'slow' mutexes. */
void void
os_sync_free(void); os_sync_free(void);
/*==============*/ /*==============*/
/************************************************************* /*************************************************************
Creates an event semaphore, i.e., a semaphore which may Creates an event semaphore, i.e., a semaphore which may just have two states:
just have two states: signaled and nonsignaled. signaled and nonsignaled. The created event is manual reset: it must be reset
The created event is manual reset: it must be reset
explicitly by calling sync_os_reset_event. */ explicitly by calling sync_os_reset_event. */
os_event_t os_event_t
...@@ -74,10 +86,10 @@ os_event_create( ...@@ -74,10 +86,10 @@ os_event_create(
/* out: the event handle */ /* out: the event handle */
char* name); /* in: the name of the event, if NULL char* name); /* in: the name of the event, if NULL
the event is created without a name */ the event is created without a name */
#ifdef __WIN__
/************************************************************* /*************************************************************
Creates an auto-reset event semaphore, i.e., an event Creates an auto-reset event semaphore, i.e., an event which is automatically
which is automatically reset when a single thread is reset when a single thread is released. Works only in Windows. */
released. */
os_event_t os_event_t
os_event_create_auto( os_event_create_auto(
...@@ -85,6 +97,7 @@ os_event_create_auto( ...@@ -85,6 +97,7 @@ os_event_create_auto(
/* out: the event handle */ /* out: the event handle */
char* name); /* in: the name of the event, if NULL char* name); /* in: the name of the event, if NULL
the event is created without a name */ the event is created without a name */
#endif
/************************************************************** /**************************************************************
Sets an event semaphore to the signaled state: lets waiting threads Sets an event semaphore to the signaled state: lets waiting threads
proceed. */ proceed. */
...@@ -120,7 +133,7 @@ os_event_wait( ...@@ -120,7 +133,7 @@ os_event_wait(
os_event_t event); /* in: event to wait */ os_event_t event); /* in: event to wait */
/************************************************************** /**************************************************************
Waits for an event object until it is in the signaled state or 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 ulint
os_event_wait_time( os_event_wait_time(
...@@ -131,8 +144,9 @@ os_event_wait_time( ...@@ -131,8 +144,9 @@ os_event_wait_time(
os_event_t event, /* in: event to wait */ os_event_t event, /* in: event to wait */
ulint time); /* in: timeout in microseconds, or ulint time); /* in: timeout in microseconds, or
OS_SYNC_INFINITE_TIME */ 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. */ one is signaled or becomes signaled. */
ulint ulint
...@@ -142,12 +156,13 @@ os_event_wait_multiple( ...@@ -142,12 +156,13 @@ os_event_wait_multiple(
which was signaled */ which was signaled */
ulint n, /* in: number of events in the ulint n, /* in: number of events in the
array */ 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 */ handles */
#endif
/************************************************************* /*************************************************************
Creates an operating system mutex semaphore. Creates an operating system mutex semaphore. Because these are slow, the
Because these are slow, the mutex semaphore of the database mutex semaphore of InnoDB itself (mutex_t) should be used where possible. */
itself (sync_mutex_t) should be used where possible. */
os_mutex_t os_mutex_t
os_mutex_create( os_mutex_create(
......
...@@ -44,4 +44,3 @@ os_fast_mutex_trylock( ...@@ -44,4 +44,3 @@ os_fast_mutex_trylock(
#endif #endif
#endif #endif
} }
...@@ -65,7 +65,9 @@ os_thread_pf( ...@@ -65,7 +65,9 @@ os_thread_pf(
/******************************************************************** /********************************************************************
Creates a new thread of execution. The execution starts from Creates a new thread of execution. The execution starts from
the function given. The start function takes a void* parameter 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_t
os_thread_create( os_thread_create(
......
...@@ -80,6 +80,8 @@ struct os_aio_slot_struct{ ...@@ -80,6 +80,8 @@ struct os_aio_slot_struct{
which pending aio operation was which pending aio operation was
completed */ completed */
#ifdef WIN_ASYNC_IO #ifdef WIN_ASYNC_IO
os_event_t event; /* event object we need in the
OVERLAPPED struct */
OVERLAPPED control; /* Windows control block for the OVERLAPPED control; /* Windows control block for the
aio request */ aio request */
#elif defined(POSIX_ASYNC_IO) #elif defined(POSIX_ASYNC_IO)
...@@ -107,11 +109,14 @@ struct os_aio_array_struct{ ...@@ -107,11 +109,14 @@ struct os_aio_array_struct{
ulint n_reserved;/* Number of reserved slots in the ulint n_reserved;/* Number of reserved slots in the
aio array outside the ibuf segment */ aio array outside the ibuf segment */
os_aio_slot_t* slots; /* Pointer to the slots in the array */ os_aio_slot_t* slots; /* Pointer to the slots in the array */
os_event_t* events; /* Pointer to an array of event handles #ifdef __WIN__
where we copied the handles from slots, os_native_event_t* native_events;
in the same order. This can be used in /* Pointer to an array of OS native event
WaitForMultipleObjects; used only in handles where we copied the handles from
slots, in the same order. This can be used
in WaitForMultipleObjects; used only in
Windows */ Windows */
#endif
}; };
/* Array of events used in simulated aio */ /* Array of events used in simulated aio */
...@@ -295,8 +300,7 @@ os_file_handle_error( ...@@ -295,8 +300,7 @@ os_file_handle_error(
/* out: TRUE if we should retry the /* out: TRUE if we should retry the
operation */ operation */
os_file_t file, /* in: file pointer */ 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; ulint err;
...@@ -338,7 +342,6 @@ os_file_handle_error( ...@@ -338,7 +342,6 @@ os_file_handle_error(
if (name) { if (name) {
fprintf(stderr, "InnoDB: File name %s\n", name); fprintf(stderr, "InnoDB: File name %s\n", name);
} }
fprintf(stderr, "InnoDB: system call %s\n", operation);
fprintf(stderr, "InnoDB: Cannot continue operation.\n"); fprintf(stderr, "InnoDB: Cannot continue operation.\n");
...@@ -421,9 +424,7 @@ os_file_create_simple( ...@@ -421,9 +424,7 @@ os_file_create_simple(
if (file == INVALID_HANDLE_VALUE) { if (file == INVALID_HANDLE_VALUE) {
*success = FALSE; *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) { if (retry) {
goto try_again; goto try_again;
...@@ -464,10 +465,7 @@ os_file_create_simple( ...@@ -464,10 +465,7 @@ os_file_create_simple(
if (file == -1) { if (file == -1) {
*success = FALSE; *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) { if (retry) {
goto try_again; goto try_again;
...@@ -575,9 +573,7 @@ os_file_create( ...@@ -575,9 +573,7 @@ os_file_create(
if (file == INVALID_HANDLE_VALUE) { if (file == INVALID_HANDLE_VALUE) {
*success = FALSE; *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) { if (retry) {
goto try_again; goto try_again;
...@@ -624,9 +620,7 @@ os_file_create( ...@@ -624,9 +620,7 @@ os_file_create(
if (file == -1) { if (file == -1) {
*success = FALSE; *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) { if (retry) {
goto try_again; goto try_again;
...@@ -660,7 +654,7 @@ os_file_close( ...@@ -660,7 +654,7 @@ os_file_close(
return(TRUE); return(TRUE);
} }
os_file_handle_error(file, NULL, "close"); os_file_handle_error(file, NULL);
return(FALSE); return(FALSE);
#else #else
int ret; int ret;
...@@ -668,7 +662,7 @@ os_file_close( ...@@ -668,7 +662,7 @@ os_file_close(
ret = close(file); ret = close(file);
if (ret == -1) { if (ret == -1) {
os_file_handle_error(file, NULL, "close"); os_file_handle_error(file, NULL);
return(FALSE); return(FALSE);
} }
...@@ -836,7 +830,7 @@ os_file_flush( ...@@ -836,7 +830,7 @@ os_file_flush(
return(TRUE); 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 /* It is a fatal error if a file flush does not succeed, because then
the database can get corrupt on disk */ the database can get corrupt on disk */
...@@ -869,7 +863,7 @@ os_file_flush( ...@@ -869,7 +863,7 @@ os_file_flush(
fprintf(stderr, fprintf(stderr,
" InnoDB: Error: the OS said file flush did not succeed\n"); " 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 /* It is a fatal error if a file flush does not succeed, because then
the database can get corrupt on disk */ the database can get corrupt on disk */
...@@ -1110,7 +1104,7 @@ os_file_read( ...@@ -1110,7 +1104,7 @@ os_file_read(
#ifdef __WIN__ #ifdef __WIN__
error_handling: error_handling:
#endif #endif
retry = os_file_handle_error(file, NULL, "read"); retry = os_file_handle_error(file, NULL);
if (retry) { if (retry) {
goto try_again; goto try_again;
...@@ -1319,19 +1313,22 @@ os_aio_array_create( ...@@ -1319,19 +1313,22 @@ os_aio_array_create(
array->n_segments = n_segments; array->n_segments = n_segments;
array->n_reserved = 0; array->n_reserved = 0;
array->slots = ut_malloc(n * sizeof(os_aio_slot_t)); 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++) { for (i = 0; i < n; i++) {
slot = os_aio_array_get_nth_slot(array, i); slot = os_aio_array_get_nth_slot(array, i);
slot->pos = i; slot->pos = i;
slot->reserved = FALSE; slot->reserved = FALSE;
#ifdef WIN_ASYNC_IO #ifdef WIN_ASYNC_IO
slot->event = os_event_create(NULL);
over = &(slot->control); 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 #endif
} }
...@@ -1429,7 +1426,7 @@ os_aio_array_wake_win_aio_at_shutdown( ...@@ -1429,7 +1426,7 @@ os_aio_array_wake_win_aio_at_shutdown(
for (i = 0; i < array->n_slots; i++) { for (i = 0; i < array->n_slots; i++) {
os_event_set(*(array->events + i)); os_event_set((array->slots + i)->event);
} }
} }
#endif #endif
...@@ -1689,7 +1686,7 @@ os_aio_array_reserve_slot( ...@@ -1689,7 +1686,7 @@ os_aio_array_reserve_slot(
control = &(slot->control); control = &(slot->control);
control->Offset = (DWORD)offset; control->Offset = (DWORD)offset;
control->OffsetHigh = (DWORD)offset_high; control->OffsetHigh = (DWORD)offset_high;
os_event_reset(control->hEvent); os_event_reset(slot->event);
#elif defined(POSIX_ASYNC_IO) #elif defined(POSIX_ASYNC_IO)
...@@ -1747,7 +1744,7 @@ os_aio_array_free_slot( ...@@ -1747,7 +1744,7 @@ os_aio_array_free_slot(
} }
#ifdef WIN_ASYNC_IO #ifdef WIN_ASYNC_IO
os_event_reset(slot->control.hEvent); os_event_reset(slot->event);
#endif #endif
os_mutex_exit(array->mutex); os_mutex_exit(array->mutex);
} }
...@@ -1916,7 +1913,8 @@ os_aio( ...@@ -1916,7 +1913,8 @@ os_aio(
wait in the Windows case. */ wait in the Windows case. */
if (type == OS_FILE_READ) { 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); ut_a(type == OS_FILE_WRITE);
...@@ -1995,7 +1993,6 @@ os_aio( ...@@ -1995,7 +1993,6 @@ os_aio(
if (os_aio_use_native_aio) { if (os_aio_use_native_aio) {
if ((ret && len == n) if ((ret && len == n)
|| (!ret && GetLastError() == ERROR_IO_PENDING)) { || (!ret && GetLastError() == ERROR_IO_PENDING)) {
/* aio was queued successfully! */ /* aio was queued successfully! */
if (mode == OS_AIO_SYNC) { if (mode == OS_AIO_SYNC) {
...@@ -2025,7 +2022,7 @@ os_aio( ...@@ -2025,7 +2022,7 @@ os_aio(
os_aio_array_free_slot(array, slot); os_aio_array_free_slot(array, slot);
retry = os_file_handle_error(file, name, "aio"); retry = os_file_handle_error(file, name);
if (retry) { if (retry) {
...@@ -2091,15 +2088,15 @@ os_aio_windows_handle( ...@@ -2091,15 +2088,15 @@ os_aio_windows_handle(
n = array->n_slots / array->n_segments; n = array->n_slots / array->n_segments;
if (array == os_aio_sync_array) { if (array == os_aio_sync_array) {
srv_io_thread_op_info[orig_seg] = "wait Windows aio for 1 page"; srv_io_thread_op_info[orig_seg] =
"wait Windows aio for 1 page";
ut_ad(pos < array->n_slots); os_event_wait(os_aio_array_get_nth_slot(array, pos)->event);
os_event_wait(array->events[pos]);
i = pos; i = pos;
} else { } else {
srv_io_thread_op_info[orig_seg] = srv_io_thread_op_info[orig_seg] =
"wait Windows aio"; "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); os_mutex_enter(array->mutex);
...@@ -2124,7 +2121,7 @@ os_aio_windows_handle( ...@@ -2124,7 +2121,7 @@ os_aio_windows_handle(
ut_a(TRUE == os_file_flush(slot->file)); ut_a(TRUE == os_file_flush(slot->file));
} }
} else { } else {
os_file_handle_error(slot->file, slot->name, "aio"); os_file_handle_error(slot->file, slot->name);
ret_val = FALSE; ret_val = FALSE;
} }
......
This diff is collapsed.
...@@ -186,6 +186,10 @@ os_thread_exit( ...@@ -186,6 +186,10 @@ os_thread_exit(
void* exit_value) /* in: exit value; in Windows this void* void* exit_value) /* in: exit value; in Windows this void*
is cast as a DWORD */ 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_mutex_enter(os_sync_mutex);
os_thread_count--; os_thread_count--;
os_mutex_exit(os_sync_mutex); os_mutex_exit(os_sync_mutex);
......
...@@ -856,6 +856,7 @@ srv_release_max_if_no_queries(void) ...@@ -856,6 +856,7 @@ srv_release_max_if_no_queries(void)
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
} }
#ifdef notdefined
/*********************************************************************** /***********************************************************************
Releases one utility thread if no queries are active and Releases one utility thread if no queries are active and
the high-water mark 2 for the utility is exceeded. */ the high-water mark 2 for the utility is exceeded. */
...@@ -890,7 +891,6 @@ srv_release_one_if_no_queries(void) ...@@ -890,7 +891,6 @@ srv_release_one_if_no_queries(void)
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
} }
#ifdef notdefined
/*********************************************************************** /***********************************************************************
Decrements the utility meter by the value given and suspends the calling 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. */ thread, which must be an utility thread of the type given, if necessary. */
...@@ -1001,6 +1001,8 @@ srv_communication_init( ...@@ -1001,6 +1001,8 @@ srv_communication_init(
ut_a(ret == 0); ut_a(ret == 0);
} }
#ifdef notdefined
/************************************************************************* /*************************************************************************
Implements the recovery utility. */ Implements the recovery utility. */
static static
...@@ -1060,6 +1062,7 @@ srv_purge_thread( ...@@ -1060,6 +1062,7 @@ srv_purge_thread(
return(0); return(0);
} }
#endif /* notdefined */
/************************************************************************* /*************************************************************************
Creates the utility threads. */ Creates the utility threads. */
...@@ -1090,6 +1093,7 @@ srv_create_utility_threads(void) ...@@ -1090,6 +1093,7 @@ srv_create_utility_threads(void)
ut_a(thread); */ ut_a(thread); */
} }
#ifdef notdefined
/************************************************************************* /*************************************************************************
Implements the communication threads. */ Implements the communication threads. */
static static
...@@ -1139,6 +1143,7 @@ srv_com_thread( ...@@ -1139,6 +1143,7 @@ srv_com_thread(
return(0); return(0);
} }
#endif
/************************************************************************* /*************************************************************************
Creates the communication threads. */ Creates the communication threads. */
...@@ -1159,6 +1164,7 @@ srv_create_com_threads(void) ...@@ -1159,6 +1164,7 @@ srv_create_com_threads(void)
} }
} }
#ifdef notdefined
/************************************************************************* /*************************************************************************
Implements the worker threads. */ Implements the worker threads. */
static static
...@@ -1203,6 +1209,7 @@ srv_worker_thread( ...@@ -1203,6 +1209,7 @@ srv_worker_thread(
return(0); return(0);
} }
#endif
/************************************************************************* /*************************************************************************
Creates the worker threads. */ Creates the worker threads. */
...@@ -2456,6 +2463,10 @@ srv_lock_timeout_and_monitor_thread( ...@@ -2456,6 +2463,10 @@ srv_lock_timeout_and_monitor_thread(
char* buf; char* buf;
ulint i; 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); UT_NOT_USED(arg);
srv_last_monitor_time = time(NULL); srv_last_monitor_time = time(NULL);
last_table_monitor_time = time(NULL); last_table_monitor_time = time(NULL);
...@@ -2596,6 +2607,10 @@ srv_lock_timeout_and_monitor_thread( ...@@ -2596,6 +2607,10 @@ srv_lock_timeout_and_monitor_thread(
exit_func: exit_func:
srv_lock_timeout_and_monitor_active = FALSE; 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__ #ifndef __WIN__
return(NULL); return(NULL);
#else #else
...@@ -2621,6 +2636,10 @@ srv_error_monitor_thread( ...@@ -2621,6 +2636,10 @@ srv_error_monitor_thread(
ulint cnt = 0; ulint cnt = 0;
UT_NOT_USED(arg); 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: loop:
srv_error_monitor_active = TRUE; srv_error_monitor_active = TRUE;
...@@ -2657,6 +2676,9 @@ srv_error_monitor_thread( ...@@ -2657,6 +2676,9 @@ srv_error_monitor_thread(
srv_error_monitor_active = FALSE; 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); os_thread_exit(NULL);
#ifndef __WIN__ #ifndef __WIN__
...@@ -2737,6 +2759,10 @@ srv_master_thread( ...@@ -2737,6 +2759,10 @@ srv_master_thread(
UT_NOT_USED(arg); 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_process_no = os_proc_get_number();
srv_main_thread_id = os_thread_pf(os_thread_get_curr_id()); srv_main_thread_id = os_thread_pf(os_thread_get_curr_id());
...@@ -2972,6 +2998,15 @@ srv_master_thread( ...@@ -2972,6 +2998,15 @@ srv_master_thread(
n_tables_to_drop = row_drop_tables_for_mysql_in_background(); 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"; srv_main_thread_op_info = (char*)"purging";
if (srv_fast_shutdown && srv_shutdown_state > 0) { if (srv_fast_shutdown && srv_shutdown_state > 0) {
...@@ -3110,6 +3145,13 @@ srv_master_thread( ...@@ -3110,6 +3145,13 @@ srv_master_thread(
goto loop; 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__ #ifndef __WIN__
return(NULL); return(NULL);
#else #else
......
...@@ -414,8 +414,10 @@ io_handler_thread( ...@@ -414,8 +414,10 @@ io_handler_thread(
segment = *((ulint*)arg); 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++) { for (i = 0;; i++) {
fil_aio_wait(segment); fil_aio_wait(segment);
...@@ -424,6 +426,13 @@ io_handler_thread( ...@@ -424,6 +426,13 @@ io_handler_thread(
mutex_exit(&ios_mutex); 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__ #ifndef __WIN__
return(NULL); return(NULL);
#else #else
...@@ -1546,21 +1555,32 @@ innobase_shutdown_for_mysql(void) ...@@ -1546,21 +1555,32 @@ innobase_shutdown_for_mysql(void)
os_thread_count); 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(); sync_close();
/* 4. Free all OS synchronization primitives (in Windows currently /* 4. Free the os_conc_mutex and all os_events and os_mutexes */
events are not freed) */
srv_free(); srv_free();
os_sync_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 */ ut0mem.c */
ut_free_all_mem(); 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) { if (srv_print_verbose_log) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Shutdown completed\n"); fprintf(stderr, " InnoDB: Shutdown completed\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment