win: drop support for Windows < Vista
PR-URL: https://github.com/libuv/libuv/pull/966 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Fedor Indutny <fedor@indutny.com>
This commit is contained in:
parent
9d2c77e9f6
commit
9329327a2a
@ -224,7 +224,7 @@ Run:
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
Microsoft Windows operating systems since Windows XP SP2. It can be built
|
||||
Microsoft Windows operating systems since Windows Vista. It can be built
|
||||
with either Visual Studio 2015 or MinGW.
|
||||
|
||||
Linux using the GCC toolchain.
|
||||
|
||||
@ -290,10 +290,6 @@ API
|
||||
|
||||
Equivalent to :man:`realpath(3)` on Unix. Windows uses ``GetFinalPathNameByHandle()``.
|
||||
|
||||
.. note::
|
||||
This function is not implemented on Windows XP and Windows Server 2003.
|
||||
On these systems, UV_ENOSYS is returned.
|
||||
|
||||
.. versionadded:: 1.8.0
|
||||
|
||||
.. c:function:: int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb)
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
#ifndef _WIN32_WINNT
|
||||
# define _WIN32_WINNT 0x0502
|
||||
# define _WIN32_WINNT 0x0600
|
||||
#endif
|
||||
|
||||
#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED)
|
||||
|
||||
@ -251,58 +251,7 @@ int uv_backend_timeout(const uv_loop_t* loop) {
|
||||
}
|
||||
|
||||
|
||||
static void uv_poll(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_ex(uv_loop_t* loop, DWORD timeout) {
|
||||
static void uv__loop_poll(uv_loop_t* loop, DWORD timeout) {
|
||||
BOOL success;
|
||||
uv_req_t* req;
|
||||
OVERLAPPED_ENTRY overlappeds[128];
|
||||
@ -314,12 +263,12 @@ static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) {
|
||||
timeout_time = loop->time + timeout;
|
||||
|
||||
for (repeat = 0; ; repeat++) {
|
||||
success = pGetQueuedCompletionStatusEx(loop->iocp,
|
||||
overlappeds,
|
||||
ARRAY_SIZE(overlappeds),
|
||||
&count,
|
||||
timeout,
|
||||
FALSE);
|
||||
success = GetQueuedCompletionStatusEx(loop->iocp,
|
||||
overlappeds,
|
||||
ARRAY_SIZE(overlappeds),
|
||||
&count,
|
||||
timeout,
|
||||
FALSE);
|
||||
|
||||
if (success) {
|
||||
for (i = 0; i < count; i++) {
|
||||
@ -373,12 +322,6 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
|
||||
DWORD timeout;
|
||||
int r;
|
||||
int ran_pending;
|
||||
void (*poll)(uv_loop_t* loop, DWORD timeout);
|
||||
|
||||
if (pGetQueuedCompletionStatusEx)
|
||||
poll = &uv_poll_ex;
|
||||
else
|
||||
poll = &uv_poll;
|
||||
|
||||
r = uv__loop_alive(loop);
|
||||
if (!r)
|
||||
@ -396,7 +339,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
|
||||
if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
|
||||
timeout = uv_backend_timeout(loop);
|
||||
|
||||
(*poll)(loop, timeout);
|
||||
uv__loop_poll(loop, timeout);
|
||||
|
||||
uv_check_invoke(loop);
|
||||
uv_process_endgames(loop);
|
||||
|
||||
19
src/win/fs.c
19
src/win/fs.c
@ -1675,17 +1675,15 @@ static void fs__symlink(uv_fs_t* req) {
|
||||
|
||||
if (flags & UV_FS_SYMLINK_JUNCTION) {
|
||||
fs__create_junction(req, pathw, new_pathw);
|
||||
} else if (pCreateSymbolicLinkW) {
|
||||
result = pCreateSymbolicLinkW(new_pathw,
|
||||
pathw,
|
||||
flags & UV_FS_SYMLINK_DIR ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) ? 0 : -1;
|
||||
} else {
|
||||
result = CreateSymbolicLinkW(new_pathw,
|
||||
pathw,
|
||||
flags & UV_FS_SYMLINK_DIR ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) ? 0 : -1;
|
||||
if (result == -1) {
|
||||
SET_REQ_WIN32_ERROR(req, GetLastError());
|
||||
} else {
|
||||
SET_REQ_RESULT(req, result);
|
||||
}
|
||||
} else {
|
||||
SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1725,7 +1723,7 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
|
||||
WCHAR* w_realpath_ptr = NULL;
|
||||
WCHAR* w_realpath_buf;
|
||||
|
||||
w_realpath_len = pGetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS);
|
||||
w_realpath_len = GetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS);
|
||||
if (w_realpath_len == 0) {
|
||||
return -1;
|
||||
}
|
||||
@ -1737,7 +1735,7 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
|
||||
}
|
||||
w_realpath_ptr = w_realpath_buf;
|
||||
|
||||
if (pGetFinalPathNameByHandleW(handle,
|
||||
if (GetFinalPathNameByHandleW(handle,
|
||||
w_realpath_ptr,
|
||||
w_realpath_len,
|
||||
VOLUME_NAME_DOS) == 0) {
|
||||
@ -1772,11 +1770,6 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
|
||||
static void fs__realpath(uv_fs_t* req) {
|
||||
HANDLE handle;
|
||||
|
||||
if (!pGetFinalPathNameByHandleW) {
|
||||
SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
|
||||
return;
|
||||
}
|
||||
|
||||
handle = CreateFileW(req->file.pathw,
|
||||
0,
|
||||
0,
|
||||
|
||||
@ -114,10 +114,9 @@ static void uv_pipe_connection_init(uv_pipe_t* handle) {
|
||||
handle->read_req.data = handle;
|
||||
handle->pipe.conn.eof_timer = NULL;
|
||||
assert(!(handle->flags & UV_HANDLE_PIPESERVER));
|
||||
if (pCancelSynchronousIo &&
|
||||
handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
|
||||
uv_mutex_init(&handle->pipe.conn.readfile_mutex);
|
||||
handle->flags |= UV_HANDLE_PIPE_READ_CANCELABLE;
|
||||
if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
|
||||
uv_mutex_init(&handle->pipe.conn.readfile_mutex);
|
||||
handle->flags |= UV_HANDLE_PIPE_READ_CANCELABLE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -718,7 +717,7 @@ void uv__pipe_pause_read(uv_pipe_t* handle) {
|
||||
/* spinlock: we expect this to finish quickly,
|
||||
or we are probably about to deadlock anyways
|
||||
(in the kernel), so it doesn't matter */
|
||||
pCancelSynchronousIo(h);
|
||||
CancelSynchronousIo(h);
|
||||
SwitchToThread(); /* yield thread control briefly */
|
||||
h = handle->pipe.conn.readfile_thread;
|
||||
}
|
||||
|
||||
@ -524,8 +524,6 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
|
||||
|
||||
/* Try to obtain a base handle for the socket. This increases this chances */
|
||||
/* that we find an AFD handle and are able to use the fast poll mechanism. */
|
||||
/* This will always fail on windows XP/2k3, since they don't support the */
|
||||
/* SIO_BASE_HANDLE ioctl. */
|
||||
#ifndef NDEBUG
|
||||
base_socket = INVALID_SOCKET;
|
||||
#endif
|
||||
|
||||
@ -118,9 +118,8 @@ static int uv_tcp_set_socket(uv_loop_t* loop,
|
||||
non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv4;
|
||||
}
|
||||
|
||||
if (pSetFileCompletionNotificationModes &&
|
||||
!(handle->flags & UV_HANDLE_EMULATE_IOCP) && !non_ifs_lsp) {
|
||||
if (pSetFileCompletionNotificationModes((HANDLE) socket,
|
||||
if (!(handle->flags & UV_HANDLE_EMULATE_IOCP) && !non_ifs_lsp) {
|
||||
if (SetFileCompletionNotificationModes((HANDLE) socket,
|
||||
FILE_SKIP_SET_EVENT_ON_HANDLE |
|
||||
FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
|
||||
handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
|
||||
@ -327,8 +326,7 @@ static int uv_tcp_try_bind(uv_tcp_t* handle,
|
||||
on = (flags & UV_TCP_IPV6ONLY) != 0;
|
||||
|
||||
/* TODO: how to handle errors? This may fail if there is no ipv4 stack */
|
||||
/* available, or when run on XP/2003 which have no support for dualstack */
|
||||
/* sockets. For now we're silently ignoring the error. */
|
||||
/* available. For now we're silently ignoring the error. */
|
||||
setsockopt(handle->socket,
|
||||
IPPROTO_IPV6,
|
||||
IPV6_V6ONLY,
|
||||
@ -1342,8 +1340,8 @@ static int uv_tcp_try_cancel_io(uv_tcp_t* tcp) {
|
||||
non_ifs_lsp = (tcp->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 :
|
||||
uv_tcp_non_ifs_lsp_ipv4;
|
||||
|
||||
/* If there are non-ifs LSPs then try to obtain a base handle for the */
|
||||
/* socket. This will always fail on Windows XP/3k. */
|
||||
/* If there are non-ifs LSPs then try to obtain a base handle for the
|
||||
socket. */
|
||||
if (non_ifs_lsp) {
|
||||
DWORD bytes;
|
||||
if (WSAIoctl(socket,
|
||||
|
||||
233
src/win/thread.c
233
src/win/thread.c
@ -27,25 +27,6 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
#define HAVE_CONDVAR_API() (pInitializeConditionVariable != NULL)
|
||||
|
||||
static int uv_cond_fallback_init(uv_cond_t* cond);
|
||||
static void uv_cond_fallback_destroy(uv_cond_t* cond);
|
||||
static void uv_cond_fallback_signal(uv_cond_t* cond);
|
||||
static void uv_cond_fallback_broadcast(uv_cond_t* cond);
|
||||
static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex);
|
||||
static int uv_cond_fallback_timedwait(uv_cond_t* cond,
|
||||
uv_mutex_t* mutex, uint64_t timeout);
|
||||
|
||||
static int uv_cond_condvar_init(uv_cond_t* cond);
|
||||
static void uv_cond_condvar_destroy(uv_cond_t* cond);
|
||||
static void uv_cond_condvar_signal(uv_cond_t* cond);
|
||||
static void uv_cond_condvar_broadcast(uv_cond_t* cond);
|
||||
static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex);
|
||||
static int uv_cond_condvar_timedwait(uv_cond_t* cond,
|
||||
uv_mutex_t* mutex, uint64_t timeout);
|
||||
|
||||
|
||||
static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) {
|
||||
DWORD result;
|
||||
HANDLE existing_event, created_event;
|
||||
@ -138,7 +119,7 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
|
||||
ctx->arg = arg;
|
||||
|
||||
/* Create the thread in suspended state so we have a chance to pass
|
||||
* its own creation handle to it */
|
||||
* its own creation handle to it */
|
||||
thread = (HANDLE) _beginthreadex(NULL,
|
||||
0,
|
||||
uv__thread_start,
|
||||
@ -371,220 +352,39 @@ int uv_sem_trywait(uv_sem_t* sem) {
|
||||
}
|
||||
|
||||
|
||||
/* This condition variable implementation is based on the SetEvent solution
|
||||
* (section 3.2) at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
|
||||
* We could not use the SignalObjectAndWait solution (section 3.4) because
|
||||
* it want the 2nd argument (type uv_mutex_t) of uv_cond_wait() and
|
||||
* uv_cond_timedwait() to be HANDLEs, but we use CRITICAL_SECTIONs.
|
||||
*/
|
||||
|
||||
static int uv_cond_fallback_init(uv_cond_t* cond) {
|
||||
int err;
|
||||
|
||||
/* Initialize the count to 0. */
|
||||
cond->fallback.waiters_count = 0;
|
||||
|
||||
InitializeCriticalSection(&cond->fallback.waiters_count_lock);
|
||||
|
||||
/* Create an auto-reset event. */
|
||||
cond->fallback.signal_event = CreateEvent(NULL, /* no security */
|
||||
FALSE, /* auto-reset event */
|
||||
FALSE, /* non-signaled initially */
|
||||
NULL); /* unnamed */
|
||||
if (!cond->fallback.signal_event) {
|
||||
err = GetLastError();
|
||||
goto error2;
|
||||
}
|
||||
|
||||
/* Create a manual-reset event. */
|
||||
cond->fallback.broadcast_event = CreateEvent(NULL, /* no security */
|
||||
TRUE, /* manual-reset */
|
||||
FALSE, /* non-signaled */
|
||||
NULL); /* unnamed */
|
||||
if (!cond->fallback.broadcast_event) {
|
||||
err = GetLastError();
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
CloseHandle(cond->fallback.signal_event);
|
||||
error2:
|
||||
DeleteCriticalSection(&cond->fallback.waiters_count_lock);
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
||||
|
||||
static int uv_cond_condvar_init(uv_cond_t* cond) {
|
||||
pInitializeConditionVariable(&cond->cond_var);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_cond_init(uv_cond_t* cond) {
|
||||
uv__once_init();
|
||||
|
||||
if (HAVE_CONDVAR_API())
|
||||
return uv_cond_condvar_init(cond);
|
||||
else
|
||||
return uv_cond_fallback_init(cond);
|
||||
}
|
||||
|
||||
|
||||
static void uv_cond_fallback_destroy(uv_cond_t* cond) {
|
||||
if (!CloseHandle(cond->fallback.broadcast_event))
|
||||
abort();
|
||||
if (!CloseHandle(cond->fallback.signal_event))
|
||||
abort();
|
||||
DeleteCriticalSection(&cond->fallback.waiters_count_lock);
|
||||
}
|
||||
|
||||
|
||||
static void uv_cond_condvar_destroy(uv_cond_t* cond) {
|
||||
/* nothing to do */
|
||||
InitializeConditionVariable(&cond->cond_var);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uv_cond_destroy(uv_cond_t* cond) {
|
||||
if (HAVE_CONDVAR_API())
|
||||
uv_cond_condvar_destroy(cond);
|
||||
else
|
||||
uv_cond_fallback_destroy(cond);
|
||||
}
|
||||
|
||||
|
||||
static void uv_cond_fallback_signal(uv_cond_t* cond) {
|
||||
int have_waiters;
|
||||
|
||||
/* Avoid race conditions. */
|
||||
EnterCriticalSection(&cond->fallback.waiters_count_lock);
|
||||
have_waiters = cond->fallback.waiters_count > 0;
|
||||
LeaveCriticalSection(&cond->fallback.waiters_count_lock);
|
||||
|
||||
if (have_waiters)
|
||||
SetEvent(cond->fallback.signal_event);
|
||||
}
|
||||
|
||||
|
||||
static void uv_cond_condvar_signal(uv_cond_t* cond) {
|
||||
pWakeConditionVariable(&cond->cond_var);
|
||||
/* Nothing to do. */
|
||||
}
|
||||
|
||||
|
||||
void uv_cond_signal(uv_cond_t* cond) {
|
||||
if (HAVE_CONDVAR_API())
|
||||
uv_cond_condvar_signal(cond);
|
||||
else
|
||||
uv_cond_fallback_signal(cond);
|
||||
}
|
||||
|
||||
|
||||
static void uv_cond_fallback_broadcast(uv_cond_t* cond) {
|
||||
int have_waiters;
|
||||
|
||||
/* Avoid race conditions. */
|
||||
EnterCriticalSection(&cond->fallback.waiters_count_lock);
|
||||
have_waiters = cond->fallback.waiters_count > 0;
|
||||
LeaveCriticalSection(&cond->fallback.waiters_count_lock);
|
||||
|
||||
if (have_waiters)
|
||||
SetEvent(cond->fallback.broadcast_event);
|
||||
}
|
||||
|
||||
|
||||
static void uv_cond_condvar_broadcast(uv_cond_t* cond) {
|
||||
pWakeAllConditionVariable(&cond->cond_var);
|
||||
WakeConditionVariable(&cond->cond_var);
|
||||
}
|
||||
|
||||
|
||||
void uv_cond_broadcast(uv_cond_t* cond) {
|
||||
if (HAVE_CONDVAR_API())
|
||||
uv_cond_condvar_broadcast(cond);
|
||||
else
|
||||
uv_cond_fallback_broadcast(cond);
|
||||
}
|
||||
|
||||
|
||||
static int uv_cond_wait_helper(uv_cond_t* cond, uv_mutex_t* mutex,
|
||||
DWORD dwMilliseconds) {
|
||||
DWORD result;
|
||||
int last_waiter;
|
||||
HANDLE handles[2] = {
|
||||
cond->fallback.signal_event,
|
||||
cond->fallback.broadcast_event
|
||||
};
|
||||
|
||||
/* Avoid race conditions. */
|
||||
EnterCriticalSection(&cond->fallback.waiters_count_lock);
|
||||
cond->fallback.waiters_count++;
|
||||
LeaveCriticalSection(&cond->fallback.waiters_count_lock);
|
||||
|
||||
/* It's ok to release the <mutex> here since Win32 manual-reset events */
|
||||
/* maintain state when used with <SetEvent>. This avoids the "lost wakeup" */
|
||||
/* bug. */
|
||||
uv_mutex_unlock(mutex);
|
||||
|
||||
/* Wait for either event to become signaled due to <uv_cond_signal> being */
|
||||
/* called or <uv_cond_broadcast> being called. */
|
||||
result = WaitForMultipleObjects(2, handles, FALSE, dwMilliseconds);
|
||||
|
||||
EnterCriticalSection(&cond->fallback.waiters_count_lock);
|
||||
cond->fallback.waiters_count--;
|
||||
last_waiter = result == WAIT_OBJECT_0 + 1
|
||||
&& cond->fallback.waiters_count == 0;
|
||||
LeaveCriticalSection(&cond->fallback.waiters_count_lock);
|
||||
|
||||
/* Some thread called <pthread_cond_broadcast>. */
|
||||
if (last_waiter) {
|
||||
/* We're the last waiter to be notified or to stop waiting, so reset the */
|
||||
/* the manual-reset event. */
|
||||
ResetEvent(cond->fallback.broadcast_event);
|
||||
}
|
||||
|
||||
/* Reacquire the <mutex>. */
|
||||
uv_mutex_lock(mutex);
|
||||
|
||||
if (result == WAIT_OBJECT_0 || result == WAIT_OBJECT_0 + 1)
|
||||
return 0;
|
||||
|
||||
if (result == WAIT_TIMEOUT)
|
||||
return UV_ETIMEDOUT;
|
||||
|
||||
abort();
|
||||
return -1; /* Satisfy the compiler. */
|
||||
}
|
||||
|
||||
|
||||
static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
|
||||
if (uv_cond_wait_helper(cond, mutex, INFINITE))
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
|
||||
if (!pSleepConditionVariableCS(&cond->cond_var, mutex, INFINITE))
|
||||
abort();
|
||||
WakeAllConditionVariable(&cond->cond_var);
|
||||
}
|
||||
|
||||
|
||||
void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
|
||||
if (HAVE_CONDVAR_API())
|
||||
uv_cond_condvar_wait(cond, mutex);
|
||||
else
|
||||
uv_cond_fallback_wait(cond, mutex);
|
||||
if (!SleepConditionVariableCS(&cond->cond_var, mutex, INFINITE))
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
static int uv_cond_fallback_timedwait(uv_cond_t* cond,
|
||||
uv_mutex_t* mutex, uint64_t timeout) {
|
||||
return uv_cond_wait_helper(cond, mutex, (DWORD)(timeout / 1e6));
|
||||
}
|
||||
|
||||
|
||||
static int uv_cond_condvar_timedwait(uv_cond_t* cond,
|
||||
uv_mutex_t* mutex, uint64_t timeout) {
|
||||
if (pSleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6)))
|
||||
int uv_cond_timedwait(uv_cond_t* cond,
|
||||
uv_mutex_t* mutex,
|
||||
uint64_t timeout) {
|
||||
if (SleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6)))
|
||||
return 0;
|
||||
if (GetLastError() != ERROR_TIMEOUT)
|
||||
abort();
|
||||
@ -592,15 +392,6 @@ static int uv_cond_condvar_timedwait(uv_cond_t* cond,
|
||||
}
|
||||
|
||||
|
||||
int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex,
|
||||
uint64_t timeout) {
|
||||
if (HAVE_CONDVAR_API())
|
||||
return uv_cond_condvar_timedwait(cond, mutex, timeout);
|
||||
else
|
||||
return uv_cond_fallback_timedwait(cond, mutex, timeout);
|
||||
}
|
||||
|
||||
|
||||
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
|
||||
int err;
|
||||
|
||||
|
||||
@ -83,31 +83,29 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
if (pSetFileCompletionNotificationModes) {
|
||||
/* All known Windows that support SetFileCompletionNotificationModes */
|
||||
/* have a bug that makes it impossible to use this function in */
|
||||
/* conjunction with datagram sockets. We can work around that but only */
|
||||
/* if the user is using the default UDP driver (AFD) and has no other */
|
||||
/* LSPs stacked on top. Here we check whether that is the case. */
|
||||
opt_len = (int) sizeof info;
|
||||
if (getsockopt(socket,
|
||||
SOL_SOCKET,
|
||||
SO_PROTOCOL_INFOW,
|
||||
(char*) &info,
|
||||
&opt_len) == SOCKET_ERROR) {
|
||||
return GetLastError();
|
||||
}
|
||||
/* All known Windows that support SetFileCompletionNotificationModes */
|
||||
/* have a bug that makes it impossible to use this function in */
|
||||
/* conjunction with datagram sockets. We can work around that but only */
|
||||
/* if the user is using the default UDP driver (AFD) and has no other */
|
||||
/* LSPs stacked on top. Here we check whether that is the case. */
|
||||
opt_len = (int) sizeof info;
|
||||
if (getsockopt(socket,
|
||||
SOL_SOCKET,
|
||||
SO_PROTOCOL_INFOW,
|
||||
(char*) &info,
|
||||
&opt_len) == SOCKET_ERROR) {
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
if (info.ProtocolChain.ChainLen == 1) {
|
||||
if (pSetFileCompletionNotificationModes((HANDLE)socket,
|
||||
FILE_SKIP_SET_EVENT_ON_HANDLE |
|
||||
FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
|
||||
handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
|
||||
handle->func_wsarecv = uv_wsarecv_workaround;
|
||||
handle->func_wsarecvfrom = uv_wsarecvfrom_workaround;
|
||||
} else if (GetLastError() != ERROR_INVALID_FUNCTION) {
|
||||
return GetLastError();
|
||||
}
|
||||
if (info.ProtocolChain.ChainLen == 1) {
|
||||
if (SetFileCompletionNotificationModes((HANDLE)socket,
|
||||
FILE_SKIP_SET_EVENT_ON_HANDLE |
|
||||
FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
|
||||
handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
|
||||
handle->func_wsarecv = uv_wsarecv_workaround;
|
||||
handle->func_wsarecvfrom = uv_wsarecvfrom_workaround;
|
||||
} else if (GetLastError() != ERROR_INVALID_FUNCTION) {
|
||||
return GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,8 +248,7 @@ static int uv_udp_maybe_bind(uv_udp_t* handle,
|
||||
/* If the user doesn't specify it libuv turns it off. */
|
||||
|
||||
/* TODO: how to handle errors? This may fail if there is no ipv4 stack */
|
||||
/* available, or when run on XP/2003 which have no support for dualstack */
|
||||
/* sockets. For now we're silently ignoring the error. */
|
||||
/* available. For now we're silently ignoring the error. */
|
||||
setsockopt(handle->socket,
|
||||
IPPROTO_IPV6,
|
||||
IPV6_V6ONLY,
|
||||
|
||||
@ -728,37 +728,6 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
|
||||
}
|
||||
|
||||
|
||||
static int is_windows_version_or_greater(DWORD os_major,
|
||||
DWORD os_minor,
|
||||
WORD service_pack_major,
|
||||
WORD service_pack_minor) {
|
||||
OSVERSIONINFOEX osvi;
|
||||
DWORDLONG condition_mask = 0;
|
||||
int op = VER_GREATER_EQUAL;
|
||||
|
||||
/* Initialize the OSVERSIONINFOEX structure. */
|
||||
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
|
||||
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||
osvi.dwMajorVersion = os_major;
|
||||
osvi.dwMinorVersion = os_minor;
|
||||
osvi.wServicePackMajor = service_pack_major;
|
||||
osvi.wServicePackMinor = service_pack_minor;
|
||||
|
||||
/* Initialize the condition mask. */
|
||||
VER_SET_CONDITION(condition_mask, VER_MAJORVERSION, op);
|
||||
VER_SET_CONDITION(condition_mask, VER_MINORVERSION, op);
|
||||
VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMAJOR, op);
|
||||
VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMINOR, op);
|
||||
|
||||
/* Perform the test. */
|
||||
return (int) VerifyVersionInfo(
|
||||
&osvi,
|
||||
VER_MAJORVERSION | VER_MINORVERSION |
|
||||
VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
||||
condition_mask);
|
||||
}
|
||||
|
||||
|
||||
static int address_prefix_match(int family,
|
||||
struct sockaddr* address,
|
||||
struct sockaddr* prefix_address,
|
||||
@ -805,23 +774,11 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
|
||||
uv_interface_address_t* uv_address;
|
||||
|
||||
int count;
|
||||
|
||||
int is_vista_or_greater;
|
||||
ULONG flags;
|
||||
|
||||
is_vista_or_greater = is_windows_version_or_greater(6, 0, 0, 0);
|
||||
if (is_vista_or_greater) {
|
||||
flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
|
||||
GAA_FLAG_SKIP_DNS_SERVER;
|
||||
} else {
|
||||
/* We need at least XP SP1. */
|
||||
if (!is_windows_version_or_greater(5, 1, 1, 0))
|
||||
return UV_ENOTSUP;
|
||||
|
||||
flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
|
||||
GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_PREFIX;
|
||||
}
|
||||
|
||||
flags = GAA_FLAG_SKIP_ANYCAST |
|
||||
GAA_FLAG_SKIP_MULTICAST |
|
||||
GAA_FLAG_SKIP_DNS_SERVER;
|
||||
|
||||
/* Fetch the size of the adapters reported by windows, and then get the */
|
||||
/* list itself. */
|
||||
@ -985,37 +942,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
|
||||
|
||||
sa = unicast_address->Address.lpSockaddr;
|
||||
|
||||
/* XP has no OnLinkPrefixLength field. */
|
||||
if (is_vista_or_greater) {
|
||||
prefix_len =
|
||||
((IP_ADAPTER_UNICAST_ADDRESS_LH*) unicast_address)->OnLinkPrefixLength;
|
||||
} else {
|
||||
/* Prior to Windows Vista the FirstPrefix pointed to the list with
|
||||
* single prefix for each IP address assigned to the adapter.
|
||||
* Order of FirstPrefix does not match order of FirstUnicastAddress,
|
||||
* so we need to find corresponding prefix.
|
||||
*/
|
||||
IP_ADAPTER_PREFIX* prefix;
|
||||
prefix_len = 0;
|
||||
|
||||
for (prefix = adapter->FirstPrefix; prefix; prefix = prefix->Next) {
|
||||
/* We want the longest matching prefix. */
|
||||
if (prefix->Address.lpSockaddr->sa_family != sa->sa_family ||
|
||||
prefix->PrefixLength <= prefix_len)
|
||||
continue;
|
||||
|
||||
if (address_prefix_match(sa->sa_family, sa,
|
||||
prefix->Address.lpSockaddr, prefix->PrefixLength)) {
|
||||
prefix_len = prefix->PrefixLength;
|
||||
}
|
||||
}
|
||||
|
||||
/* If there is no matching prefix information, return a single-host
|
||||
* subnet mask (e.g. 255.255.255.255 for IPv4).
|
||||
*/
|
||||
if (!prefix_len)
|
||||
prefix_len = (sa->sa_family == AF_INET6) ? 128 : 32;
|
||||
}
|
||||
prefix_len =
|
||||
((IP_ADAPTER_UNICAST_ADDRESS_LH*) unicast_address)->OnLinkPrefixLength;
|
||||
|
||||
memset(uv_address, 0, sizeof *uv_address);
|
||||
|
||||
|
||||
@ -36,17 +36,6 @@ sNtQuerySystemInformation pNtQuerySystemInformation;
|
||||
|
||||
|
||||
/* Kernel32 function pointers */
|
||||
sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
|
||||
sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;
|
||||
sCreateSymbolicLinkW pCreateSymbolicLinkW;
|
||||
sCancelIoEx pCancelIoEx;
|
||||
sInitializeConditionVariable pInitializeConditionVariable;
|
||||
sSleepConditionVariableCS pSleepConditionVariableCS;
|
||||
sSleepConditionVariableSRW pSleepConditionVariableSRW;
|
||||
sWakeAllConditionVariable pWakeAllConditionVariable;
|
||||
sWakeConditionVariable pWakeConditionVariable;
|
||||
sCancelSynchronousIo pCancelSynchronousIo;
|
||||
sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
|
||||
|
||||
|
||||
void uv_winapi_init() {
|
||||
@ -110,37 +99,4 @@ void uv_winapi_init() {
|
||||
uv_fatal_error(GetLastError(), "GetModuleHandleA");
|
||||
}
|
||||
|
||||
pGetQueuedCompletionStatusEx = (sGetQueuedCompletionStatusEx) GetProcAddress(
|
||||
kernel32_module,
|
||||
"GetQueuedCompletionStatusEx");
|
||||
|
||||
pSetFileCompletionNotificationModes = (sSetFileCompletionNotificationModes)
|
||||
GetProcAddress(kernel32_module, "SetFileCompletionNotificationModes");
|
||||
|
||||
pCreateSymbolicLinkW = (sCreateSymbolicLinkW)
|
||||
GetProcAddress(kernel32_module, "CreateSymbolicLinkW");
|
||||
|
||||
pCancelIoEx = (sCancelIoEx)
|
||||
GetProcAddress(kernel32_module, "CancelIoEx");
|
||||
|
||||
pInitializeConditionVariable = (sInitializeConditionVariable)
|
||||
GetProcAddress(kernel32_module, "InitializeConditionVariable");
|
||||
|
||||
pSleepConditionVariableCS = (sSleepConditionVariableCS)
|
||||
GetProcAddress(kernel32_module, "SleepConditionVariableCS");
|
||||
|
||||
pSleepConditionVariableSRW = (sSleepConditionVariableSRW)
|
||||
GetProcAddress(kernel32_module, "SleepConditionVariableSRW");
|
||||
|
||||
pWakeAllConditionVariable = (sWakeAllConditionVariable)
|
||||
GetProcAddress(kernel32_module, "WakeAllConditionVariable");
|
||||
|
||||
pWakeConditionVariable = (sWakeConditionVariable)
|
||||
GetProcAddress(kernel32_module, "WakeConditionVariable");
|
||||
|
||||
pCancelSynchronousIo = (sCancelSynchronousIo)
|
||||
GetProcAddress(kernel32_module, "CancelSynchronousIo");
|
||||
|
||||
pGetFinalPathNameByHandleW = (sGetFinalPathNameByHandleW)
|
||||
GetProcAddress(kernel32_module, "GetFinalPathNameByHandleW");
|
||||
}
|
||||
|
||||
@ -4634,56 +4634,6 @@ typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile)
|
||||
# define ERROR_MUI_FILE_NOT_LOADED 15105
|
||||
#endif
|
||||
|
||||
typedef BOOL (WINAPI *sGetQueuedCompletionStatusEx)
|
||||
(HANDLE CompletionPort,
|
||||
LPOVERLAPPED_ENTRY lpCompletionPortEntries,
|
||||
ULONG ulCount,
|
||||
PULONG ulNumEntriesRemoved,
|
||||
DWORD dwMilliseconds,
|
||||
BOOL fAlertable);
|
||||
|
||||
typedef BOOL (WINAPI* sSetFileCompletionNotificationModes)
|
||||
(HANDLE FileHandle,
|
||||
UCHAR Flags);
|
||||
|
||||
typedef BOOLEAN (WINAPI* sCreateSymbolicLinkW)
|
||||
(LPCWSTR lpSymlinkFileName,
|
||||
LPCWSTR lpTargetFileName,
|
||||
DWORD dwFlags);
|
||||
|
||||
typedef BOOL (WINAPI* sCancelIoEx)
|
||||
(HANDLE hFile,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
|
||||
typedef VOID (WINAPI* sInitializeConditionVariable)
|
||||
(PCONDITION_VARIABLE ConditionVariable);
|
||||
|
||||
typedef BOOL (WINAPI* sSleepConditionVariableCS)
|
||||
(PCONDITION_VARIABLE ConditionVariable,
|
||||
PCRITICAL_SECTION CriticalSection,
|
||||
DWORD dwMilliseconds);
|
||||
|
||||
typedef BOOL (WINAPI* sSleepConditionVariableSRW)
|
||||
(PCONDITION_VARIABLE ConditionVariable,
|
||||
PSRWLOCK SRWLock,
|
||||
DWORD dwMilliseconds,
|
||||
ULONG Flags);
|
||||
|
||||
typedef VOID (WINAPI* sWakeAllConditionVariable)
|
||||
(PCONDITION_VARIABLE ConditionVariable);
|
||||
|
||||
typedef VOID (WINAPI* sWakeConditionVariable)
|
||||
(PCONDITION_VARIABLE ConditionVariable);
|
||||
|
||||
typedef BOOL (WINAPI* sCancelSynchronousIo)
|
||||
(HANDLE hThread);
|
||||
|
||||
typedef DWORD (WINAPI* sGetFinalPathNameByHandleW)
|
||||
(HANDLE hFile,
|
||||
LPWSTR lpszFilePath,
|
||||
DWORD cchFilePath,
|
||||
DWORD dwFlags);
|
||||
|
||||
/* Ntdll function pointers */
|
||||
extern sRtlNtStatusToDosError pRtlNtStatusToDosError;
|
||||
extern sNtDeviceIoControlFile pNtDeviceIoControlFile;
|
||||
@ -4695,16 +4645,6 @@ extern sNtQuerySystemInformation pNtQuerySystemInformation;
|
||||
|
||||
|
||||
/* Kernel32 function pointers */
|
||||
extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
|
||||
extern sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;
|
||||
extern sCreateSymbolicLinkW pCreateSymbolicLinkW;
|
||||
extern sCancelIoEx pCancelIoEx;
|
||||
extern sInitializeConditionVariable pInitializeConditionVariable;
|
||||
extern sSleepConditionVariableCS pSleepConditionVariableCS;
|
||||
extern sSleepConditionVariableSRW pSleepConditionVariableSRW;
|
||||
extern sWakeAllConditionVariable pWakeAllConditionVariable;
|
||||
extern sWakeConditionVariable pWakeConditionVariable;
|
||||
extern sCancelSynchronousIo pCancelSynchronousIo;
|
||||
extern sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
|
||||
|
||||
|
||||
#endif /* UV_WIN_WINAPI_H_ */
|
||||
|
||||
@ -173,16 +173,6 @@ static void realpath_cb(uv_fs_t* req) {
|
||||
char test_file_abs_buf[PATHMAX];
|
||||
size_t test_file_abs_size = sizeof(test_file_abs_buf);
|
||||
ASSERT(req->fs_type == UV_FS_REALPATH);
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
|
||||
*/
|
||||
if (req->result == UV_ENOSYS) {
|
||||
realpath_cb_count++;
|
||||
uv_fs_req_cleanup(req);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ASSERT(req->result == 0);
|
||||
|
||||
uv_cwd(test_file_abs_buf, &test_file_abs_size);
|
||||
@ -623,11 +613,10 @@ TEST_IMPL(fs_file_loop) {
|
||||
r = uv_fs_symlink(NULL, &req, "test_symlink", "test_symlink", 0, NULL);
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* Windows XP and Server 2003 don't support symlinks; we'll get UV_ENOTSUP.
|
||||
* Starting with vista they are supported, but only when elevated, otherwise
|
||||
* we'll see UV_EPERM.
|
||||
* Starting with Windows Vista symlinks are supported, but only when
|
||||
* elevated, otherwise we'll see UV_EPERM.
|
||||
*/
|
||||
if (r == UV_ENOTSUP || r == UV_EPERM)
|
||||
if (r == UV_EPERM)
|
||||
return 0;
|
||||
#endif
|
||||
ASSERT(r == 0);
|
||||
@ -1603,15 +1592,6 @@ TEST_IMPL(fs_realpath) {
|
||||
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||
ASSERT(dummy_cb_count == 1);
|
||||
ASSERT(req.ptr == NULL);
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
|
||||
*/
|
||||
if (req.result == UV_ENOSYS) {
|
||||
uv_fs_req_cleanup(&req);
|
||||
RETURN_SKIP("realpath is not supported on Windows XP");
|
||||
}
|
||||
#endif
|
||||
ASSERT(req.result == UV_ENOENT);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
@ -1718,15 +1698,6 @@ TEST_IMPL(fs_symlink) {
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
r = uv_fs_realpath(NULL, &req, "test_file_symlink_symlink", NULL);
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
|
||||
*/
|
||||
if (r == UV_ENOSYS) {
|
||||
uv_fs_req_cleanup(&req);
|
||||
RETURN_SKIP("realpath is not supported on Windows XP");
|
||||
}
|
||||
#endif
|
||||
ASSERT(r == 0);
|
||||
#ifdef _WIN32
|
||||
ASSERT(stricmp(req.ptr, test_file_abs_buf) == 0);
|
||||
@ -1776,15 +1747,6 @@ TEST_IMPL(fs_symlink) {
|
||||
ASSERT(readlink_cb_count == 1);
|
||||
|
||||
r = uv_fs_realpath(loop, &req, "test_file", realpath_cb);
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
|
||||
*/
|
||||
if (r == UV_ENOSYS) {
|
||||
uv_fs_req_cleanup(&req);
|
||||
RETURN_SKIP("realpath is not supported on Windows XP");
|
||||
}
|
||||
#endif
|
||||
ASSERT(r == 0);
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
ASSERT(realpath_cb_count == 1);
|
||||
@ -1873,15 +1835,6 @@ TEST_IMPL(fs_symlink_dir) {
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
r = uv_fs_realpath(NULL, &req, "test_dir_symlink", NULL);
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
|
||||
*/
|
||||
if (r == UV_ENOSYS) {
|
||||
uv_fs_req_cleanup(&req);
|
||||
RETURN_SKIP("realpath is not supported on Windows XP");
|
||||
}
|
||||
#endif
|
||||
ASSERT(r == 0);
|
||||
#ifdef _WIN32
|
||||
ASSERT(strlen(req.ptr) == test_dir_abs_size - 5);
|
||||
|
||||
@ -1178,9 +1178,8 @@ TEST_IMPL(environment_creation) {
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
if (prev) { /* verify sort order -- requires Vista */
|
||||
#if _WIN32_WINNT >= 0x0600 && \
|
||||
(!defined(__MINGW32__) || defined(__MINGW64_VERSION_MAJOR))
|
||||
if (prev) { /* verify sort order */
|
||||
#if !defined(__MINGW32__) || defined(__MINGW64_VERSION_MAJOR)
|
||||
ASSERT(CompareStringOrdinal(prev, -1, str, -1, TRUE) == 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user