Skip to content

Commit

Permalink
Skip IOCP for tcp operations that complete synchronously
Browse files Browse the repository at this point in the history
  • Loading branch information
Igor Zinkovsky committed Aug 17, 2011
1 parent 358d89a commit e67b9a3
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 32 deletions.
8 changes: 8 additions & 0 deletions src/win/internal.h
Expand Up @@ -107,6 +107,7 @@ extern uv_loop_t uv_main_loop_;
#define UV_HANDLE_READ_PENDING 0x8000
#define UV_HANDLE_GIVEN_OS_HANDLE 0x10000
#define UV_HANDLE_UV_ALLOCED 0x20000
#define UV_HANDLE_SYNC_BYPASS_IOCP 0x40000

void uv_want_endgame(uv_handle_t* handle);
void uv_process_endgames();
Expand All @@ -122,6 +123,12 @@ void uv_process_endgames();
} \
} while (0)

#define UV_SUCCEEDED_WITHOUT_IOCP(result) \
((result) && (handle->flags & UV_HANDLE_SYNC_BYPASS_IOCP))

#define UV_SUCCEEDED_WITH_IOCP(result) \
((result) || (GetLastError() == ERROR_IO_PENDING))


/*
* Requests
Expand Down Expand Up @@ -254,6 +261,7 @@ void uv_winapi_init();
extern sRtlNtStatusToDosError pRtlNtStatusToDosError;
extern sNtQueryInformationFile pNtQueryInformationFile;
extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
extern sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;


#endif /* UV_WIN_INTERNAL_H_ */
8 changes: 8 additions & 0 deletions src/win/kernel32.h
Expand Up @@ -25,6 +25,10 @@
#include <windows.h>


#define FILE_SKIP_COMPLETION_PORT_ON_SUCCESS 0x1
#define FILE_SKIP_SET_EVENT_ON_HANDLE 0x2


#ifndef _MSC_VER
typedef struct _OVERLAPPED_ENTRY {
ULONG_PTR lpCompletionKey;
Expand All @@ -43,4 +47,8 @@ typedef BOOL (WINAPI *sGetQueuedCompletionStatusEx)
DWORD dwMilliseconds,
BOOL fAlertable);

typedef BOOL (WINAPI* sSetFileCompletionNotificationModes)
(HANDLE FileHandle,
UCHAR Flags);

#endif /* UV_WIN_KERNEL32_H_ */
90 changes: 58 additions & 32 deletions src/win/tcp.c
Expand Up @@ -265,6 +265,16 @@ static int uv_tcp_set_socket(uv_tcp_t* handle, SOCKET socket) {
return -1;
}

if (pSetFileCompletionNotificationModes) {
if (!pSetFileCompletionNotificationModes((HANDLE)socket, FILE_SKIP_SET_EVENT_ON_HANDLE |
FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
uv_set_sys_error(GetLastError());
return -1;
}

handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
}

handle->socket = socket;

return 0;
Expand Down Expand Up @@ -430,19 +440,23 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle) {
&bytes,
&req->overlapped);

if (!success && WSAGetLastError() != ERROR_IO_PENDING) {
if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
/* Process the req without IOCP. */
handle->accept_socket = accept_socket;
handle->reqs_pending++;
uv_insert_pending_req((uv_req_t*)req);
} else if (UV_SUCCEEDED_WITH_IOCP(success)) {
/* The req will be processed with IOCP. */
handle->accept_socket = accept_socket;
handle->reqs_pending++;
} else {
/* Make this req pending reporting an error. */
req->error = uv_new_sys_error(WSAGetLastError());
uv_insert_pending_req(req);
handle->reqs_pending++;
/* Destroy the preallocated client socket. */
closesocket(accept_socket);
return;
}

handle->accept_socket = accept_socket;

handle->reqs_pending++;
}


Expand All @@ -469,16 +483,22 @@ static void uv_tcp_queue_read(uv_tcp_t* handle) {
&flags,
&req->overlapped,
NULL);
if (result != 0 && WSAGetLastError() != ERROR_IO_PENDING) {

if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
/* Process the req without IOCP. */
handle->flags |= UV_HANDLE_READ_PENDING;
handle->reqs_pending++;
uv_insert_pending_req(req);
} else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
/* The req will be processed with IOCP. */
handle->flags |= UV_HANDLE_READ_PENDING;
handle->reqs_pending++;
} else {
/* Make this req pending reporting an error. */
req->error = uv_new_sys_error(WSAGetLastError());
uv_insert_pending_req(req);
handle->reqs_pending++;
return;
}

handle->flags |= UV_HANDLE_READ_PENDING;
handle->reqs_pending++;
}
}


Expand Down Expand Up @@ -606,13 +626,18 @@ int uv_tcp_connect(uv_connect_t* req, uv_tcp_t* handle,
&bytes,
&req->overlapped);

if (!success && WSAGetLastError() != ERROR_IO_PENDING) {
if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
/* Process the req without IOCP. */
handle->reqs_pending++;
uv_insert_pending_req((uv_req_t*)req);
} else if (UV_SUCCEEDED_WITH_IOCP(success)) {
/* The req will be processed with IOCP. */
handle->reqs_pending++;
} else {
uv_set_sys_error(WSAGetLastError());
return -1;
}

handle->reqs_pending++;

return 0;
}

Expand Down Expand Up @@ -656,13 +681,16 @@ int uv_tcp_connect6(uv_connect_t* req, uv_tcp_t* handle,
&bytes,
&req->overlapped);

if (!success && WSAGetLastError() != ERROR_IO_PENDING) {
if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
handle->reqs_pending++;
uv_insert_pending_req((uv_req_t*)req);
} else if (UV_SUCCEEDED_WITH_IOCP(success)) {
handle->reqs_pending++;
} else {
uv_set_sys_error(WSAGetLastError());
return -1;
}

handle->reqs_pending++;

return 0;
}

Expand All @@ -688,7 +716,7 @@ int uv_getsockname(uv_tcp_t* handle, struct sockaddr* name, int* namelen) {
int uv_tcp_write(uv_write_t* req, uv_tcp_t* handle, uv_buf_t bufs[], int bufcnt,
uv_write_cb cb) {
int result;
DWORD bytes, err;
DWORD bytes;

if (!(handle->flags & UV_HANDLE_CONNECTION)) {
uv_set_sys_error(WSAEINVAL);
Expand All @@ -713,27 +741,25 @@ int uv_tcp_write(uv_write_t* req, uv_tcp_t* handle, uv_buf_t bufs[], int bufcnt,
0,
&req->overlapped,
NULL);
if (result != 0) {
err = WSAGetLastError();
if (err != WSA_IO_PENDING) {
/* Send failed due to an error. */
uv_set_sys_error(WSAGetLastError());
return -1;
}
}

if (result == 0) {
if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
/* Request completed immediately. */
req->queued_bytes = 0;
} else {
handle->reqs_pending++;
handle->write_reqs_pending++;
uv_insert_pending_req((uv_req_t*)req);
} else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
/* Request queued by the kernel. */
req->queued_bytes = uv_count_bufs(bufs, bufcnt);
handle->reqs_pending++;
handle->write_reqs_pending++;
handle->write_queue_size += req->queued_bytes;
} else {
/* Send failed due to an error. */
uv_set_sys_error(WSAGetLastError());
return -1;
}

handle->reqs_pending++;
handle->write_reqs_pending++;

return 0;
}

Expand Down
4 changes: 4 additions & 0 deletions src/win/winapi.c
Expand Up @@ -29,6 +29,7 @@
sRtlNtStatusToDosError pRtlNtStatusToDosError;
sNtQueryInformationFile pNtQueryInformationFile;
sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;


void uv_winapi_init() {
Expand Down Expand Up @@ -62,4 +63,7 @@ void uv_winapi_init() {
pGetQueuedCompletionStatusEx = (sGetQueuedCompletionStatusEx) GetProcAddress(
kernel32_module,
"GetQueuedCompletionStatusEx");

pSetFileCompletionNotificationModes = (sSetFileCompletionNotificationModes)
GetProcAddress(kernel32_module, "SetFileCompletionNotificationModes");
}

0 comments on commit e67b9a3

Please sign in to comment.