Partially revert "win,code: remove GetQueuedCompletionStatus-based poller"
This reverts commit fd8d212a80,
and thereby restores partial support for using libuv under Wine
(which does not implement GetQueuedCompletionStatusEx).
PR-URL: https://github.com/libuv/libuv/pull/1963
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Bert Belder <bertbelder@gmail.com>
This commit is contained in:
parent
f43c663433
commit
153ea114ff
@ -381,6 +381,57 @@ int uv_backend_timeout(const uv_loop_t* loop) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void uv__poll_wine(uv_loop_t* loop, DWORD timeout) {
|
||||||
|
DWORD bytes;
|
||||||
|
ULONG_PTR key;
|
||||||
|
OVERLAPPED* overlapped;
|
||||||
|
uv_req_t* req;
|
||||||
|
int repeat;
|
||||||
|
uint64_t timeout_time;
|
||||||
|
|
||||||
|
timeout_time = loop->time + timeout;
|
||||||
|
|
||||||
|
for (repeat = 0; ; repeat++) {
|
||||||
|
GetQueuedCompletionStatus(loop->iocp,
|
||||||
|
&bytes,
|
||||||
|
&key,
|
||||||
|
&overlapped,
|
||||||
|
timeout);
|
||||||
|
|
||||||
|
if (overlapped) {
|
||||||
|
/* 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) {
|
||||||
BOOL success;
|
BOOL success;
|
||||||
uv_req_t* req;
|
uv_req_t* req;
|
||||||
@ -473,7 +524,11 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
|
|||||||
if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
|
if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
|
||||||
timeout = uv_backend_timeout(loop);
|
timeout = uv_backend_timeout(loop);
|
||||||
|
|
||||||
uv__poll(loop, timeout);
|
if (pGetQueuedCompletionStatusEx)
|
||||||
|
uv__poll(loop, timeout);
|
||||||
|
else
|
||||||
|
uv__poll_wine(loop, timeout);
|
||||||
|
|
||||||
|
|
||||||
uv_check_invoke(loop);
|
uv_check_invoke(loop);
|
||||||
uv_process_endgames(loop);
|
uv_process_endgames(loop);
|
||||||
|
|||||||
@ -34,6 +34,9 @@ sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
|
|||||||
sNtQueryDirectoryFile pNtQueryDirectoryFile;
|
sNtQueryDirectoryFile pNtQueryDirectoryFile;
|
||||||
sNtQuerySystemInformation pNtQuerySystemInformation;
|
sNtQuerySystemInformation pNtQuerySystemInformation;
|
||||||
|
|
||||||
|
/* Kernel32 function pointers */
|
||||||
|
sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
|
||||||
|
|
||||||
/* Powrprof.dll function pointer */
|
/* Powrprof.dll function pointer */
|
||||||
sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
|
sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
|
||||||
|
|
||||||
@ -45,6 +48,7 @@ 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;
|
||||||
|
|
||||||
ntdll_module = GetModuleHandleA("ntdll.dll");
|
ntdll_module = GetModuleHandleA("ntdll.dll");
|
||||||
if (ntdll_module == NULL) {
|
if (ntdll_module == NULL) {
|
||||||
@ -98,6 +102,15 @@ 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 = LoadLibraryA("powrprof.dll");
|
powrprof_module = LoadLibraryA("powrprof.dll");
|
||||||
if (powrprof_module != NULL) {
|
if (powrprof_module != NULL) {
|
||||||
pPowerRegisterSuspendResumeNotification = (sPowerRegisterSuspendResumeNotification)
|
pPowerRegisterSuspendResumeNotification = (sPowerRegisterSuspendResumeNotification)
|
||||||
|
|||||||
@ -4642,6 +4642,14 @@ typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile)
|
|||||||
# 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
|
||||||
@ -4704,6 +4712,9 @@ extern sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
|
|||||||
extern sNtQueryDirectoryFile pNtQueryDirectoryFile;
|
extern sNtQueryDirectoryFile pNtQueryDirectoryFile;
|
||||||
extern sNtQuerySystemInformation pNtQuerySystemInformation;
|
extern sNtQuerySystemInformation pNtQuerySystemInformation;
|
||||||
|
|
||||||
|
/* 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