win: use GetQueuedCompletionStatusEx directly
It was introduced in Vista, so we can assume it's always there now.
This commit is contained in:
parent
2494c088f0
commit
6af08fb527
@ -423,97 +423,6 @@ int uv_backend_timeout(const uv_loop_t* loop) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void uv__poll_wine(uv_loop_t* loop, DWORD timeout) {
|
|
||||||
uv__loop_internal_fields_t* lfields;
|
|
||||||
DWORD bytes;
|
|
||||||
ULONG_PTR key;
|
|
||||||
OVERLAPPED* overlapped;
|
|
||||||
uv_req_t* req;
|
|
||||||
int repeat;
|
|
||||||
uint64_t timeout_time;
|
|
||||||
uint64_t user_timeout;
|
|
||||||
int reset_timeout;
|
|
||||||
|
|
||||||
lfields = uv__get_internal_fields(loop);
|
|
||||||
timeout_time = loop->time + timeout;
|
|
||||||
|
|
||||||
if (lfields->flags & UV_METRICS_IDLE_TIME) {
|
|
||||||
reset_timeout = 1;
|
|
||||||
user_timeout = timeout;
|
|
||||||
timeout = 0;
|
|
||||||
} else {
|
|
||||||
reset_timeout = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (repeat = 0; ; repeat++) {
|
|
||||||
/* Only need to set the provider_entry_time if timeout != 0. The function
|
|
||||||
* will return early if the loop isn't configured with UV_METRICS_IDLE_TIME.
|
|
||||||
*/
|
|
||||||
if (timeout != 0)
|
|
||||||
uv__metrics_set_provider_entry_time(loop);
|
|
||||||
|
|
||||||
/* Store the current timeout in a location that's globally accessible so
|
|
||||||
* other locations like uv__work_done() can determine whether the queue
|
|
||||||
* of events in the callback were waiting when poll was called.
|
|
||||||
*/
|
|
||||||
lfields->current_timeout = timeout;
|
|
||||||
|
|
||||||
GetQueuedCompletionStatus(loop->iocp,
|
|
||||||
&bytes,
|
|
||||||
&key,
|
|
||||||
&overlapped,
|
|
||||||
timeout);
|
|
||||||
|
|
||||||
if (reset_timeout != 0) {
|
|
||||||
if (overlapped && timeout == 0)
|
|
||||||
uv__metrics_inc_events_waiting(loop, 1);
|
|
||||||
timeout = user_timeout;
|
|
||||||
reset_timeout = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Placed here because on success the loop will break whether there is an
|
|
||||||
* empty package or not, or if GetQueuedCompletionStatus returned early then
|
|
||||||
* the timeout will be updated and the loop will run again. In either case
|
|
||||||
* the idle time will need to be updated.
|
|
||||||
*/
|
|
||||||
uv__metrics_update_idle_time(loop);
|
|
||||||
|
|
||||||
if (overlapped) {
|
|
||||||
uv__metrics_inc_events(loop, 1);
|
|
||||||
|
|
||||||
/* Package was dequeued */
|
|
||||||
req = uv__overlapped_to_req(overlapped);
|
|
||||||
uv__insert_pending_req(loop, req);
|
|
||||||
|
|
||||||
/* Some time might have passed waiting for I/O,
|
|
||||||
* so update the loop time here.
|
|
||||||
*/
|
|
||||||
uv_update_time(loop);
|
|
||||||
} else if (GetLastError() != WAIT_TIMEOUT) {
|
|
||||||
/* Serious error */
|
|
||||||
uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus");
|
|
||||||
} else if (timeout > 0) {
|
|
||||||
/* GetQueuedCompletionStatus can occasionally return a little early.
|
|
||||||
* Make sure that the desired timeout target time is reached.
|
|
||||||
*/
|
|
||||||
uv_update_time(loop);
|
|
||||||
if (timeout_time > loop->time) {
|
|
||||||
timeout = (DWORD)(timeout_time - loop->time);
|
|
||||||
/* The first call to GetQueuedCompletionStatus should return very
|
|
||||||
* close to the target time and the second should reach it, but
|
|
||||||
* this is not stated in the documentation. To make sure a busy
|
|
||||||
* loop cannot happen, the timeout is increased exponentially
|
|
||||||
* starting on the third round.
|
|
||||||
*/
|
|
||||||
timeout += repeat ? (1 << (repeat - 1)) : 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void uv__poll(uv_loop_t* loop, DWORD timeout) {
|
static void uv__poll(uv_loop_t* loop, DWORD timeout) {
|
||||||
uv__loop_internal_fields_t* lfields;
|
uv__loop_internal_fields_t* lfields;
|
||||||
BOOL success;
|
BOOL success;
|
||||||
@ -553,7 +462,7 @@ static void uv__poll(uv_loop_t* loop, DWORD timeout) {
|
|||||||
*/
|
*/
|
||||||
lfields->current_timeout = timeout;
|
lfields->current_timeout = timeout;
|
||||||
|
|
||||||
success = pGetQueuedCompletionStatusEx(loop->iocp,
|
success = GetQueuedCompletionStatusEx(loop->iocp,
|
||||||
overlappeds,
|
overlappeds,
|
||||||
ARRAY_SIZE(overlappeds),
|
ARRAY_SIZE(overlappeds),
|
||||||
&count,
|
&count,
|
||||||
@ -566,7 +475,7 @@ static void uv__poll(uv_loop_t* loop, DWORD timeout) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Placed here because on success the loop will break whether there is an
|
/* Placed here because on success the loop will break whether there is an
|
||||||
* empty package or not, or if pGetQueuedCompletionStatusEx returned early
|
* empty package or not, or if GetQueuedCompletionStatusEx returned early
|
||||||
* then the timeout will be updated and the loop will run again. In either
|
* then the timeout will be updated and the loop will run again. In either
|
||||||
* case the idle time will need to be updated.
|
* case the idle time will need to be updated.
|
||||||
*/
|
*/
|
||||||
@ -647,10 +556,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
|
|||||||
|
|
||||||
uv__metrics_inc_loop_count(loop);
|
uv__metrics_inc_loop_count(loop);
|
||||||
|
|
||||||
if (pGetQueuedCompletionStatusEx)
|
|
||||||
uv__poll(loop, timeout);
|
uv__poll(loop, timeout);
|
||||||
else
|
|
||||||
uv__poll_wine(loop, timeout);
|
|
||||||
|
|
||||||
/* Process immediate callbacks (e.g. write_cb) a small fixed number of
|
/* Process immediate callbacks (e.g. write_cb) a small fixed number of
|
||||||
* times to avoid loop starvation.*/
|
* times to avoid loop starvation.*/
|
||||||
|
|||||||
@ -36,9 +36,6 @@ sNtQueryDirectoryFile pNtQueryDirectoryFile;
|
|||||||
sNtQuerySystemInformation pNtQuerySystemInformation;
|
sNtQuerySystemInformation pNtQuerySystemInformation;
|
||||||
sNtQueryInformationProcess pNtQueryInformationProcess;
|
sNtQueryInformationProcess pNtQueryInformationProcess;
|
||||||
|
|
||||||
/* Kernel32 function pointers */
|
|
||||||
sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
|
|
||||||
|
|
||||||
/* Powrprof.dll function pointer */
|
/* Powrprof.dll function pointer */
|
||||||
sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
|
sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
|
||||||
|
|
||||||
@ -55,7 +52,6 @@ void uv__winapi_init(void) {
|
|||||||
HMODULE ntdll_module;
|
HMODULE ntdll_module;
|
||||||
HMODULE powrprof_module;
|
HMODULE powrprof_module;
|
||||||
HMODULE user32_module;
|
HMODULE user32_module;
|
||||||
HMODULE kernel32_module;
|
|
||||||
HMODULE ws2_32_module;
|
HMODULE ws2_32_module;
|
||||||
HMODULE api_win_core_file_module;
|
HMODULE api_win_core_file_module;
|
||||||
|
|
||||||
@ -121,15 +117,6 @@ void uv__winapi_init(void) {
|
|||||||
uv_fatal_error(GetLastError(), "GetProcAddress");
|
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");
|
|
||||||
|
|
||||||
powrprof_module = LoadLibraryExA("powrprof.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
powrprof_module = LoadLibraryExA("powrprof.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||||
if (powrprof_module != NULL) {
|
if (powrprof_module != NULL) {
|
||||||
pPowerRegisterSuspendResumeNotification = (sPowerRegisterSuspendResumeNotification)
|
pPowerRegisterSuspendResumeNotification = (sPowerRegisterSuspendResumeNotification)
|
||||||
|
|||||||
@ -4716,14 +4716,6 @@ typedef NTSTATUS (NTAPI *sNtQueryInformationProcess)
|
|||||||
# define ERROR_MUI_FILE_NOT_LOADED 15105
|
# define ERROR_MUI_FILE_NOT_LOADED 15105
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef BOOL (WINAPI *sGetQueuedCompletionStatusEx)
|
|
||||||
(HANDLE CompletionPort,
|
|
||||||
LPOVERLAPPED_ENTRY lpCompletionPortEntries,
|
|
||||||
ULONG ulCount,
|
|
||||||
PULONG ulNumEntriesRemoved,
|
|
||||||
DWORD dwMilliseconds,
|
|
||||||
BOOL fAlertable);
|
|
||||||
|
|
||||||
/* from powerbase.h */
|
/* from powerbase.h */
|
||||||
#ifndef DEVICE_NOTIFY_CALLBACK
|
#ifndef DEVICE_NOTIFY_CALLBACK
|
||||||
# define DEVICE_NOTIFY_CALLBACK 2
|
# define DEVICE_NOTIFY_CALLBACK 2
|
||||||
@ -4818,9 +4810,6 @@ extern sNtQueryDirectoryFile pNtQueryDirectoryFile;
|
|||||||
extern sNtQuerySystemInformation pNtQuerySystemInformation;
|
extern sNtQuerySystemInformation pNtQuerySystemInformation;
|
||||||
extern sNtQueryInformationProcess pNtQueryInformationProcess;
|
extern sNtQueryInformationProcess pNtQueryInformationProcess;
|
||||||
|
|
||||||
/* Kernel32 function pointers */
|
|
||||||
extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
|
|
||||||
|
|
||||||
/* Powrprof.dll function pointer */
|
/* Powrprof.dll function pointer */
|
||||||
extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
|
extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user