Commit 5a6d4e7e authored by lenz@mysql.com's avatar lenz@mysql.com

Merge lgrimmer@build.mysql.com:/home/bk/mysql-4.0

into mysql.com:/space/my/mysql-4.0
parents 048b89f0 41a5f79a
...@@ -103,7 +103,8 @@ struct com_shm_endpoint_struct{ ...@@ -103,7 +103,8 @@ struct com_shm_endpoint_struct{
the area currently may contain a datagram; the area currently may contain a datagram;
NOTE: automatic event */ NOTE: automatic event */
os_event_t empty; /* this is in the signaled state if the area os_event_t empty; /* this is in the signaled state if the area
currently may be empty; NOTE: automatic event */ currently may be empty; NOTE: automatic
event */
ip_mutex_hdl_t* ip_mutex; /* handle to the interprocess mutex ip_mutex_hdl_t* ip_mutex; /* handle to the interprocess mutex
protecting the shared memory */ protecting the shared memory */
UT_LIST_NODE_T(com_shm_endpoint_t) list; /* If the endpoint struct UT_LIST_NODE_T(com_shm_endpoint_t) list; /* If the endpoint struct
...@@ -793,16 +794,18 @@ com_shm_create_or_open( ...@@ -793,16 +794,18 @@ com_shm_create_or_open(
ut_strcpy(buf + len, (char*)"_IBSHM_EV_NE"), ut_strcpy(buf + len, (char*)"_IBSHM_EV_NE"),
event_ne = os_event_create_auto(buf); event_ne = os_event_create(buf);
ut_ad(event_ne); ut_ad(event_ne);
ut_strcpy(buf + len, (char*)"_IBSHM_EV_EM"), ut_strcpy(buf + len, (char*)"_IBSHM_EV_EM"),
event_em = os_event_create_auto(buf); event_em = os_event_create(buf);
ut_ad(event_em); ut_ad(event_em);
ut_a(0); /* event_ne and event_em should be auto events! */
com_shm_endpoint_set_shm(ep, shm); com_shm_endpoint_set_shm(ep, shm);
com_shm_endpoint_set_map(ep, map); com_shm_endpoint_set_map(ep, map);
......
...@@ -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
...@@ -140,14 +154,15 @@ os_event_wait_multiple( ...@@ -140,14 +154,15 @@ os_event_wait_multiple(
/*===================*/ /*===================*/
/* out: index of the event /* out: index of the event
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 */
...@@ -296,7 +301,7 @@ os_file_handle_error( ...@@ -296,7 +301,7 @@ os_file_handle_error(
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 */ const char* operation)/* in: operation */
{ {
ulint err; ulint err;
...@@ -338,8 +343,8 @@ os_file_handle_error( ...@@ -338,8 +343,8 @@ 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: System call %s.\n", operation);
fprintf(stderr, "InnoDB: Cannot continue operation.\n"); fprintf(stderr, "InnoDB: Cannot continue operation.\n");
fflush(stderr); fflush(stderr);
...@@ -422,9 +427,8 @@ try_again: ...@@ -422,9 +427,8 @@ try_again:
*success = FALSE; *success = FALSE;
retry = os_file_handle_error(file, name, retry = os_file_handle_error(file, name,
create_mode == OS_FILE_OPEN ? create_mode == OS_FILE_OPEN ?
"open" : "create"); "open" : "create");
if (retry) { if (retry) {
goto try_again; goto try_again;
} }
...@@ -465,10 +469,8 @@ try_again: ...@@ -465,10 +469,8 @@ try_again:
*success = FALSE; *success = FALSE;
retry = os_file_handle_error(file, name, retry = os_file_handle_error(file, name,
create_mode == OS_FILE_OPEN ? create_mode == OS_FILE_OPEN ?
"open" : "create"); "open" : "create");
if (retry) { if (retry) {
goto try_again; goto try_again;
} }
...@@ -576,9 +578,8 @@ try_again: ...@@ -576,9 +578,8 @@ try_again:
*success = FALSE; *success = FALSE;
retry = os_file_handle_error(file, name, retry = os_file_handle_error(file, name,
create_mode == OS_FILE_OPEN ? create_mode == OS_FILE_OPEN ?
"open" : "create"); "open" : "create");
if (retry) { if (retry) {
goto try_again; goto try_again;
} }
...@@ -625,9 +626,8 @@ try_again: ...@@ -625,9 +626,8 @@ try_again:
*success = FALSE; *success = FALSE;
retry = os_file_handle_error(file, name, retry = os_file_handle_error(file, name,
create_mode == OS_FILE_OPEN ? create_mode == OS_FILE_OPEN ?
"open" : "create"); "open" : "create");
if (retry) { if (retry) {
goto try_again; goto try_again;
} }
...@@ -1319,19 +1319,22 @@ os_aio_array_create( ...@@ -1319,19 +1319,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 +1432,7 @@ os_aio_array_wake_win_aio_at_shutdown( ...@@ -1429,7 +1432,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 +1692,7 @@ loop: ...@@ -1689,7 +1692,7 @@ loop:
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 +1750,7 @@ os_aio_array_free_slot( ...@@ -1747,7 +1750,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);
} }
...@@ -1872,7 +1875,7 @@ os_aio( ...@@ -1872,7 +1875,7 @@ os_aio(
offset where to read or write */ offset where to read or write */
ulint offset_high, /* in: most significant 32 bits of ulint offset_high, /* in: most significant 32 bits of
offset */ offset */
ulint n, /* in: number of bytes to read or write */ ulint n, /* in: number of bytes to read or write */
void* message1,/* in: messages for the aio handler (these void* message1,/* in: messages for the aio handler (these
can be used to identify a completed aio can be used to identify a completed aio
operation); if mode is OS_AIO_SYNC, these operation); if mode is OS_AIO_SYNC, these
...@@ -1916,7 +1919,8 @@ os_aio( ...@@ -1916,7 +1919,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);
...@@ -1994,8 +1998,7 @@ try_again: ...@@ -1994,8 +1998,7 @@ try_again:
#ifdef WIN_ASYNC_IO #ifdef WIN_ASYNC_IO
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,8 +2028,8 @@ try_again: ...@@ -2025,8 +2028,8 @@ try_again:
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,
type == OS_FILE_READ ? "aio read" : "aio write");
if (retry) { if (retry) {
goto try_again; goto try_again;
...@@ -2091,15 +2094,15 @@ os_aio_windows_handle( ...@@ -2091,15 +2094,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 +2127,7 @@ os_aio_windows_handle( ...@@ -2124,7 +2127,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, "Windows aio");
ret_val = FALSE; ret_val = FALSE;
} }
......
...@@ -32,24 +32,23 @@ struct os_mutex_struct{ ...@@ -32,24 +32,23 @@ struct os_mutex_struct{
/* list of all 'slow' OS mutexes created */ /* list of all 'slow' OS mutexes created */
}; };
/* Mutex protecting the thread count and the lists of OS mutexes /* Mutex protecting counts and the lists of OS mutexes and events */
and events */
os_mutex_t os_sync_mutex; os_mutex_t os_sync_mutex;
ibool os_sync_mutex_inited = FALSE; ibool os_sync_mutex_inited = FALSE;
/* 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 */
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; UT_LIST_BASE_NODE_T(os_event_struct_t) os_event_list;
/* The list of all OS 'slow' mutexes */ /* The list of all OS 'slow' mutexes */
UT_LIST_BASE_NODE_T(os_mutex_str_t) os_mutex_list; 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_event_count = 0; ulint os_mutex_count = 0;
ulint os_mutex_count = 0; ulint os_fast_mutex_count = 0;
/************************************************************* /*************************************************************
...@@ -68,7 +67,7 @@ os_sync_init(void) ...@@ -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 void
os_sync_free(void) os_sync_free(void)
...@@ -89,6 +88,12 @@ os_sync_free(void) ...@@ -89,6 +88,12 @@ os_sync_free(void)
mutex = UT_LIST_GET_FIRST(os_mutex_list); mutex = UT_LIST_GET_FIRST(os_mutex_list);
while (mutex) { while (mutex) {
if (mutex == os_sync_mutex) {
/* Set the flag to FALSE so that we do not try to
reserve os_sync_mutex any more in remaining freeing
operations in shutdown */
os_sync_mutex_inited = FALSE;
}
os_mutex_free(mutex); os_mutex_free(mutex);
...@@ -97,10 +102,9 @@ os_sync_free(void) ...@@ -97,10 +102,9 @@ 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
just have two states: signaled and nonsignaled. states: signaled and nonsignaled. The created event is manual reset: it
The created event is manual reset: it must be reset must be reset explicitly by calling sync_os_reset_event. */
explicitly by calling sync_os_reset_event. */
os_event_t os_event_t
os_event_create( os_event_create(
...@@ -112,20 +116,18 @@ os_event_create( ...@@ -112,20 +116,18 @@ os_event_create(
#ifdef __WIN__ #ifdef __WIN__
os_event_t event; 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 */ TRUE, /* Manual reset */
FALSE, /* Initial state nonsignaled */ FALSE, /* Initial state nonsignaled */
name); name);
if (!event) { if (!event->handle) {
fprintf(stderr, fprintf(stderr,
"InnoDB: Could not create a Windows event semaphore; Windows error %lu\n", "InnoDB: Could not create a Windows event semaphore; Windows error %lu\n",
(ulint)GetLastError()); (ulint)GetLastError());
} }
#else /* Unix */
ut_a(event);
return(event);
#else
os_event_t event; os_event_t event;
UT_NOT_USED(name); UT_NOT_USED(name);
...@@ -141,7 +143,9 @@ os_event_create( ...@@ -141,7 +143,9 @@ os_event_create(
ut_a(0 == pthread_cond_init(&(event->cond_var), NULL)); ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
#endif #endif
event->is_set = FALSE; event->is_set = FALSE;
#endif /* __WIN__ */
/* Put to the list of events */
os_mutex_enter(os_sync_mutex); os_mutex_enter(os_sync_mutex);
UT_LIST_ADD_FIRST(os_event_list, os_event_list, event); UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
...@@ -151,13 +155,12 @@ os_event_create( ...@@ -151,13 +155,12 @@ os_event_create(
os_mutex_exit(os_sync_mutex); os_mutex_exit(os_sync_mutex);
return(event); return(event);
#endif
} }
#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(
...@@ -166,26 +169,33 @@ os_event_create_auto( ...@@ -166,26 +169,33 @@ os_event_create_auto(
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__
os_event_t event; 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, /* Auto-reset */
FALSE, /* Initial state nonsignaled */ FALSE, /* Initial state nonsignaled */
name); name);
ut_a(event);
return(event); if (!event->handle) {
#else fprintf(stderr,
/* Does nothing in Posix because we do not need this with MySQL */ "InnoDB: Could not create a Windows auto event semaphore; Windows error %lu\n",
(ulint)GetLastError());
}
UT_NOT_USED(name); /* Put to the list of events */
os_mutex_enter(os_sync_mutex);
ut_a(0); UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
return(NULL); os_event_count++;
#endif
os_mutex_exit(os_sync_mutex);
return(event);
} }
#endif
/************************************************************** /**************************************************************
Sets an event semaphore to the signaled state: lets waiting threads Sets an event semaphore to the signaled state: lets waiting threads
...@@ -198,7 +208,7 @@ os_event_set( ...@@ -198,7 +208,7 @@ os_event_set(
{ {
#ifdef __WIN__ #ifdef __WIN__
ut_a(event); ut_a(event);
ut_a(SetEvent(event)); ut_a(SetEvent(event->handle));
#else #else
ut_a(event); ut_a(event);
...@@ -227,7 +237,7 @@ os_event_reset( ...@@ -227,7 +237,7 @@ os_event_reset(
#ifdef __WIN__ #ifdef __WIN__
ut_a(event); ut_a(event);
ut_a(ResetEvent(event)); ut_a(ResetEvent(event->handle));
#else #else
ut_a(event); ut_a(event);
...@@ -255,12 +265,14 @@ os_event_free( ...@@ -255,12 +265,14 @@ os_event_free(
#ifdef __WIN__ #ifdef __WIN__
ut_a(event); ut_a(event);
ut_a(CloseHandle(event)); ut_a(CloseHandle(event->handle));
#else #else
ut_a(event); ut_a(event);
os_fast_mutex_free(&(event->os_mutex)); os_fast_mutex_free(&(event->os_mutex));
ut_a(0 == pthread_cond_destroy(&(event->cond_var))); ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
#endif
/* Remove from the list of events */
os_mutex_enter(os_sync_mutex); os_mutex_enter(os_sync_mutex);
...@@ -271,7 +283,6 @@ os_event_free( ...@@ -271,7 +283,6 @@ os_event_free(
os_mutex_exit(os_sync_mutex); os_mutex_exit(os_sync_mutex);
ut_free(event); ut_free(event);
#endif
} }
/************************************************************** /**************************************************************
...@@ -291,7 +302,7 @@ os_event_wait( ...@@ -291,7 +302,7 @@ os_event_wait(
ut_a(event); ut_a(event);
/* Specify an infinite time limit for waiting */ /* Specify an infinite time limit for waiting */
err = WaitForSingleObject(event, INFINITE); err = WaitForSingleObject(event->handle, INFINITE);
ut_a(err == WAIT_OBJECT_0); ut_a(err == WAIT_OBJECT_0);
...@@ -324,7 +335,7 @@ loop: ...@@ -324,7 +335,7 @@ loop:
/************************************************************** /**************************************************************
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(
...@@ -341,9 +352,9 @@ os_event_wait_time( ...@@ -341,9 +352,9 @@ os_event_wait_time(
ut_a(event); ut_a(event);
if (time != OS_SYNC_INFINITE_TIME) { if (time != OS_SYNC_INFINITE_TIME) {
err = WaitForSingleObject(event, time / 1000); err = WaitForSingleObject(event->handle, time / 1000);
} else { } else {
err = WaitForSingleObject(event, INFINITE); err = WaitForSingleObject(event->handle, INFINITE);
} }
if (err == WAIT_OBJECT_0) { if (err == WAIT_OBJECT_0) {
...@@ -367,8 +378,9 @@ os_event_wait_time( ...@@ -367,8 +378,9 @@ os_event_wait_time(
#endif #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. */ one is signaled or becomes signaled. */
ulint ulint
...@@ -376,18 +388,18 @@ os_event_wait_multiple( ...@@ -376,18 +388,18 @@ os_event_wait_multiple(
/*===================*/ /*===================*/
/* out: index of the event /* out: index of the event
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 */
{ {
#ifdef __WIN__
DWORD index; DWORD index;
ut_a(event_array); ut_a(native_event_array);
ut_a(n > 0); ut_a(n > 0);
index = WaitForMultipleObjects(n, event_array, index = WaitForMultipleObjects(n, native_event_array,
FALSE, /* Wait for any 1 event */ FALSE, /* Wait for any 1 event */
INFINITE); /* Infinite wait time INFINITE); /* Infinite wait time
limit */ limit */
...@@ -399,21 +411,12 @@ os_event_wait_multiple( ...@@ -399,21 +411,12 @@ os_event_wait_multiple(
} }
return(index - WAIT_OBJECT_0); 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. 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(
...@@ -430,50 +433,35 @@ os_mutex_create( ...@@ -430,50 +433,35 @@ os_mutex_create(
FALSE, /* Initial state: no owner */ FALSE, /* Initial state: no owner */
name); name);
ut_a(mutex); ut_a(mutex);
mutex_str = ut_malloc(sizeof(os_mutex_str_t));
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 #else
os_fast_mutex_t* os_mutex; os_fast_mutex_t* mutex;
os_mutex_t mutex_str; os_mutex_t mutex_str;
UT_NOT_USED(name); UT_NOT_USED(name);
os_mutex = ut_malloc(sizeof(os_fast_mutex_t)); mutex = ut_malloc(sizeof(os_fast_mutex_t));
os_fast_mutex_init(os_mutex);
os_fast_mutex_init(mutex);
#endif
mutex_str = ut_malloc(sizeof(os_mutex_str_t)); mutex_str = ut_malloc(sizeof(os_mutex_str_t));
mutex_str->handle = os_mutex; mutex_str->handle = mutex;
mutex_str->count = 0; mutex_str->count = 0;
if (os_sync_mutex_inited) { if (os_sync_mutex_inited) {
/* When creating os_sync_mutex itself we cannot reserve it */
os_mutex_enter(os_sync_mutex); os_mutex_enter(os_sync_mutex);
} }
UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str); UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
os_mutex_count++;
if (os_sync_mutex_inited) { if (os_sync_mutex_inited) {
os_mutex_exit(os_sync_mutex); os_mutex_exit(os_sync_mutex);
} }
return(mutex_str); return(mutex_str);
#endif
} }
/************************************************************** /**************************************************************
...@@ -513,21 +501,14 @@ os_mutex_exit( ...@@ -513,21 +501,14 @@ os_mutex_exit(
/*==========*/ /*==========*/
os_mutex_t mutex) /* in: mutex to release */ os_mutex_t mutex) /* in: mutex to release */
{ {
#ifdef __WIN__
ut_a(mutex); ut_a(mutex);
ut_a(mutex->count == 1); ut_a(mutex->count == 1);
(mutex->count)--; (mutex->count)--;
#ifdef __WIN__
ut_a(ReleaseMutex(mutex->handle)); ut_a(ReleaseMutex(mutex->handle));
#else #else
ut_a(mutex);
ut_a(mutex->count == 1);
(mutex->count)--;
os_fast_mutex_unlock(mutex->handle); os_fast_mutex_unlock(mutex->handle);
#endif #endif
} }
...@@ -540,25 +521,25 @@ os_mutex_free( ...@@ -540,25 +521,25 @@ os_mutex_free(
/*==========*/ /*==========*/
os_mutex_t mutex) /* in: mutex to free */ os_mutex_t mutex) /* in: mutex to free */
{ {
#ifdef __WIN__
ut_a(mutex); ut_a(mutex);
os_mutex_enter(os_sync_mutex); if (os_sync_mutex_inited) {
os_mutex_enter(os_sync_mutex);
}
UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex); UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
os_mutex_count--;
os_mutex_exit(os_sync_mutex); if (os_sync_mutex_inited) {
os_mutex_exit(os_sync_mutex);
}
#ifdef __WIN__
ut_a(CloseHandle(mutex->handle)); ut_a(CloseHandle(mutex->handle));
ut_free(mutex); ut_free(mutex);
#else #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); os_fast_mutex_free(mutex->handle);
ut_free(mutex->handle); ut_free(mutex->handle);
ut_free(mutex); ut_free(mutex);
...@@ -583,8 +564,19 @@ os_fast_mutex_init( ...@@ -583,8 +564,19 @@ os_fast_mutex_init(
#else #else
ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST)); ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST));
#endif #endif
os_mutex_count++;
#endif #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 +623,17 @@ os_fast_mutex_free( ...@@ -631,6 +623,17 @@ os_fast_mutex_free(
DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex); DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex);
#else #else
ut_a(0 == pthread_mutex_destroy(fast_mutex)); ut_a(0 == pthread_mutex_destroy(fast_mutex));
os_mutex_count--;
#endif #endif
if (os_sync_mutex_inited) {
/* When freeing the last mutexes, we have
already freed os_sync_mutex */
os_mutex_enter(os_sync_mutex);
}
os_fast_mutex_count--;
if (os_sync_mutex_inited) {
os_mutex_exit(os_sync_mutex);
}
} }
...@@ -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. */
...@@ -1000,6 +1000,8 @@ srv_communication_init( ...@@ -1000,6 +1000,8 @@ srv_communication_init(
ut_a(ret == 0); ut_a(ret == 0);
} }
#ifdef notdefined
/************************************************************************* /*************************************************************************
Implements the recovery utility. */ Implements the recovery utility. */
...@@ -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 @@ loop: ...@@ -2596,6 +2607,10 @@ loop:
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 @@ loop: ...@@ -2657,6 +2676,9 @@ loop:
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 @@ background_loop: ...@@ -2972,6 +2998,15 @@ background_loop:
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 @@ suspend_thread: ...@@ -3110,6 +3145,13 @@ suspend_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");
......
...@@ -2081,8 +2081,13 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) ...@@ -2081,8 +2081,13 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
else else
{ {
sql_print_error("\ sql_print_error("\
Could not parse log event entry, check the master for binlog corruption\n\ Could not parse relay log event entry. The possible reasons are: the master's \
This may also be a network problem, or just a bug in the master or slave code.\ binary log is corrupted (you can check this by running 'mysqlbinlog' on the \
binary log), the slave's relay log is corrupted (you can check this by running \
'mysqlbinlog' on the relay log), a network problem, or a bug in the master's \
or slave's MySQL code. If you want to check the master's binary log or slave's \
relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' \
on this slave.\
"); ");
return 1; return 1;
} }
......
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