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
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
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;
}
* 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 <stddef.h> /* NULL */
#include <stdio.h> /* printf */
#include <stdlib.h>
return -1;
}
- if (uv__stream_open(tcp, fd)) {
+ if (uv__stream_open((uv_stream_t*)tcp, fd)) {
close(fd);
return -1;
}
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++;
/* Initialize winsock */
uv_winsock_startup();
- /* Initialize timers */
- uv_timer_startup();
-
/* Intialize event loop */
uv_loop_init();
}
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;
/*
* 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();
}
/* 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");
}
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");
}
#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;
}
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);
}
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;
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));
ASSERT(r == 0);
r = uv_tcp_listen(&server, 128, NULL);
ASSERT(r == 0);
+
+ return 0;
}
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);
}
ASSERT(r == 0);
- char ip[20];
r = uv_ip4_name((struct sockaddr_in*)&sockname, ip, 20);
ASSERT(r == 0);
ASSERT(ip[0] == '0');
#include "uv.h"
#include "task.h"
-
-#ifndef MICROSEC
-# define MICROSEC 1000000
+#ifndef MILLISEC
+# define MILLISEC 1000
#endif
#ifndef NANOSEC
#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;
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;
}