diff --git a/deps/uv/config-mingw.mk b/deps/uv/config-mingw.mk index 8081fce8ad..abd244e3ae 100644 --- a/deps/uv/config-mingw.mk +++ b/deps/uv/config-mingw.mk @@ -59,7 +59,9 @@ src/uv-eio.o: src/uv-eio.c clean-platform: -rm -f src/ares/*.o -rm -f src/eio/*.o + -rm -f src/win/*.o distclean-platform: -rm -f src/ares/*.o -rm -f src/eio/*.o + -rm -f src/win/*.o diff --git a/deps/uv/config-unix.mk b/deps/uv/config-unix.mk index 2b44dd6457..1352682778 100644 --- a/deps/uv/config-unix.mk +++ b/deps/uv/config-unix.mk @@ -65,6 +65,8 @@ endif ifneq (,$(findstring CYGWIN,$(uname_S))) EV_CONFIG=config_cygwin.h EIO_CONFIG=config_cygwin.h +# We drop the --std=c89, it hides CLOCK_MONOTONIC on cygwin +CSTDFLAG = -D_GNU_SOURCE CPPFLAGS += -Isrc/ares/config_cygwin LINKFLAGS+= UV_OS_FILE=uv-cygwin.c diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index d202128ff6..b0c8a82520 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -114,13 +114,13 @@ struct sockaddr_in6 uv_ip6_addr(const char* ip, int port) { int uv_ip4_name(struct sockaddr_in* src, char* dst, size_t size) { - char* d = ares_inet_ntop(AF_INET, &src->sin_addr, dst, size); + const char* d = ares_inet_ntop(AF_INET, &src->sin_addr, dst, size); return d != dst; } int uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size) { - char* d = ares_inet_ntop(AF_INET6, &src->sin6_addr, dst, size); + const char* d = ares_inet_ntop(AF_INET6, &src->sin6_addr, dst, size); return d != dst; } diff --git a/deps/uv/src/uv-unix.c b/deps/uv/src/uv-unix.c index 2ee2f8643a..842fe326dd 100644 --- a/deps/uv/src/uv-unix.c +++ b/deps/uv/src/uv-unix.c @@ -18,12 +18,14 @@ * IN THE SOFTWARE. */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE /* O_CLOEXEC, accept4(), etc. */ +#endif + #include "uv.h" #include "uv-common.h" #include "uv-eio.h" -#define _GNU_SOURCE /* O_CLOEXEC */ - #include /* NULL */ #include /* printf */ #include @@ -494,7 +496,7 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { return -1; } - if (uv__stream_open(tcp, fd)) { + if (uv__stream_open((uv_stream_t*)tcp, fd)) { close(fd); return -1; } @@ -1751,7 +1753,7 @@ int uv_getaddrinfo(uv_getaddrinfo_t* handle, int uv_pipe_init(uv_pipe_t* handle) { - memset(handle, 0, sizeof handle); + memset(handle, 0, sizeof *handle); uv__handle_init((uv_handle_t*)handle, UV_NAMED_PIPE); uv_counters()->pipe_init++; diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c index 32009478fb..e2d5a32c8a 100644 --- a/deps/uv/src/win/core.c +++ b/deps/uv/src/win/core.c @@ -70,9 +70,6 @@ void uv_init() { /* Initialize winsock */ uv_winsock_startup(); - /* Initialize timers */ - uv_timer_startup(); - /* Intialize event loop */ uv_loop_init(); } diff --git a/deps/uv/src/win/error.c b/deps/uv/src/win/error.c index d7cf9866c5..d44be2bb2d 100644 --- a/deps/uv/src/win/error.c +++ b/deps/uv/src/win/error.c @@ -107,6 +107,7 @@ uv_err_code uv_translate_sys_error(int sys_errno) { case ERROR_TOO_MANY_OPEN_FILES: return UV_EMFILE; case WSAEMFILE: return UV_EMFILE; case ERROR_OUTOFMEMORY: return UV_ENOMEM; + case ERROR_NOT_SUPPORTED: return UV_ENOTSUP; case ERROR_INSUFFICIENT_BUFFER: return UV_EINVAL; case ERROR_INVALID_FLAGS: return UV_EBADF; case ERROR_INVALID_PARAMETER: return UV_EINVAL; diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h index 7c42a774e7..33783f6eb9 100644 --- a/deps/uv/src/win/internal.h +++ b/deps/uv/src/win/internal.h @@ -30,11 +30,8 @@ /* * Timers */ - RB_HEAD(uv_timer_tree_s, uv_timer_s); -void uv_timer_startup(); - void uv_timer_endgame(uv_timer_t* handle); DWORD uv_get_poll_timeout(); diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c index f253d82a86..563c431f01 100644 --- a/deps/uv/src/win/pipe.c +++ b/deps/uv/src/win/pipe.c @@ -107,7 +107,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { } /* Make our own copy of the pipe name */ - handle->name = strdup(name); + handle->name = _strdup(name); if (!handle->name) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } @@ -198,7 +198,7 @@ int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, if (pipeHandle == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_PIPE_BUSY) { /* Wait for the server to make a pipe instance available. */ - handle->name = strdup(name); + handle->name = _strdup(name); if (!handle->name) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } diff --git a/deps/uv/src/win/timer.c b/deps/uv/src/win/timer.c index 6f74a2ca00..ea5e7195e8 100644 --- a/deps/uv/src/win/timer.c +++ b/deps/uv/src/win/timer.c @@ -26,19 +26,30 @@ #include "internal.h" #include "tree.h" +#undef NANOSEC +#define NANOSEC 1000000000 + /* The resolution of the high-resolution clock. */ static int64_t uv_ticks_per_msec_ = 0; - +static uint64_t uv_hrtime_frequency_ = 0; +static char uv_hrtime_initialized_ = 0; void uv_update_time() { - LARGE_INTEGER counter; + DWORD ticks = GetTickCount(); - if (!QueryPerformanceCounter(&counter)) - uv_fatal_error(GetLastError(), "QueryPerformanceCounter"); + /* The assumption is made that LARGE_INTEGER.QuadPart has the same type */ + /* LOOP->time, which happens to be. Is there any way to assert this? */ + LARGE_INTEGER* time = (LARGE_INTEGER*) &LOOP->time; - LOOP->time = counter.QuadPart / uv_ticks_per_msec_; + /* If the timer has wrapped, add 1 to it's high-order dword. */ + /* uv_poll must make sure that the timer can never overflow more than */ + /* once between two subsequent uv_update_time calls. */ + if (ticks < time->LowPart) { + time->HighPart += 1; + } + time->LowPart = ticks; } @@ -48,18 +59,39 @@ int64_t uv_now() { uint64_t uv_hrtime(void) { - assert(0 && "implement me"); - return 0; -} + LARGE_INTEGER counter; + /* When called for the first time, obtain the high-resolution clock */ + /* frequency. */ + if (!uv_hrtime_initialized_) { + uv_hrtime_initialized_ = 1; -void uv_timer_startup() { - LARGE_INTEGER timer_frequency; + if (!QueryPerformanceFrequency(&counter)) { + uv_hrtime_frequency_ = 0; + uv_set_sys_error(GetLastError()); + return 0; + } + + uv_hrtime_frequency_ = counter.QuadPart; + } + + /* If the performance frequency is zero, there's no support. */ + if (!uv_hrtime_frequency_) { + uv_set_sys_error(ERROR_NOT_SUPPORTED); + return 0; + } + + if (!QueryPerformanceCounter(&counter)) { + uv_set_sys_error(GetLastError()); + return 0; + } - /* Initialize the event loop time */ - if (!QueryPerformanceFrequency(&timer_frequency)) - uv_fatal_error(GetLastError(), "QueryPerformanceFrequency"); - uv_ticks_per_msec_ = timer_frequency.QuadPart / 1000; + /* Because we have no guarantee about the order of magniture of the */ + /* performance counter frequency, and there may not be much headroom to */ + /* multiply by NANOSEC without overflowing, we use 128-bit math instead. */ + return ((uint64_t) counter.LowPart * NANOSEC / uv_hrtime_frequency_) + + (((uint64_t) counter.HighPart * NANOSEC / uv_hrtime_frequency_) + << 32); } @@ -187,10 +219,15 @@ DWORD uv_get_poll_timeout() { uv_update_time(); delta = timer->due - LOOP->time; - if (delta >= UINT_MAX) { - /* Can't have a timeout greater than UINT_MAX, and a timeout value of */ - /* UINT_MAX means infinite, so that's no good either. */ - return UINT_MAX - 1; + if (delta >= UINT_MAX >> 1) { + /* A timeout value of UINT_MAX means infinite, so that's no good. But */ + /* more importantly, there's always the risk that GetTickCount wraps. */ + /* uv_update_time can detect this, but we must make sure that the */ + /* tick counter never overflows twice between two subsequent */ + /* uv_update_time calls. We do this by never sleeping more than half */ + /* the time it takes to wrap the counter - which is huge overkill, */ + /* but hey, it's not so bad to wake up every 25 days. */ + return UINT_MAX >> 1; } else if (delta < 0) { /* Negative timeout values are not allowed */ return 0; diff --git a/deps/uv/test/benchmark-sizes.c b/deps/uv/test/benchmark-sizes.c index 9038645253..ab60e96fcc 100644 --- a/deps/uv/test/benchmark-sizes.c +++ b/deps/uv/test/benchmark-sizes.c @@ -24,7 +24,9 @@ BENCHMARK_IMPL(sizes) { - LOGF("uv_req_t: %u bytes\n", (unsigned int) sizeof(uv_req_t)); + LOGF("uv_shutdown_t: %u bytes\n", (unsigned int) sizeof(uv_shutdown_t)); + LOGF("uv_write_t: %u bytes\n", (unsigned int) sizeof(uv_write_t)); + LOGF("uv_connect_t: %u bytes\n", (unsigned int) sizeof(uv_connect_t)); LOGF("uv_tcp_t: %u bytes\n", (unsigned int) sizeof(uv_tcp_t)); LOGF("uv_pipe_t: %u bytes\n", (unsigned int) sizeof(uv_pipe_t)); LOGF("uv_prepare_t: %u bytes\n", (unsigned int) sizeof(uv_prepare_t)); diff --git a/deps/uv/test/test-bind-error.c b/deps/uv/test/test-bind-error.c index f3db848a75..834f4ffa02 100644 --- a/deps/uv/test/test-bind-error.c +++ b/deps/uv/test/test-bind-error.c @@ -199,4 +199,6 @@ TEST_IMPL(listen_without_bind) { ASSERT(r == 0); r = uv_tcp_listen(&server, 128, NULL); ASSERT(r == 0); + + return 0; } diff --git a/deps/uv/test/test-getsockname.c b/deps/uv/test/test-getsockname.c index eeae468672..6e4f643661 100644 --- a/deps/uv/test/test-getsockname.c +++ b/deps/uv/test/test-getsockname.c @@ -126,6 +126,7 @@ static int tcp_listener(int port) { struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", port); struct sockaddr sockname; int namelen = sizeof(sockname); + char ip[20]; int r; r = uv_tcp_init(&tcpServer); @@ -152,7 +153,6 @@ static int tcp_listener(int port) { } ASSERT(r == 0); - char ip[20]; r = uv_ip4_name((struct sockaddr_in*)&sockname, ip, 20); ASSERT(r == 0); ASSERT(ip[0] == '0'); diff --git a/deps/uv/test/test-hrtime.c b/deps/uv/test/test-hrtime.c index e1959b07a5..566e0d2ee0 100644 --- a/deps/uv/test/test-hrtime.c +++ b/deps/uv/test/test-hrtime.c @@ -22,9 +22,8 @@ #include "uv.h" #include "task.h" - -#ifndef MICROSEC -# define MICROSEC 1000000 +#ifndef MILLISEC +# define MILLISEC 1000 #endif #ifndef NANOSEC @@ -32,11 +31,6 @@ #endif - -/* - * We expect the amount of time passed to be at least one us plus two system - * calls. Therefore checking that at least a microsecond has elapsed is safe. - */ TEST_IMPL(hrtime) { uint64_t a, b, diff; @@ -46,9 +40,12 @@ TEST_IMPL(hrtime) { diff = b - a; - printf("diff = %llu\n", (unsigned long long int)diff); + printf("diff = %llu\n", (unsigned long long int) diff); - ASSERT(diff >= NANOSEC / MICROSEC); - ASSERT(diff > MICROSEC); + /* The windows Sleep() function has only a resolution of 10-20 ms. */ + /* Check that the difference between the two hrtime values is somewhat in */ + /* the range we expect it to be. */ + ASSERT(diff > (uint64_t) 80 * NANOSEC / MILLISEC); + ASSERT(diff < (uint64_t) 120 * NANOSEC / MILLISEC); return 0; }