use GetQueuedCompletionStatusEx if the OS supports it
This commit is contained in:
parent
38c2322378
commit
fc26321890
@ -103,12 +103,7 @@ int uv_async_send(uv_async_t* handle) {
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSING));
|
||||
|
||||
if (!uv_atomic_exchange_set(&handle->async_sent)) {
|
||||
if (!PostQueuedCompletionStatus(LOOP->iocp,
|
||||
0,
|
||||
0,
|
||||
&handle->async_req.overlapped)) {
|
||||
uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
|
||||
}
|
||||
POST_COMPLETION_FOR_REQ(&handle->async_req);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -92,12 +92,7 @@ static void CALLBACK uv_ares_socksignal_tp(void* parameter, BOOLEAN timerfired)
|
||||
uv_ares_req->data = selhandle;
|
||||
|
||||
/* post ares needs to called */
|
||||
if (!PostQueuedCompletionStatus(LOOP->iocp,
|
||||
0,
|
||||
0,
|
||||
&uv_ares_req->overlapped)) {
|
||||
uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
|
||||
}
|
||||
POST_COMPLETION_FOR_REQ(uv_ares_req);
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,12 +143,7 @@ static void uv_ares_sockstate_cb(void *data, ares_socket_t sock, int read, int w
|
||||
uv_ares_req->data = uv_handle_ares;
|
||||
|
||||
/* post ares done with socket - finish cleanup when all threads done. */
|
||||
if (!PostQueuedCompletionStatus(LOOP->iocp,
|
||||
0,
|
||||
0,
|
||||
&uv_ares_req->overlapped)) {
|
||||
uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
|
||||
}
|
||||
POST_COMPLETION_FOR_REQ(uv_ares_req);
|
||||
} else {
|
||||
assert(0);
|
||||
uv_fatal_error(ERROR_INVALID_DATA, "ares_SockStateCB");
|
||||
@ -256,12 +246,7 @@ void uv_process_ares_cleanup_req(uv_ares_task_t* handle, uv_req_t* req) {
|
||||
}
|
||||
} else {
|
||||
/* stil busy - repost and try again */
|
||||
if (!PostQueuedCompletionStatus(LOOP->iocp,
|
||||
0,
|
||||
0,
|
||||
&req->overlapped)) {
|
||||
uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
|
||||
}
|
||||
POST_COMPLETION_FOR_REQ(req);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -124,33 +124,80 @@ static void uv_poll(int block) {
|
||||
}
|
||||
|
||||
|
||||
static void uv_poll_ex(int block) {
|
||||
BOOL success;
|
||||
DWORD timeout;
|
||||
uv_req_t* req;
|
||||
OVERLAPPED_ENTRY overlappeds[64];
|
||||
ULONG count;
|
||||
int i;
|
||||
|
||||
if (block) {
|
||||
timeout = uv_get_poll_timeout();
|
||||
} else {
|
||||
timeout = 0;
|
||||
}
|
||||
|
||||
assert(pGetQueuedCompletionStatusEx);
|
||||
|
||||
success = pGetQueuedCompletionStatusEx(LOOP->iocp,
|
||||
overlappeds,
|
||||
COUNTOF(overlappeds),
|
||||
&count,
|
||||
timeout,
|
||||
FALSE);
|
||||
if (success) {
|
||||
for (i = 0; i < count; i++) {
|
||||
/* Package was dequeued */
|
||||
req = uv_overlapped_to_req(overlappeds[i].lpOverlapped);
|
||||
if (overlappeds[i].lpOverlapped->Internal != STATUS_SUCCESS) {
|
||||
req->error = uv_new_sys_error(pRtlNtStatusToDosError(
|
||||
overlappeds[i].lpOverlapped->Internal));
|
||||
}
|
||||
uv_insert_pending_req(req);
|
||||
}
|
||||
} else if (GetLastError() != WAIT_TIMEOUT) {
|
||||
/* Serious error */
|
||||
uv_fatal_error(GetLastError(), "GetQueuedCompletionStatusEx");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define UV_LOOP(poll) \
|
||||
while (LOOP->refs > 0) { \
|
||||
uv_update_time(); \
|
||||
uv_process_timers(); \
|
||||
\
|
||||
/* Call idle callbacks if nothing to do. */ \
|
||||
if (LOOP->pending_reqs_tail == NULL && LOOP->endgame_handles == NULL) { \
|
||||
uv_idle_invoke(); \
|
||||
} \
|
||||
\
|
||||
/* Completely flush all pending reqs and endgames. */ \
|
||||
/* We do even when we just called the idle callbacks because those may */ \
|
||||
/* have closed handles or started requests that short-circuited. */ \
|
||||
while (LOOP->pending_reqs_tail || LOOP->endgame_handles) { \
|
||||
uv_process_endgames(); \
|
||||
uv_process_reqs(); \
|
||||
} \
|
||||
\
|
||||
if (LOOP->refs <= 0) { \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
uv_prepare_invoke(); \
|
||||
\
|
||||
poll(LOOP->idle_handles == NULL && LOOP->refs > 0); \
|
||||
\
|
||||
uv_check_invoke(); \
|
||||
}
|
||||
|
||||
|
||||
int uv_run() {
|
||||
while (LOOP->refs > 0) {
|
||||
uv_update_time();
|
||||
uv_process_timers();
|
||||
|
||||
/* Call idle callbacks if nothing to do. */
|
||||
if (LOOP->pending_reqs_tail == NULL && LOOP->endgame_handles == NULL) {
|
||||
uv_idle_invoke();
|
||||
}
|
||||
|
||||
/* Completely flush all pending reqs and endgames. */
|
||||
/* We do even when we just called the idle callbacks because those may */
|
||||
/* have closed handles or started requests that short-circuited. */
|
||||
while (LOOP->pending_reqs_tail || LOOP->endgame_handles) {
|
||||
uv_process_endgames();
|
||||
uv_process_reqs();
|
||||
}
|
||||
|
||||
if (LOOP->refs <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
uv_prepare_invoke();
|
||||
|
||||
uv_poll(LOOP->idle_handles == NULL && LOOP->refs > 0);
|
||||
|
||||
uv_check_invoke();
|
||||
if (pGetQueuedCompletionStatusEx) {
|
||||
UV_LOOP(uv_poll_ex);
|
||||
} else {
|
||||
UV_LOOP(uv_poll);
|
||||
}
|
||||
|
||||
assert(LOOP->refs == 0);
|
||||
|
||||
@ -88,12 +88,7 @@ static DWORD WINAPI getaddrinfo_thread_proc(void* parameter) {
|
||||
handle->retcode = ret;
|
||||
|
||||
/* post getaddrinfo completed */
|
||||
if (!PostQueuedCompletionStatus(LOOP->iocp,
|
||||
0,
|
||||
0,
|
||||
&handle->getadddrinfo_req.overlapped)) {
|
||||
uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
|
||||
}
|
||||
POST_COMPLETION_FOR_REQ(&handle->getadddrinfo_req);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
|
||||
#include "tree.h"
|
||||
#include "ntdll.h"
|
||||
#include "kernel32.h"
|
||||
|
||||
|
||||
/*
|
||||
@ -132,6 +133,15 @@ uv_req_t* uv_overlapped_to_req(OVERLAPPED* overlapped);
|
||||
void uv_insert_pending_req(uv_req_t* req);
|
||||
void uv_process_reqs();
|
||||
|
||||
#define POST_COMPLETION_FOR_REQ(req) \
|
||||
memset(&((req)->overlapped), 0, sizeof((req)->overlapped)); \
|
||||
if (!PostQueuedCompletionStatus(LOOP->iocp, \
|
||||
0, \
|
||||
0, \
|
||||
&((req)->overlapped))) { \
|
||||
uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus"); \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Streams
|
||||
@ -243,6 +253,7 @@ void uv_winapi_init();
|
||||
|
||||
extern sRtlNtStatusToDosError pRtlNtStatusToDosError;
|
||||
extern sNtQueryInformationFile pNtQueryInformationFile;
|
||||
extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
|
||||
|
||||
|
||||
#endif /* UV_WIN_INTERNAL_H_ */
|
||||
|
||||
46
src/win/kernel32.h
Normal file
46
src/win/kernel32.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UV_WIN_KERNEL32_H_
|
||||
#define UV_WIN_KERNEL32_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
#ifndef _MSC_VER
|
||||
typedef struct _OVERLAPPED_ENTRY {
|
||||
ULONG_PTR lpCompletionKey;
|
||||
LPOVERLAPPED lpOverlapped;
|
||||
ULONG_PTR Internal;
|
||||
DWORD dwNumberOfBytesTransferred;
|
||||
} OVERLAPPED_ENTRY, *LPOVERLAPPED_ENTRY;
|
||||
#endif
|
||||
|
||||
|
||||
typedef BOOL (WINAPI *sGetQueuedCompletionStatusEx)
|
||||
(HANDLE CompletionPort,
|
||||
LPOVERLAPPED_ENTRY lpCompletionPortEntries,
|
||||
ULONG ulCount,
|
||||
PULONG ulNumEntriesRemoved,
|
||||
DWORD dwMilliseconds,
|
||||
BOOL fAlertable);
|
||||
|
||||
#endif /* UV_WIN_KERNEL32_H_ */
|
||||
@ -157,12 +157,7 @@ static DWORD WINAPI pipe_shutdown_thread_proc(void* parameter) {
|
||||
FlushFileBuffers(handle->handle);
|
||||
|
||||
/* Post completed */
|
||||
if (!PostQueuedCompletionStatus(LOOP->iocp,
|
||||
0,
|
||||
0,
|
||||
&req->overlapped)) {
|
||||
uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
|
||||
}
|
||||
POST_COMPLETION_FOR_REQ(req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -378,15 +373,8 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
|
||||
req->error = uv_new_sys_error(GetLastError());
|
||||
}
|
||||
|
||||
memset(&req->overlapped, 0, sizeof(req->overlapped));
|
||||
|
||||
/* Post completed */
|
||||
if (!PostQueuedCompletionStatus(LOOP->iocp,
|
||||
0,
|
||||
0,
|
||||
&req->overlapped)) {
|
||||
uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
|
||||
}
|
||||
POST_COMPLETION_FOR_REQ(req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -611,15 +611,8 @@ static void CALLBACK exit_wait_callback(void* data, BOOLEAN didTimeout) {
|
||||
assert(didTimeout == FALSE);
|
||||
assert(process);
|
||||
|
||||
memset(&process->exit_req.overlapped, 0, sizeof(process->exit_req.overlapped));
|
||||
|
||||
/* Post completed */
|
||||
if (!PostQueuedCompletionStatus(LOOP->iocp,
|
||||
0,
|
||||
0,
|
||||
&process->exit_req.overlapped)) {
|
||||
uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
|
||||
}
|
||||
POST_COMPLETION_FOR_REQ(&process->exit_req);
|
||||
}
|
||||
|
||||
|
||||
@ -633,15 +626,8 @@ static void CALLBACK close_wait_callback(void* data, BOOLEAN didTimeout) {
|
||||
assert(didTimeout == FALSE);
|
||||
assert(process);
|
||||
|
||||
memset(&process->close_req.overlapped, 0, sizeof(process->close_req.overlapped));
|
||||
|
||||
/* Post completed */
|
||||
if (!PostQueuedCompletionStatus(LOOP->iocp,
|
||||
0,
|
||||
0,
|
||||
&process->close_req.overlapped)) {
|
||||
uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
|
||||
}
|
||||
POST_COMPLETION_FOR_REQ(&process->close_req);
|
||||
}
|
||||
|
||||
|
||||
@ -679,15 +665,8 @@ static DWORD WINAPI spawn_failure(void* data) {
|
||||
|
||||
FlushFileBuffers(child_stderr);
|
||||
|
||||
memset(&process->exit_req.overlapped, 0, sizeof(process->exit_req.overlapped));
|
||||
|
||||
/* Post completed */
|
||||
if (!PostQueuedCompletionStatus(LOOP->iocp,
|
||||
0,
|
||||
0,
|
||||
&process->exit_req.overlapped)) {
|
||||
uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
|
||||
}
|
||||
POST_COMPLETION_FOR_REQ(&process->exit_req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -28,25 +28,38 @@
|
||||
|
||||
sRtlNtStatusToDosError pRtlNtStatusToDosError;
|
||||
sNtQueryInformationFile pNtQueryInformationFile;
|
||||
sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
|
||||
|
||||
|
||||
void uv_winapi_init() {
|
||||
HMODULE module;
|
||||
HMODULE ntdll_module;
|
||||
HMODULE kernel32_module;
|
||||
|
||||
module = GetModuleHandleA("ntdll.dll");
|
||||
if (module == NULL) {
|
||||
ntdll_module = GetModuleHandleA("ntdll.dll");
|
||||
if (ntdll_module == NULL) {
|
||||
uv_fatal_error(GetLastError(), "GetModuleHandleA");
|
||||
}
|
||||
|
||||
pRtlNtStatusToDosError = (sRtlNtStatusToDosError) GetProcAddress(module,
|
||||
pRtlNtStatusToDosError = (sRtlNtStatusToDosError) GetProcAddress(
|
||||
ntdll_module,
|
||||
"RtlNtStatusToDosError");
|
||||
if (pRtlNtStatusToDosError == NULL) {
|
||||
uv_fatal_error(GetLastError(), "GetProcAddress");
|
||||
}
|
||||
|
||||
pNtQueryInformationFile = (sNtQueryInformationFile) GetProcAddress(module,
|
||||
pNtQueryInformationFile = (sNtQueryInformationFile) GetProcAddress(
|
||||
ntdll_module,
|
||||
"NtQueryInformationFile");
|
||||
if (pNtQueryInformationFile == NULL) {
|
||||
uv_fatal_error(GetLastError(), "GetProcAddress");
|
||||
}
|
||||
}
|
||||
|
||||
kernel32_module = GetModuleHandleA("kernel32.dll");
|
||||
if (kernel32_module == NULL) {
|
||||
uv_fatal_error(GetLastError(), "GetModuleHandleA");
|
||||
}
|
||||
|
||||
pGetQueuedCompletionStatusEx = (sGetQueuedCompletionStatusEx) GetProcAddress(
|
||||
kernel32_module,
|
||||
"GetQueuedCompletionStatusEx");
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user