250
250
/** IO completion port used by background io threads */
251
251
static HANDLE completion_port;
252
/** IO completion port used by background io READ threads */
253
static HANDLE read_completion_port;
252
254
/** Thread local storage index for the per-thread event used for synchronous IO */
253
255
static DWORD tls_sync_io = TLS_OUT_OF_INDEXES;
3252
3254
os_last_printout = time(NULL);
3254
ut_a(completion_port == 0);
3256
ut_a(completion_port == 0 && read_completion_port == 0);
3255
3257
completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
3256
ut_a(completion_port);
3258
read_completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
3259
ut_a(completion_port && read_completion_port);
3299
3302
if(completion_port)
3301
3304
PostQueuedCompletionStatus(completion_port, 0, IOCP_SHUTDOWN_KEY, NULL);
3305
PostQueuedCompletionStatus(read_completion_port, 0, IOCP_SHUTDOWN_KEY, NULL);
3862
3866
#ifdef WIN_ASYNC_IO
3867
#define READ_SEGMENT(x) (x < srv_n_read_io_threads)
3868
#define WRITE_SEGMENT(x) !READ_SEGMENT(x)
3863
3870
/**********************************************************************//**
3864
3871
This function is only used in Windows asynchronous i/o.
3865
3872
Waits for an aio operation to complete. This function is used to wait the
3899
3906
BOOL retry = FALSE;
3902
ret = GetQueuedCompletionStatus(completion_port, &len, &key,
3903
(OVERLAPPED **)&slot, INFINITE);
3905
/* If shutdown key was received, repost the shutdown message and exit */
3906
if (ret && (key == IOCP_SHUTDOWN_KEY)) {
3907
PostQueuedCompletionStatus(completion_port, 0, key, NULL);
3908
os_thread_exit(NULL);
3911
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
3912
os_thread_exit(NULL);
3908
HANDLE port = READ_SEGMENT(segment)? read_completion_port : completion_port;
3911
ret = GetQueuedCompletionStatus(port, &len, &key,
3912
(OVERLAPPED **)&slot, INFINITE);
3914
/* If shutdown key was received, repost the shutdown message and exit */
3915
if (ret && (key == IOCP_SHUTDOWN_KEY)) {
3916
PostQueuedCompletionStatus(port, 0, key, NULL);
3917
os_thread_exit(NULL);
3920
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
3921
os_thread_exit(NULL);
3924
if(WRITE_SEGMENT(segment)&& slot->type == OS_FILE_READ) {
3926
Redirect read completions to the dedicated completion port
3927
and thread. We need to split read and write threads. If we do not
3928
do that, and just allow all io threads process all IO, it is possible
3929
to get stuck in a deadlock in buffer pool code,
3931
Currently, the problem is solved this way - "write io" threads
3932
always get all completion notifications, from both async reads and
3933
writes. Write completion is handled in the same thread that gets it.
3934
Read completion is forwarded via PostQueueCompletionStatus())
3935
to the second completion port dedicated solely to reads. One of the
3936
"read io" threads waiting on this port will finally handle the IO.
3938
Forwarding IO completion this way costs a context switch , and this
3939
seems tolerable since asynchronous reads are by far less frequent.
3941
ut_a(PostQueuedCompletionStatus(read_completion_port, len, key,