summaryrefslogtreecommitdiffstats
path: root/Utilities/cmlibuv/src/win
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2020-09-24 19:15:38 (GMT)
committerKitware Robot <kwrobot@kitware.com>2020-09-24 19:16:28 (GMT)
commitc98ec731f90eb0180c89108b7d2e42263b66d1ed (patch)
tree2d67994bbea44ba6712e6dcb637438f6dbfb0ac6 /Utilities/cmlibuv/src/win
parent0436f70f80de4a56313b9da0668ac6674078b2d1 (diff)
parent7a0506bafe387bfff441c0159b9a3d58f68db177 (diff)
downloadCMake-c98ec731f90eb0180c89108b7d2e42263b66d1ed.zip
CMake-c98ec731f90eb0180c89108b7d2e42263b66d1ed.tar.gz
CMake-c98ec731f90eb0180c89108b7d2e42263b66d1ed.tar.bz2
Merge topic 'update-libuv'
7a0506bafe libuv: Suppress conversion warning on Windows 2269ad6a0a libuv: Add fs_copy stub to cmake-bootstrap.c e21325c2c6 Merge branch 'upstream-libuv' into update-libuv c1463f959f libuv 2020-09-22 (ed5b42d5) Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !5259
Diffstat (limited to 'Utilities/cmlibuv/src/win')
-rw-r--r--Utilities/cmlibuv/src/win/core.c91
-rw-r--r--Utilities/cmlibuv/src/win/detect-wakeup.c21
-rw-r--r--Utilities/cmlibuv/src/win/fs-fd-hash-inl.h24
-rw-r--r--Utilities/cmlibuv/src/win/fs.c93
-rw-r--r--Utilities/cmlibuv/src/win/internal.h2
-rw-r--r--Utilities/cmlibuv/src/win/pipe.c12
-rw-r--r--Utilities/cmlibuv/src/win/tcp.c62
-rw-r--r--Utilities/cmlibuv/src/win/tty.c15
-rw-r--r--Utilities/cmlibuv/src/win/udp.c16
-rw-r--r--Utilities/cmlibuv/src/win/util.c34
-rw-r--r--Utilities/cmlibuv/src/win/winapi.h12
11 files changed, 300 insertions, 82 deletions
diff --git a/Utilities/cmlibuv/src/win/core.c b/Utilities/cmlibuv/src/win/core.c
index 9974a11..e53a0f8 100644
--- a/Utilities/cmlibuv/src/win/core.c
+++ b/Utilities/cmlibuv/src/win/core.c
@@ -222,6 +222,7 @@ static void uv_init(void) {
int uv_loop_init(uv_loop_t* loop) {
+ uv__loop_internal_fields_t* lfields;
struct heap* timer_heap;
int err;
@@ -233,6 +234,15 @@ int uv_loop_init(uv_loop_t* loop) {
if (loop->iocp == NULL)
return uv_translate_sys_error(GetLastError());
+ lfields = (uv__loop_internal_fields_t*) uv__calloc(1, sizeof(*lfields));
+ if (lfields == NULL)
+ return UV_ENOMEM;
+ loop->internal_fields = lfields;
+
+ err = uv_mutex_init(&lfields->loop_metrics.lock);
+ if (err)
+ goto fail_metrics_mutex_init;
+
/* To prevent uninitialized memory access, loop->time must be initialized
* to zero before calling uv_update_time for the first time.
*/
@@ -297,6 +307,11 @@ fail_mutex_init:
loop->timer_heap = NULL;
fail_timers_alloc:
+ uv_mutex_destroy(&lfields->loop_metrics.lock);
+
+fail_metrics_mutex_init:
+ uv__free(lfields);
+ loop->internal_fields = NULL;
CloseHandle(loop->iocp);
loop->iocp = INVALID_HANDLE_VALUE;
@@ -317,6 +332,7 @@ void uv__once_init(void) {
void uv__loop_close(uv_loop_t* loop) {
+ uv__loop_internal_fields_t* lfields;
size_t i;
uv__loops_remove(loop);
@@ -347,11 +363,24 @@ void uv__loop_close(uv_loop_t* loop) {
uv__free(loop->timer_heap);
loop->timer_heap = NULL;
+ lfields = uv__get_internal_fields(loop);
+ uv_mutex_destroy(&lfields->loop_metrics.lock);
+ uv__free(lfields);
+ loop->internal_fields = NULL;
+
CloseHandle(loop->iocp);
}
int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) {
+ uv__loop_internal_fields_t* lfields;
+
+ lfields = uv__get_internal_fields(loop);
+ if (option == UV_METRICS_IDLE_TIME) {
+ lfields->flags |= UV_METRICS_IDLE_TIME;
+ return 0;
+ }
+
return UV_ENOSYS;
}
@@ -393,16 +422,44 @@ static void uv__poll_wine(uv_loop_t* loop, DWORD timeout) {
uv_req_t* req;
int repeat;
uint64_t timeout_time;
+ uint64_t user_timeout;
+ int reset_timeout;
timeout_time = loop->time + timeout;
+ if (uv__get_internal_fields(loop)->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);
+
GetQueuedCompletionStatus(loop->iocp,
&bytes,
&key,
&overlapped,
timeout);
+ if (reset_timeout != 0) {
+ 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) {
/* Package was dequeued */
req = uv_overlapped_to_req(overlapped);
@@ -445,10 +502,26 @@ static void uv__poll(uv_loop_t* loop, DWORD timeout) {
ULONG i;
int repeat;
uint64_t timeout_time;
+ uint64_t user_timeout;
+ int reset_timeout;
timeout_time = loop->time + timeout;
+ if (uv__get_internal_fields(loop)->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);
+
success = pGetQueuedCompletionStatusEx(loop->iocp,
overlappeds,
ARRAY_SIZE(overlappeds),
@@ -456,6 +529,18 @@ static void uv__poll(uv_loop_t* loop, DWORD timeout) {
timeout,
FALSE);
+ if (reset_timeout != 0) {
+ 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 (success) {
for (i = 0; i < count; i++) {
/* Package was dequeued, but see if it is not a empty package
@@ -534,6 +619,12 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
else
uv__poll_wine(loop, timeout);
+ /* Run one final update on the provider_idle_time in case uv__poll*
+ * returned because the timeout expired, but no events were received. This
+ * call will be ignored if the provider_entry_time was either never set (if
+ * the timeout == 0) or was already updated b/c an event was received.
+ */
+ uv__metrics_update_idle_time(loop);
uv_check_invoke(loop);
uv_process_endgames(loop);
diff --git a/Utilities/cmlibuv/src/win/detect-wakeup.c b/Utilities/cmlibuv/src/win/detect-wakeup.c
index 72dfb7a..ab19361 100644
--- a/Utilities/cmlibuv/src/win/detect-wakeup.c
+++ b/Utilities/cmlibuv/src/win/detect-wakeup.c
@@ -1,3 +1,24 @@
+/* Copyright libuv project 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.
+ */
+
#include "uv.h"
#include "internal.h"
#include "winapi.h"
diff --git a/Utilities/cmlibuv/src/win/fs-fd-hash-inl.h b/Utilities/cmlibuv/src/win/fs-fd-hash-inl.h
index 7a203d2..0b532af 100644
--- a/Utilities/cmlibuv/src/win/fs-fd-hash-inl.h
+++ b/Utilities/cmlibuv/src/win/fs-fd-hash-inl.h
@@ -1,3 +1,24 @@
+/* Copyright libuv project 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_FS_FD_HASH_INL_H_
#define UV_WIN_FS_FD_HASH_INL_H_
@@ -53,7 +74,8 @@ static struct uv__fd_hash_bucket_s uv__fd_hash[UV__FD_HASH_SIZE];
INLINE static void uv__fd_hash_init(void) {
- int i, err;
+ size_t i;
+ int err;
err = uv_mutex_init(&uv__fd_hash_mutex);
if (err) {
diff --git a/Utilities/cmlibuv/src/win/fs.c b/Utilities/cmlibuv/src/win/fs.c
index 9577bc0..d6ff7ed 100644
--- a/Utilities/cmlibuv/src/win/fs.c
+++ b/Utilities/cmlibuv/src/win/fs.c
@@ -70,10 +70,7 @@
#define SET_REQ_RESULT(req, result_value) \
do { \
req->result = (result_value); \
- if (req->result == -1) { \
- req->sys_errno_ = _doserrno; \
- req->result = uv_translate_sys_error(req->sys_errno_); \
- } \
+ assert(req->result != -1); \
} while (0)
#define SET_REQ_WIN32_ERROR(req, sys_errno) \
@@ -730,14 +727,14 @@ void fs__close(uv_fs_t* req) {
assert(errno == EBADF);
SET_REQ_UV_ERROR(req, UV_EBADF, ERROR_INVALID_HANDLE);
} else {
- req->result = 0;
+ SET_REQ_RESULT(req, 0);
}
}
LONG fs__filemap_ex_filter(LONG excode, PEXCEPTION_POINTERS pep,
int* perror) {
- if (excode != EXCEPTION_IN_PAGE_ERROR) {
+ if (excode != (LONG)EXCEPTION_IN_PAGE_ERROR) {
return EXCEPTION_CONTINUE_SEARCH;
}
@@ -816,10 +813,10 @@ void fs__read_filemap(uv_fs_t* req, struct uv__fd_info_s* fd_info) {
for (index = 0;
index < req->fs.info.nbufs && done_read < read_size;
++index) {
- int err = 0;
size_t this_read_size = MIN(req->fs.info.bufs[index].len,
read_size - done_read);
#ifdef _MSC_VER
+ int err = 0;
__try {
#endif
memcpy(req->fs.info.bufs[index].base,
@@ -938,7 +935,7 @@ void fs__write_filemap(uv_fs_t* req, HANDLE file,
(UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR);
size_t write_size, done_write;
unsigned int index;
- LARGE_INTEGER zero, pos, end_pos;
+ LARGE_INTEGER pos, end_pos;
size_t view_offset;
LARGE_INTEGER view_base;
void* view;
@@ -963,7 +960,6 @@ void fs__write_filemap(uv_fs_t* req, HANDLE file,
return;
}
- zero.QuadPart = 0;
if (force_append) {
pos = fd_info->size;
} else if (req->fs.info.offset == -1) {
@@ -1014,8 +1010,8 @@ void fs__write_filemap(uv_fs_t* req, HANDLE file,
done_write = 0;
for (index = 0; index < req->fs.info.nbufs; ++index) {
- int err = 0;
#ifdef _MSC_VER
+ int err = 0;
__try {
#endif
memcpy((char*)view + view_offset + done_write,
@@ -1128,7 +1124,10 @@ void fs__write(uv_fs_t* req) {
void fs__rmdir(uv_fs_t* req) {
int result = _wrmdir(req->file.pathw);
- SET_REQ_RESULT(req, result);
+ if (result == -1)
+ SET_REQ_WIN32_ERROR(req, _doserrno);
+ else
+ SET_REQ_RESULT(req, 0);
}
@@ -1221,12 +1220,12 @@ void fs__unlink(uv_fs_t* req) {
void fs__mkdir(uv_fs_t* req) {
/* TODO: use req->mode. */
- req->result = _wmkdir(req->file.pathw);
- if (req->result == -1) {
- req->sys_errno_ = _doserrno;
- req->result = req->sys_errno_ == ERROR_INVALID_NAME
- ? UV_EINVAL
- : uv_translate_sys_error(req->sys_errno_);
+ if (CreateDirectoryW(req->file.pathw, NULL)) {
+ SET_REQ_RESULT(req, 0);
+ } else {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ if (req->sys_errno_ == ERROR_INVALID_NAME)
+ req->result = UV_EINVAL;
}
}
@@ -1242,19 +1241,21 @@ void fs__mktemp(uv_fs_t* req, uv__fs_mktemp_func func) {
unsigned int tries, i;
size_t len;
uint64_t v;
-
+ char* path;
+
+ path = (char*)req->path;
len = wcslen(req->file.pathw);
ep = req->file.pathw + len;
if (len < num_x || wcsncmp(ep - num_x, L"XXXXXX", num_x)) {
SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
- return;
+ goto clobber;
}
tries = TMP_MAX;
do {
if (uv__random_rtlgenrandom((void *)&v, sizeof(v)) < 0) {
SET_REQ_UV_ERROR(req, UV_EIO, ERROR_IO_DEVICE);
- break;
+ goto clobber;
}
cp = ep - num_x;
@@ -1265,25 +1266,29 @@ void fs__mktemp(uv_fs_t* req, uv__fs_mktemp_func func) {
if (func(req)) {
if (req->result >= 0) {
- len = strlen(req->path);
- wcstombs((char*) req->path + len - num_x, ep - num_x, num_x);
+ len = strlen(path);
+ wcstombs(path + len - num_x, ep - num_x, num_x);
}
- break;
+ return;
}
} while (--tries);
- if (tries == 0) {
- SET_REQ_RESULT(req, -1);
- }
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+
+clobber:
+ path[0] = '\0';
}
static int fs__mkdtemp_func(uv_fs_t* req) {
- if (_wmkdir(req->file.pathw) == 0) {
+ DWORD error;
+ if (CreateDirectoryW(req->file.pathw, NULL)) {
SET_REQ_RESULT(req, 0);
return 1;
- } else if (errno != EEXIST) {
- SET_REQ_RESULT(req, -1);
+ }
+ error = GetLastError();
+ if (error != ERROR_ALREADY_EXISTS) {
+ SET_REQ_WIN32_ERROR(req, error);
return 1;
}
@@ -1404,7 +1409,7 @@ void fs__scandir(uv_fs_t* req) {
/* If the handle is not a directory, we'll get STATUS_INVALID_PARAMETER.
* This should be reported back as UV_ENOTDIR.
*/
- if (status == STATUS_INVALID_PARAMETER)
+ if (status == (NTSTATUS)STATUS_INVALID_PARAMETER)
goto not_a_directory_error;
while (NT_SUCCESS(status)) {
@@ -1895,7 +1900,7 @@ INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) {
}
req->ptr = &req->statbuf;
- req->result = 0;
+ SET_REQ_RESULT(req, 0);
}
@@ -1930,7 +1935,7 @@ static void fs__fstat(uv_fs_t* req) {
}
req->ptr = &req->statbuf;
- req->result = 0;
+ SET_REQ_RESULT(req, 0);
}
@@ -2157,7 +2162,10 @@ static void fs__access(uv_fs_t* req) {
static void fs__chmod(uv_fs_t* req) {
int result = _wchmod(req->file.pathw, req->fs.info.mode);
- SET_REQ_RESULT(req, result);
+ if (result == -1)
+ SET_REQ_WIN32_ERROR(req, _doserrno);
+ else
+ SET_REQ_RESULT(req, 0);
}
@@ -2315,7 +2323,7 @@ INLINE static void fs__utime_impl(uv_fs_t* req, int do_lutime) {
return;
}
- req->result = 0;
+ SET_REQ_RESULT(req, 0);
}
static void fs__utime(uv_fs_t* req) {
@@ -2340,7 +2348,7 @@ static void fs__futime(uv_fs_t* req) {
return;
}
- req->result = 0;
+ SET_REQ_RESULT(req, 0);
}
static void fs__lutime(uv_fs_t* req) {
@@ -2350,11 +2358,10 @@ static void fs__lutime(uv_fs_t* req) {
static void fs__link(uv_fs_t* req) {
DWORD r = CreateHardLinkW(req->fs.info.new_pathw, req->file.pathw, NULL);
- if (r == 0) {
+ if (r == 0)
SET_REQ_WIN32_ERROR(req, GetLastError());
- } else {
- req->result = 0;
- }
+ else
+ SET_REQ_RESULT(req, 0);
}
@@ -2674,17 +2681,17 @@ static void fs__realpath(uv_fs_t* req) {
static void fs__chown(uv_fs_t* req) {
- req->result = 0;
+ SET_REQ_RESULT(req, 0);
}
static void fs__fchown(uv_fs_t* req) {
- req->result = 0;
+ SET_REQ_RESULT(req, 0);
}
static void fs__lchown(uv_fs_t* req) {
- req->result = 0;
+ SET_REQ_RESULT(req, 0);
}
@@ -2829,7 +2836,7 @@ static void uv__fs_done(struct uv__work* w, int status) {
if (status == UV_ECANCELED) {
assert(req->result == 0);
- req->result = UV_ECANCELED;
+ SET_REQ_UV_ERROR(req, UV_ECANCELED, 0);
}
req->cb(req);
diff --git a/Utilities/cmlibuv/src/win/internal.h b/Utilities/cmlibuv/src/win/internal.h
index 463ef33..3f56777 100644
--- a/Utilities/cmlibuv/src/win/internal.h
+++ b/Utilities/cmlibuv/src/win/internal.h
@@ -270,7 +270,7 @@ void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle);
*/
void uv__util_init(void);
-uint64_t uv__hrtime(double scale);
+uint64_t uv__hrtime(unsigned int scale);
__declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall);
int uv__getpwuid_r(uv_passwd_t* pwd);
int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8);
diff --git a/Utilities/cmlibuv/src/win/pipe.c b/Utilities/cmlibuv/src/win/pipe.c
index fc0112a..f81245e 100644
--- a/Utilities/cmlibuv/src/win/pipe.c
+++ b/Utilities/cmlibuv/src/win/pipe.c
@@ -244,9 +244,8 @@ int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
return 0;
error:
- if (pipeHandle != INVALID_HANDLE_VALUE) {
+ if (pipeHandle != INVALID_HANDLE_VALUE)
CloseHandle(pipeHandle);
- }
return err;
}
@@ -554,7 +553,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
/* Convert name to UTF16. */
nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR);
- handle->name = (WCHAR*)uv__malloc(nameSize);
+ handle->name = uv__malloc(nameSize);
if (!handle->name) {
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
@@ -621,9 +620,8 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
while (WaitNamedPipeW(handle->name, 30000)) {
/* The pipe is now available, try to connect. */
pipeHandle = open_named_pipe(handle->name, &duplex_flags);
- if (pipeHandle != INVALID_HANDLE_VALUE) {
+ if (pipeHandle != INVALID_HANDLE_VALUE)
break;
- }
SwitchToThread();
}
@@ -655,7 +653,7 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
/* Convert name to UTF16. */
nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR);
- handle->name = (WCHAR*)uv__malloc(nameSize);
+ handle->name = uv__malloc(nameSize);
if (!handle->name) {
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
@@ -2147,7 +2145,7 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
if (pipe->ipc) {
assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE));
pipe->pipe.conn.ipc_remote_pid = uv_os_getppid();
- assert(pipe->pipe.conn.ipc_remote_pid != (DWORD) -1);
+ assert(pipe->pipe.conn.ipc_remote_pid != (DWORD)(uv_pid_t) -1);
}
return 0;
}
diff --git a/Utilities/cmlibuv/src/win/tcp.c b/Utilities/cmlibuv/src/win/tcp.c
index 941c801..0dcaa97 100644
--- a/Utilities/cmlibuv/src/win/tcp.c
+++ b/Utilities/cmlibuv/src/win/tcp.c
@@ -523,16 +523,15 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) {
&req->u.io.overlapped,
NULL);
+ handle->flags |= UV_HANDLE_READ_PENDING;
+ handle->reqs_pending++;
+
if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
/* Process the req without IOCP. */
- handle->flags |= UV_HANDLE_READ_PENDING;
req->u.io.overlapped.InternalHigh = bytes;
- handle->reqs_pending++;
uv_insert_pending_req(loop, (uv_req_t*)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++;
if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
req->wait_handle == INVALID_HANDLE_VALUE &&
!RegisterWaitForSingleObject(&req->wait_handle,
@@ -545,7 +544,6 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) {
/* Make this req pending reporting an error. */
SET_REQ_ERROR(req, WSAGetLastError());
uv_insert_pending_req(loop, (uv_req_t*)req);
- handle->reqs_pending++;
}
}
@@ -750,6 +748,40 @@ int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
return 0;
}
+static int uv__is_loopback(const struct sockaddr_storage* storage) {
+ const struct sockaddr_in* in4;
+ const struct sockaddr_in6* in6;
+ int i;
+
+ if (storage->ss_family == AF_INET) {
+ in4 = (const struct sockaddr_in*) storage;
+ return in4->sin_addr.S_un.S_un_b.s_b1 == 127;
+ }
+ if (storage->ss_family == AF_INET6) {
+ in6 = (const struct sockaddr_in6*) storage;
+ for (i = 0; i < 7; ++i) {
+ if (in6->sin6_addr.u.Word[i] != 0)
+ return 0;
+ }
+ return in6->sin6_addr.u.Word[7] == htons(1);
+ }
+ return 0;
+}
+
+// Check if Windows version is 10.0.16299 or later
+static int uv__is_fast_loopback_fail_supported() {
+ OSVERSIONINFOW os_info;
+ if (!pRtlGetVersion)
+ return 0;
+ pRtlGetVersion(&os_info);
+ if (os_info.dwMajorVersion < 10)
+ return 0;
+ if (os_info.dwMajorVersion > 10)
+ return 1;
+ if (os_info.dwMinorVersion > 0)
+ return 1;
+ return os_info.dwBuildNumber >= 16299;
+}
static int uv_tcp_try_connect(uv_connect_t* req,
uv_tcp_t* handle,
@@ -757,6 +789,7 @@ static int uv_tcp_try_connect(uv_connect_t* req,
unsigned int addrlen,
uv_connect_cb cb) {
uv_loop_t* loop = handle->loop;
+ TCP_INITIAL_RTO_PARAMETERS retransmit_ioctl;
const struct sockaddr* bind_addr;
struct sockaddr_storage converted;
BOOL success;
@@ -792,6 +825,25 @@ static int uv_tcp_try_connect(uv_connect_t* req,
}
}
+ /* This makes connect() fail instantly if the target port on the localhost
+ * is not reachable, instead of waiting for 2s. We do not care if this fails.
+ * This only works on Windows version 10.0.16299 and later.
+ */
+ if (uv__is_fast_loopback_fail_supported() && uv__is_loopback(&converted)) {
+ memset(&retransmit_ioctl, 0, sizeof(retransmit_ioctl));
+ retransmit_ioctl.Rtt = TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS;
+ retransmit_ioctl.MaxSynRetransmissions = TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS;
+ WSAIoctl(handle->socket,
+ SIO_TCP_INITIAL_RTO,
+ &retransmit_ioctl,
+ sizeof(retransmit_ioctl),
+ NULL,
+ 0,
+ &bytes,
+ NULL,
+ NULL);
+ }
+
UV_REQ_INIT(req, UV_CONNECT);
req->handle = (uv_stream_t*) handle;
req->cb = cb;
diff --git a/Utilities/cmlibuv/src/win/tty.c b/Utilities/cmlibuv/src/win/tty.c
index 488d9b2..1b9d4f8 100644
--- a/Utilities/cmlibuv/src/win/tty.c
+++ b/Utilities/cmlibuv/src/win/tty.c
@@ -517,6 +517,7 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) {
status = InterlockedExchange(&uv__read_console_status, IN_PROGRESS);
if (status == TRAP_REQUESTED) {
SET_REQ_SUCCESS(req);
+ InterlockedExchange(&uv__read_console_status, COMPLETED);
req->u.io.overlapped.InternalHigh = 0;
POST_COMPLETION_FOR_REQ(loop, req);
return 0;
@@ -2121,13 +2122,6 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
abort();
}
- /* We wouldn't mind emitting utf-16 surrogate pairs. Too bad, the windows
- * console doesn't really support UTF-16, so just emit the replacement
- * character. */
- if (utf8_codepoint > 0xffff) {
- utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;
- }
-
if (utf8_codepoint == 0x0a || utf8_codepoint == 0x0d) {
/* EOL conversion - emit \r\n when we see \n. */
@@ -2154,6 +2148,12 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
ENSURE_BUFFER_SPACE(1);
utf16_buf[utf16_buf_used++] = (WCHAR) utf8_codepoint;
previous_eol = 0;
+ } else {
+ ENSURE_BUFFER_SPACE(2);
+ utf8_codepoint -= 0x10000;
+ utf16_buf[utf16_buf_used++] = (WCHAR) (utf8_codepoint / 0x400 + 0xD800);
+ utf16_buf[utf16_buf_used++] = (WCHAR) (utf8_codepoint % 0x400 + 0xDC00);
+ previous_eol = 0;
}
}
}
@@ -2412,6 +2412,7 @@ static DWORD WINAPI uv__tty_console_resize_watcher_thread(void* param) {
uv__tty_console_signal_resize();
ResetEvent(uv__tty_console_resized);
}
+ return 0;
}
static void uv__tty_console_signal_resize(void) {
diff --git a/Utilities/cmlibuv/src/win/udp.c b/Utilities/cmlibuv/src/win/udp.c
index 508ed37..68ca728 100644
--- a/Utilities/cmlibuv/src/win/udp.c
+++ b/Utilities/cmlibuv/src/win/udp.c
@@ -189,6 +189,11 @@ void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) {
}
+int uv_udp_using_recvmmsg(const uv_udp_t* handle) {
+ return 0;
+}
+
+
static int uv_udp_maybe_bind(uv_udp_t* handle,
const struct sockaddr* addr,
unsigned int addrlen,
@@ -752,6 +757,9 @@ int uv__udp_set_source_membership6(uv_udp_t* handle,
int optname;
int err;
+ STATIC_ASSERT(sizeof(mreq.gsr_group) >= sizeof(*multicast_addr));
+ STATIC_ASSERT(sizeof(mreq.gsr_source) >= sizeof(*source_addr));
+
if ((handle->flags & UV_HANDLE_BOUND) && !(handle->flags & UV_HANDLE_IPV6))
return UV_EINVAL;
@@ -774,8 +782,8 @@ int uv__udp_set_source_membership6(uv_udp_t* handle,
mreq.gsr_interface = 0;
}
- memcpy(&mreq.gsr_group, multicast_addr, sizeof(mreq.gsr_group));
- memcpy(&mreq.gsr_source, source_addr, sizeof(mreq.gsr_source));
+ memcpy(&mreq.gsr_group, multicast_addr, sizeof(*multicast_addr));
+ memcpy(&mreq.gsr_source, source_addr, sizeof(*source_addr));
if (membership == UV_JOIN_GROUP)
optname = MCAST_JOIN_SOURCE_GROUP;
@@ -1065,7 +1073,7 @@ int uv__udp_connect(uv_udp_t* handle,
err = connect(handle->socket, addr, addrlen);
if (err)
- return uv_translate_sys_error(err);
+ return uv_translate_sys_error(WSAGetLastError());
handle->flags |= UV_HANDLE_UDP_CONNECTED;
@@ -1081,7 +1089,7 @@ int uv__udp_disconnect(uv_udp_t* handle) {
err = connect(handle->socket, &addr, sizeof(addr));
if (err)
- return uv_translate_sys_error(err);
+ return uv_translate_sys_error(WSAGetLastError());
handle->flags &= ~UV_HANDLE_UDP_CONNECTED;
return 0;
diff --git a/Utilities/cmlibuv/src/win/util.c b/Utilities/cmlibuv/src/win/util.c
index 9e1e7f7..aad8f1a 100644
--- a/Utilities/cmlibuv/src/win/util.c
+++ b/Utilities/cmlibuv/src/win/util.c
@@ -30,12 +30,14 @@
#include "uv.h"
#include "internal.h"
+/* clang-format off */
#include <winsock2.h>
#include <winperf.h>
#include <iphlpapi.h>
#include <psapi.h>
#include <tlhelp32.h>
#include <windows.h>
+/* clang-format on */
#include <userenv.h>
#include <math.h>
@@ -67,8 +69,8 @@ extern BOOLEAN NTAPI SystemFunction036(PVOID Buffer, ULONG BufferLength);
static char *process_title;
static CRITICAL_SECTION process_title_lock;
-/* Interval (in seconds) of the high-resolution clock. */
-static double hrtime_interval_ = 0;
+/* Frequency of the high-resolution clock. */
+static uint64_t hrtime_frequency_ = 0;
/*
@@ -84,9 +86,9 @@ void uv__util_init(void) {
* and precompute its reciprocal.
*/
if (QueryPerformanceFrequency(&perf_frequency)) {
- hrtime_interval_ = 1.0 / perf_frequency.QuadPart;
+ hrtime_frequency_ = perf_frequency.QuadPart;
} else {
- hrtime_interval_= 0;
+ uv_fatal_error(GetLastError(), "QueryPerformanceFrequency");
}
}
@@ -490,23 +492,25 @@ uint64_t uv_hrtime(void) {
return uv__hrtime(UV__NANOSEC);
}
-uint64_t uv__hrtime(double scale) {
+uint64_t uv__hrtime(unsigned int scale) {
LARGE_INTEGER counter;
+ double scaled_freq;
+ double result;
- /* If the performance interval is zero, there's no support. */
- if (hrtime_interval_ == 0) {
- return 0;
- }
-
+ assert(hrtime_frequency_ != 0);
+ assert(scale != 0);
if (!QueryPerformanceCounter(&counter)) {
- return 0;
+ uv_fatal_error(GetLastError(), "QueryPerformanceCounter");
}
+ assert(counter.QuadPart != 0);
/* Because we have no guarantee about the order of magnitude of the
* performance counter interval, integer math could cause this computation
* to overflow. Therefore we resort to floating point math.
*/
- return (uint64_t) ((double) counter.QuadPart * hrtime_interval_ * scale);
+ scaled_freq = (double) hrtime_frequency_ / scale;
+ result = (double) counter.QuadPart / scaled_freq;
+ return (uint64_t) result;
}
@@ -1804,7 +1808,9 @@ int uv_os_uname(uv_utsname_t* buffer) {
pRtlGetVersion(&os_info);
} else {
/* Silence GetVersionEx() deprecation warning. */
+ #ifdef _MSC_VER
#pragma warning(suppress : 4996)
+ #endif
if (GetVersionExW(&os_info) == 0) {
r = uv_translate_sys_error(GetLastError());
goto error;
@@ -1871,7 +1877,7 @@ int uv_os_uname(uv_utsname_t* buffer) {
"MINGW32_NT-%u.%u",
(unsigned int) os_info.dwMajorVersion,
(unsigned int) os_info.dwMinorVersion);
- assert(r < sizeof(buffer->sysname));
+ assert((size_t)r < sizeof(buffer->sysname));
#else
uv__strscpy(buffer->sysname, "Windows_NT", sizeof(buffer->sysname));
#endif
@@ -1883,7 +1889,7 @@ int uv_os_uname(uv_utsname_t* buffer) {
(unsigned int) os_info.dwMajorVersion,
(unsigned int) os_info.dwMinorVersion,
(unsigned int) os_info.dwBuildNumber);
- assert(r < sizeof(buffer->release));
+ assert((size_t)r < sizeof(buffer->release));
/* Populate the machine field. */
GetSystemInfo(&system_info);
diff --git a/Utilities/cmlibuv/src/win/winapi.h b/Utilities/cmlibuv/src/win/winapi.h
index 77f1878..9bc4559 100644
--- a/Utilities/cmlibuv/src/win/winapi.h
+++ b/Utilities/cmlibuv/src/win/winapi.h
@@ -4735,6 +4735,18 @@ typedef HWINEVENTHOOK (WINAPI *sSetWinEventHook)
DWORD idThread,
UINT dwflags);
+/* From mstcpip.h */
+typedef struct _TCP_INITIAL_RTO_PARAMETERS {
+ USHORT Rtt;
+ UCHAR MaxSynRetransmissions;
+} TCP_INITIAL_RTO_PARAMETERS, *PTCP_INITIAL_RTO_PARAMETERS;
+
+#ifndef TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS
+# define TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS ((UCHAR) -2)
+#endif
+#ifndef SIO_TCP_INITIAL_RTO
+# define SIO_TCP_INITIAL_RTO _WSAIOW(IOC_VENDOR,17)
+#endif
/* Ntdll function pointers */
extern sRtlGetVersion pRtlGetVersion;