From 31fc52ab53b5dde882ebadbbc912c2848c7b6a83 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Fri, 11 Jan 2013 13:49:45 +0100 Subject: [PATCH] deps: upgrade libuv to 9aab5d4 --- deps/uv/Makefile | 4 +- deps/uv/checksparse.sh | 230 ++++++++++++++++++ deps/uv/config-unix.mk | 23 +- deps/uv/include/uv-private/uv-sunos.h | 10 +- deps/uv/include/uv.h | 38 ++- deps/uv/src/fs-poll.c | 10 +- deps/uv/src/unix/aix.c | 2 +- deps/uv/src/unix/async.c | 4 +- deps/uv/src/unix/core.c | 75 +++--- deps/uv/src/unix/cygwin.c | 5 +- deps/uv/src/unix/darwin.c | 2 +- deps/uv/src/unix/freebsd.c | 2 +- deps/uv/src/unix/fs.c | 2 + deps/uv/src/unix/getaddrinfo.c | 6 +- deps/uv/src/unix/internal.h | 31 +-- deps/uv/src/unix/kqueue.c | 11 +- deps/uv/src/unix/linux/linux-core.c | 37 ++- deps/uv/src/unix/linux/syscalls.c | 136 +++++------ deps/uv/src/unix/loop-watcher.c | 4 +- deps/uv/src/unix/loop.c | 2 +- deps/uv/src/unix/netbsd.c | 2 +- deps/uv/src/unix/openbsd.c | 2 +- deps/uv/src/unix/process.c | 108 ++++---- deps/uv/src/unix/signal.c | 8 +- deps/uv/src/unix/stream.c | 103 ++++---- deps/uv/src/unix/sunos.c | 38 +-- deps/uv/src/unix/thread.c | 2 +- deps/uv/src/unix/threadpool.c | 3 +- deps/uv/src/unix/tty.c | 2 +- deps/uv/src/unix/udp.c | 2 +- deps/uv/src/win/core.c | 82 +++---- deps/uv/src/win/loop-watcher.c | 3 + deps/uv/src/win/tty.c | 2 +- deps/uv/test/benchmark-getaddrinfo.c | 2 +- deps/uv/test/benchmark-list.h | 2 + deps/uv/test/benchmark-million-async.c | 112 +++++++++ deps/uv/test/benchmark-ping-pongs.c | 2 +- deps/uv/test/benchmark-pump.c | 20 +- deps/uv/test/benchmark-spawn.c | 12 +- deps/uv/test/dns-server.c | 15 +- deps/uv/test/runner-unix.c | 2 +- deps/uv/test/runner.c | 12 +- deps/uv/test/runner.h | 12 +- deps/uv/test/task.h | 18 +- deps/uv/test/test-async.c | 2 +- deps/uv/test/test-condvar-consumer-producer.c | 138 ----------- deps/uv/test/test-connection-fail.c | 2 +- deps/uv/test/test-delayed-accept.c | 4 +- deps/uv/test/test-embed.c | 8 +- deps/uv/test/test-fs-event.c | 8 +- deps/uv/test/test-fs.c | 2 +- deps/uv/test/test-getsockname.c | 6 +- deps/uv/test/test-ipc.c | 6 +- deps/uv/test/test-list.h | 6 +- deps/uv/test/test-multiple-listen.c | 4 +- deps/uv/test/test-ping-pong.c | 8 +- deps/uv/test/test-poll.c | 8 +- deps/uv/test/test-ref.c | 20 +- deps/uv/test/test-run-nowait.c | 46 ++++ deps/uv/test/test-run-once.c | 2 +- deps/uv/test/test-shutdown-eof.c | 6 +- deps/uv/test/test-spawn.c | 4 +- deps/uv/test/test-stdio-over-pipes.c | 5 +- deps/uv/test/test-threadpool-cancel.c | 41 ++++ deps/uv/uv.gyp | 14 +- 65 files changed, 948 insertions(+), 592 deletions(-) create mode 100755 deps/uv/checksparse.sh create mode 100644 deps/uv/test/benchmark-million-async.c delete mode 100644 deps/uv/test/test-condvar-consumer-producer.c create mode 100644 deps/uv/test/test-run-nowait.c diff --git a/deps/uv/Makefile b/deps/uv/Makefile index 4012b6e00d..ef2b352583 100644 --- a/deps/uv/Makefile +++ b/deps/uv/Makefile @@ -62,7 +62,7 @@ bench: test/run-benchmarks$(E) $< clean: clean-platform - $(RM) -f src/*.o *.a test/run-tests$(E) test/run-benchmarks$(E) + $(RM) -f *.a *.so test/run-tests$(E) test/run-benchmarks$(E) distclean: distclean-platform - $(RM) -f src/*.o *.a test/run-tests$(E) test/run-benchmarks$(E) + $(RM) -f *.a *.so test/run-tests$(E) test/run-benchmarks$(E) diff --git a/deps/uv/checksparse.sh b/deps/uv/checksparse.sh new file mode 100755 index 0000000000..3a19d161b5 --- /dev/null +++ b/deps/uv/checksparse.sh @@ -0,0 +1,230 @@ +#!/bin/sh + +# Copyright (c) 2013, Ben Noordhuis +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +SPARSE=${SPARSE:-sparse} + +SPARSE_FLAGS=${SPARSE_FLAGS:-" +-D__POSIX__ +-Wsparse-all +-Wno-do-while +-Wno-transparent-union +-Iinclude +-Iinclude/uv-private +-Isrc +"} + +SOURCES=" +include/uv-private/ngx-queue.h +include/uv-private/tree.h +include/uv-private/uv-unix.h +include/uv.h +src/fs-poll.c +src/inet.c +src/unix/async.c +src/unix/core.c +src/unix/dl.c +src/unix/error.c +src/unix/fs.c +src/unix/getaddrinfo.c +src/unix/internal.h +src/unix/loop-watcher.c +src/unix/loop.c +src/unix/pipe.c +src/unix/poll.c +src/unix/process.c +src/unix/signal.c +src/unix/stream.c +src/unix/tcp.c +src/unix/thread.c +src/unix/threadpool.c +src/unix/timer.c +src/unix/tty.c +src/unix/udp.c +src/uv-common.c +src/uv-common.h +" + +TESTS=" +test/benchmark-async-pummel.c +test/benchmark-async.c +test/benchmark-fs-stat.c +test/benchmark-getaddrinfo.c +test/benchmark-loop-count.c +test/benchmark-million-async.c +test/benchmark-million-timers.c +test/benchmark-multi-accept.c +test/benchmark-ping-pongs.c +test/benchmark-pound.c +test/benchmark-pump.c +test/benchmark-sizes.c +test/benchmark-spawn.c +test/benchmark-tcp-write-batch.c +test/benchmark-thread.c +test/benchmark-udp-pummel.c +test/blackhole-server.c +test/dns-server.c +test/echo-server.c +test/run-benchmarks.c +test/run-tests.c +test/runner-unix.c +test/runner-unix.h +test/runner.c +test/runner.h +test/task.h +test/test-active.c +test/test-async.c +test/test-barrier.c +test/test-callback-order.c +test/test-callback-stack.c +test/test-condvar.c +test/test-connection-fail.c +test/test-cwd-and-chdir.c +test/test-delayed-accept.c +test/test-dlerror.c +test/test-embed.c +test/test-error.c +test/test-fail-always.c +test/test-fs-event.c +test/test-fs-poll.c +test/test-fs.c +test/test-get-currentexe.c +test/test-get-loadavg.c +test/test-get-memory.c +test/test-getaddrinfo.c +test/test-getsockname.c +test/test-hrtime.c +test/test-idle.c +test/test-ipc-send-recv.c +test/test-ipc.c +test/test-loop-handles.c +test/test-multiple-listen.c +test/test-mutexes.c +test/test-pass-always.c +test/test-ping-pong.c +test/test-pipe-bind-error.c +test/test-pipe-connect-error.c +test/test-platform-output.c +test/test-poll-close.c +test/test-poll.c +test/test-process-title.c +test/test-ref.c +test/test-run-nowait.c +test/test-run-once.c +test/test-semaphore.c +test/test-shutdown-close.c +test/test-shutdown-eof.c +test/test-signal-multiple-loops.c +test/test-signal.c +test/test-spawn.c +test/test-stdio-over-pipes.c +test/test-tcp-bind-error.c +test/test-tcp-bind6-error.c +test/test-tcp-close-while-connecting.c +test/test-tcp-close.c +test/test-tcp-connect-error-after-write.c +test/test-tcp-connect-error.c +test/test-tcp-connect-timeout.c +test/test-tcp-connect6-error.c +test/test-tcp-flags.c +test/test-tcp-open.c +test/test-tcp-read-stop.c +test/test-tcp-shutdown-after-write.c +test/test-tcp-unexpected-read.c +test/test-tcp-write-error.c +test/test-tcp-write-to-half-open-connection.c +test/test-tcp-writealot.c +test/test-thread.c +test/test-threadpool-cancel.c +test/test-threadpool.c +test/test-timer-again.c +test/test-timer.c +test/test-tty.c +test/test-udp-dgram-too-big.c +test/test-udp-ipv6.c +test/test-udp-multicast-join.c +test/test-udp-multicast-ttl.c +test/test-udp-open.c +test/test-udp-options.c +test/test-udp-send-and-recv.c +test/test-util.c +test/test-walk-handles.c +" + +case `uname -s` in +AIX) + SPARSE_FLAGS="$SPARSE_FLAGS -D_AIX=1" + SOURCES="$SOURCES + src/unix/aix.c" + ;; +Darwin) + SPARSE_FLAGS="$SPARSE_FLAGS -D__APPLE__=1" + SOURCES="$SOURCES + include/uv-private/uv-bsd.h + src/unix/darwin.c + src/unix/kqueue.c + src/unix/fsevents.c" + ;; +DragonFly) + SPARSE_FLAGS="$SPARSE_FLAGS -D__DragonFly__=1" + SOURCES="$SOURCES + include/uv-private/uv-bsd.h + src/unix/kqueue.c + src/unix/freebsd.c" + ;; +FreeBSD) + SPARSE_FLAGS="$SPARSE_FLAGS -D__FreeBSD__=1" + SOURCES="$SOURCES + include/uv-private/uv-bsd.h + src/unix/kqueue.c + src/unix/freebsd.c" + ;; +Linux) + SPARSE_FLAGS="$SPARSE_FLAGS -D__linux__=1" + SOURCES="$SOURCES + include/uv-private/uv-linux.h + src/unix/linux/inotify.c + src/unix/linux/linux-core.c + src/unix/linux/syscalls.c + src/unix/linux/syscalls.h" + ;; +NetBSD) + SPARSE_FLAGS="$SPARSE_FLAGS -D__NetBSD__=1" + SOURCES="$SOURCES + include/uv-private/uv-bsd.h + src/unix/kqueue.c + src/unix/netbsd.c" + ;; +OpenBSD) + SPARSE_FLAGS="$SPARSE_FLAGS -D__OpenBSD__=1" + SOURCES="$SOURCES + include/uv-private/uv-bsd.h + src/unix/kqueue.c + src/unix/openbsd.c" + ;; +SunOS) + SPARSE_FLAGS="$SPARSE_FLAGS -D__sun=1" + SOURCES="$SOURCES + include/uv-private/uv-sunos.h + src/unix/sunos.c" + ;; +esac + +for ARCH in __i386__ __x86_64__ __arm__; do + $SPARSE $SPARSE_FLAGS -D$ARCH=1 $SOURCES +done + +# Tests are architecture independent. +$SPARSE $SPARSE_FLAGS -Itest $TESTS diff --git a/deps/uv/config-unix.mk b/deps/uv/config-unix.mk index 37828f29f6..66c74ee19f 100644 --- a/deps/uv/config-unix.mk +++ b/deps/uv/config-unix.mk @@ -123,6 +123,13 @@ else RUNNER_LDFLAGS += -pthread endif +OBJDIR := out +ifeq ($(MAKECMDGOALS), test) + OBJDIR := $(OBJDIR)/test +endif + +OBJS := $(addprefix $(OBJDIR)/,$(OBJS)) + libuv.a: $(OBJS) $(AR) rcs $@ $^ @@ -130,18 +137,18 @@ libuv.$(SOEXT): override CFLAGS += -fPIC libuv.$(SOEXT): $(OBJS) $(CC) -shared -o $@ $^ $(LDFLAGS) -src/%.o: src/%.c include/uv.h include/uv-private/uv-unix.h +$(OBJDIR)/src/unix/%.o: src/unix/%.c include/uv.h include/uv-private/uv-unix.h src/unix/internal.h + @mkdir -p $(dir $@) $(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ -src/unix/%.o: src/unix/%.c include/uv.h include/uv-private/uv-unix.h src/unix/internal.h +$(OBJDIR)/src/%.o: src/%.c include/uv.h include/uv-private/uv-unix.h + @mkdir -p $(dir $@) $(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ clean-platform: - -rm -f src/unix/*.o - -rm -f src/unix/linux/*.o - -rm -rf test/run-tests.dSYM run-benchmarks.dSYM + -rm -rf $(OBJDIR) + -rm -f libuv.a libuv.$(SOEXT) test/run-{tests,benchmarks}.dSYM distclean-platform: - -rm -f src/unix/*.o - -rm -f src/unix/linux/*.o - -rm -rf test/run-tests.dSYM run-benchmarks.dSYM + -rm -rf $(OBJDIR) + -rm -f libuv.a libuv.$(SOEXT) test/run-{tests,benchmarks}.dSYM diff --git a/deps/uv/include/uv-private/uv-sunos.h b/deps/uv/include/uv-private/uv-sunos.h index 9d55e23fde..042166424e 100644 --- a/deps/uv/include/uv-private/uv-sunos.h +++ b/deps/uv/include/uv-private/uv-sunos.h @@ -25,12 +25,16 @@ #include #include -#if defined(PORT_SOURCE_FILE) - -# define UV_PLATFORM_LOOP_FIELDS \ +/* For the sake of convenience and reduced #ifdef-ery in src/unix/sunos.c, + * add the fs_event fields even when this version of SunOS doesn't support + * file watching. + */ +#define UV_PLATFORM_LOOP_FIELDS \ uv__io_t fs_event_watcher; \ int fs_fd; \ +#if defined(PORT_SOURCE_FILE) + # define UV_PLATFORM_FS_EVENT_FIELDS \ file_obj_t fo; \ int fd; \ diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 57ce8ae5ad..692a21c15b 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -221,6 +221,13 @@ typedef struct uv_cpu_info_s uv_cpu_info_t; typedef struct uv_interface_address_s uv_interface_address_t; +typedef enum { + UV_RUN_DEFAULT = 0, + UV_RUN_ONCE, + UV_RUN_NOWAIT +} uv_run_mode; + + /* * This function must be called before any other functions in libuv. * @@ -244,12 +251,18 @@ UV_EXTERN uv_loop_t* uv_default_loop(void); UV_EXTERN int uv_run(uv_loop_t*); /* - * Poll for new events once. Note that this function blocks if there are no - * pending events. Returns zero when done (no active handles or requests left), - * or non-zero if more events are expected (meaning you should call - * uv_run_once() again sometime in the future). + * This function runs the event loop. It will act differently depending on the + * specified mode: + * - UV_RUN_DEFAULT: Runs the event loop until the reference count drops to + * zero. Always returns zero. + * - UV_RUN_ONCE: Poll for new events once. Note that this function blocks if + * there are no pending events. Returns zero when done (no active handles + * or requests left), or non-zero if more events are expected (meaning you + * should run the event loop again sometime in the future). + * - UV_RUN_NOWAIT: Poll for new events once but don't block if there are no + * pending events. */ -UV_EXTERN int uv_run_once(uv_loop_t*); +UV_EXTERN int uv_run2(uv_loop_t*, uv_run_mode mode); /* * Manually modify the event loop's reference count. Useful if the user wants @@ -265,7 +278,7 @@ UV_EXTERN int64_t uv_now(uv_loop_t*); * Get backend file descriptor. Only kqueue, epoll and event ports are * supported. * - * This can be used in conjuction with uv_run_once() to poll in one thread and + * This can be used in conjunction with uv_run_once() to poll in one thread and * run the event loop's event callbacks in another. * * Useful for embedding libuv's event loop in another event loop. @@ -1653,8 +1666,10 @@ UV_EXTERN int uv_fs_poll_stop(uv_fs_poll_t* handle); * ultra efficient so don't go creating a million event loops with a million * signal watchers. * - * TODO(bnoordhuis) As of 2012-08-10 only the default event loop supports - * signals. That will be fixed. + * Note to Linux users: SIGRT0 and SIGRT1 (signals 32 and 33) are used by the + * NPTL pthreads library to manage threads. Installing watchers for those + * signals will lead to unpredictable behavior and is strongly discouraged. + * Future versions of libuv may simply reject them. * * Some signal support is available on Windows: * @@ -1688,11 +1703,12 @@ struct uv_signal_s { UV_SIGNAL_PRIVATE_FIELDS }; -/* These functions are no-ops on Windows. */ UV_EXTERN int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle); + UV_EXTERN int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum); + UV_EXTERN int uv_signal_stop(uv_signal_t* handle); @@ -1782,7 +1798,7 @@ UV_EXTERN extern uint64_t uv_hrtime(void); /* * Disables inheritance for file descriptors / handles that this process * inherited from its parent. The effect is that child processes spawned by - * this proces don't accidently inherit these handles. + * this process don't accidentally inherit these handles. * * It is recommended to call this function as early in your program as possible, * before the inherited file descriptors can be closed or duplicated. @@ -1802,7 +1818,7 @@ UV_EXTERN void uv_disable_stdio_inheritance(void); UV_EXTERN int uv_dlopen(const char* filename, uv_lib_t* lib); /* - * Close the shared libary. + * Close the shared library. */ UV_EXTERN void uv_dlclose(uv_lib_t* lib); diff --git a/deps/uv/src/fs-poll.c b/deps/uv/src/fs-poll.c index b5b344b920..8d736caba9 100644 --- a/deps/uv/src/fs-poll.c +++ b/deps/uv/src/fs-poll.c @@ -190,15 +190,15 @@ static void timer_close_cb(uv_handle_t* handle) { static int statbuf_eq(const uv_statbuf_t* a, const uv_statbuf_t* b) { -#ifdef _WIN32 +#if defined(_WIN32) return a->st_mtime == b->st_mtime && a->st_size == b->st_size && a->st_mode == b->st_mode; #else /* Jump through a few hoops to get sub-second granularity on Linux. */ -# if __linux__ -# if __USE_MISC /* _BSD_SOURCE || _SVID_SOURCE */ +# if defined(__linux__) +# if defined(__USE_MISC) /* _BSD_SOURCE || _SVID_SOURCE */ if (a->st_ctim.tv_nsec != b->st_ctim.tv_nsec) return 0; if (a->st_mtim.tv_nsec != b->st_mtim.tv_nsec) return 0; # else @@ -208,7 +208,7 @@ static int statbuf_eq(const uv_statbuf_t* a, const uv_statbuf_t* b) { # endif /* Jump through different hoops on OS X. */ -# if __APPLE__ +# if defined(__APPLE__) # if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) if (a->st_ctimespec.tv_nsec != b->st_ctimespec.tv_nsec) return 0; if (a->st_mtimespec.tv_nsec != b->st_mtimespec.tv_nsec) return 0; @@ -234,7 +234,7 @@ static int statbuf_eq(const uv_statbuf_t* a, const uv_statbuf_t* b) { } -#ifdef _WIN32 +#if defined(_WIN32) #include "win/internal.h" #include "win/handle-inl.h" diff --git a/deps/uv/src/unix/aix.c b/deps/uv/src/unix/aix.c index 5637e87114..5ea33bbcd5 100644 --- a/deps/uv/src/unix/aix.c +++ b/deps/uv/src/unix/aix.c @@ -45,7 +45,7 @@ #include #include -uint64_t uv_hrtime() { +uint64_t uv__hrtime(void) { uint64_t G = 1000000000; timebasestruct_t t; read_wall_time(&t, TIMEBASE_SZ); diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c index d45aa5423b..322167c68c 100644 --- a/deps/uv/src/unix/async.c +++ b/deps/uv/src/unix/async.c @@ -44,13 +44,13 @@ static int uv__async_make_pending(volatile sig_atomic_t* ptr) { * on x86, it's about 4x faster. It probably makes zero difference in the * grand scheme of things but I'm OCD enough not to let this one pass. */ -#if __i386__ || __x86_64__ +#if defined(__i386__) || defined(__x86_64__) { unsigned int val = 1; __asm__ __volatile__("xchgl %0, %1" : "+r" (val) : "m" (*ptr)); return val != 0; } -#elif __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 1 /* gcc >= 4.1 */ +#elif defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ > 0) return __sync_val_compare_and_swap(ptr, 0, 1) != 0; #else *ptr = 1; diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index b0686ce0ac..b4cb948b2f 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -66,6 +66,11 @@ static uv_loop_t default_loop_struct; static uv_loop_t* default_loop_ptr; +uint64_t uv_hrtime(void) { + return uv__hrtime(); +} + + void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { assert(!(handle->flags & (UV_CLOSING | UV_CLOSED))); @@ -267,32 +272,42 @@ int uv_backend_timeout(const uv_loop_t* loop) { } -static int uv__run(uv_loop_t* loop) { - uv_update_time(loop); - uv__run_timers(loop); - uv__run_idle(loop); - uv__run_prepare(loop); - uv__run_pending(loop); - uv__io_poll(loop, uv_backend_timeout(loop)); - uv__run_check(loop); - uv__run_closing_handles(loop); - return uv__has_active_handles(loop) || uv__has_active_reqs(loop); +static int uv__loop_alive(uv_loop_t* loop) { + return uv__has_active_handles(loop) || + uv__has_active_reqs(loop) || + loop->closing_handles != NULL; } -int uv_run(uv_loop_t* loop) { - while (uv__run(loop)); - return 0; +int uv_run2(uv_loop_t* loop, uv_run_mode mode) { + int r; + + if (!uv__loop_alive(loop)) + return 0; + + do { + uv__update_time(loop); + uv__run_timers(loop); + uv__run_idle(loop); + uv__run_prepare(loop); + uv__run_pending(loop); + uv__io_poll(loop, (mode & UV_RUN_NOWAIT ? 0 : uv_backend_timeout(loop))); + uv__run_check(loop); + uv__run_closing_handles(loop); + r = uv__loop_alive(loop); + } while (r && !(mode & (UV_RUN_ONCE | UV_RUN_NOWAIT))); + + return r; } -int uv_run_once(uv_loop_t* loop) { - return uv__run(loop); +int uv_run(uv_loop_t* loop) { + return uv_run2(loop, UV_RUN_DEFAULT); } void uv_update_time(uv_loop_t* loop) { - loop->time = uv_hrtime() / 1000000; + uv__update_time(loop); } @@ -348,7 +363,7 @@ int uv__accept(int sockfd) { assert(sockfd >= 0); while (1) { -#if __linux__ +#if defined(__linux__) static int no_accept4; if (no_accept4) @@ -429,6 +444,10 @@ int uv__nonblock(int fd, int set) { if (r == -1) return -1; + /* Bail out now if already set/clear. */ + if (!!(r & O_NONBLOCK) == !!set) + return 0; + if (set) flags = r | O_NONBLOCK; else @@ -453,6 +472,10 @@ int uv__cloexec(int fd, int set) { if (r == -1) return -1; + /* Bail out now if already set/clear. */ + if (!!(r & FD_CLOEXEC) == !!set) + return 0; + if (set) flags = r | FD_CLOEXEC; else @@ -486,24 +509,6 @@ int uv__dup(int fd) { } -/* TODO move to uv-common.c? */ -size_t uv__strlcpy(char* dst, const char* src, size_t size) { - const char *org; - - if (size == 0) { - return 0; - } - - org = src; - while (--size && *src) { - *dst++ = *src++; - } - *dst = '\0'; - - return src - org; -} - - uv_err_t uv_cwd(char* buffer, size_t size) { if (!buffer || !size) { return uv__new_artificial_error(UV_EINVAL); diff --git a/deps/uv/src/unix/cygwin.c b/deps/uv/src/unix/cygwin.c index 8c0797e400..9746454119 100644 --- a/deps/uv/src/unix/cygwin.c +++ b/deps/uv/src/unix/cygwin.c @@ -19,7 +19,7 @@ */ #include "uv.h" -#include "../uv-common.h" +#include "internal.h" #include #include @@ -41,12 +41,13 @@ void uv__platform_loop_delete(uv_loop_t* loop) { } -uint64_t uv_hrtime() { +uint64_t uv__hrtime(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec); } + void uv_loadavg(double avg[3]) { /* Unsupported as of cygwin 1.7.7 */ avg[0] = avg[1] = avg[2] = 0; diff --git a/deps/uv/src/unix/darwin.c b/deps/uv/src/unix/darwin.c index f40efb2fcd..b5cba8636c 100644 --- a/deps/uv/src/unix/darwin.c +++ b/deps/uv/src/unix/darwin.c @@ -176,7 +176,7 @@ void uv__cf_loop_signal(uv_loop_t* loop, cf_loop_signal_cb cb, void* arg) { } -uint64_t uv_hrtime(void) { +uint64_t uv__hrtime(void) { mach_timebase_info_data_t info; if (mach_timebase_info(&info) != KERN_SUCCESS) diff --git a/deps/uv/src/unix/freebsd.c b/deps/uv/src/unix/freebsd.c index 4a32f6ee56..44b1ef3d20 100644 --- a/deps/uv/src/unix/freebsd.c +++ b/deps/uv/src/unix/freebsd.c @@ -63,7 +63,7 @@ void uv__platform_loop_delete(uv_loop_t* loop) { } -uint64_t uv_hrtime(void) { +uint64_t uv__hrtime(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec); diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index 6c6faf53cd..f01c83b4a0 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -381,6 +381,7 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) { errno == EIO || errno == ENOTSOCK || errno == EXDEV) { + errno = 0; return uv__fs_sendfile_emul(req); } @@ -412,6 +413,7 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) { errno == EIO || errno == ENOTSOCK || errno == EXDEV) { + errno = 0; return uv__fs_sendfile_emul(req); } diff --git a/deps/uv/src/unix/getaddrinfo.c b/deps/uv/src/unix/getaddrinfo.c index 7f147291db..283d295f5d 100644 --- a/deps/uv/src/unix/getaddrinfo.c +++ b/deps/uv/src/unix/getaddrinfo.c @@ -40,7 +40,7 @@ static void uv__getaddrinfo_work(struct uv__work* w) { static void uv__getaddrinfo_done(struct uv__work* w, int status) { uv_getaddrinfo_t* req = container_of(w, uv_getaddrinfo_t, work_req); struct addrinfo *res = req->res; -#if __sun +#if defined(__sun) size_t hostlen; if (req->hostname) @@ -69,13 +69,13 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) { if (req->retcode == 0) { /* OK */ -#if EAI_NODATA /* FreeBSD deprecated EAI_NODATA */ +#if defined(EAI_NODATA) /* FreeBSD deprecated EAI_NODATA */ } else if (req->retcode == EAI_NONAME || req->retcode == EAI_NODATA) { #else } else if (req->retcode == EAI_NONAME) { #endif uv__set_sys_error(req->loop, ENOENT); /* FIXME compatibility hack */ -#if __sun +#if defined(__sun) } else if (req->retcode == EAI_MEMORY && hostlen >= MAXHOSTNAMELEN) { uv__set_sys_error(req->loop, ENOENT); #endif diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index 786897de97..2c61f910e6 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -31,18 +31,13 @@ # define inline __inline #endif -#undef HAVE_PORTS_FS - -#if __linux__ +#if defined(__linux__) # include "linux/syscalls.h" #endif /* __linux__ */ #if defined(__sun) # include # include -# ifdef PORT_SOURCE_FILE -# define HAVE_PORTS_FS 1 -# endif # define futimes(fd, tv) futimesat(fd, (void*)0, tv) #endif /* __sun */ @@ -110,14 +105,6 @@ enum { UV_TCP_SINGLE_ACCEPT = 0x400 /* Only accept() when idle. */ }; -__attribute__((unused)) -static void uv__req_init(uv_loop_t* loop, uv_req_t* req, uv_req_type type) { - req->type = type; - uv__req_register(loop, req); -} -#define uv__req_init(loop, req, type) \ - uv__req_init((loop), (uv_req_t*)(req), (type)) - /* core */ void uv__handle_init(uv_loop_t* loop, uv_handle_t* handle, uv_handle_type type); int uv__nonblock(int fd, int set); @@ -169,7 +156,7 @@ int uv__next_timeout(const uv_loop_t* loop); /* signal */ void uv__signal_close(uv_signal_t* handle); void uv__signal_global_once_init(void); -void uv__signal_loop_cleanup(); +void uv__signal_loop_cleanup(uv_loop_t* loop); /* thread pool */ void uv__work_submit(uv_loop_t* loop, @@ -179,6 +166,7 @@ void uv__work_submit(uv_loop_t* loop, void uv__work_done(uv_async_t* handle, int status); /* platform specific */ +uint64_t uv__hrtime(void); int uv__kqueue_init(uv_loop_t* loop); int uv__platform_loop_init(uv_loop_t* loop, int default_loop); void uv__platform_loop_delete(uv_loop_t* loop); @@ -242,4 +230,17 @@ static const int kFSEventStreamEventFlagItemIsSymlink = 0x00040000; #endif /* defined(__APPLE__) */ +__attribute__((unused)) +static void uv__req_init(uv_loop_t* loop, uv_req_t* req, uv_req_type type) { + req->type = type; + uv__req_register(loop, req); +} +#define uv__req_init(loop, req, type) \ + uv__req_init((loop), (uv_req_t*)(req), (type)) + +__attribute__((unused)) +static void uv__update_time(uv_loop_t* loop) { + loop->time = uv__hrtime() / 1000000; +} + #endif /* UV_UNIX_INTERNAL_H_ */ diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c index af9078e938..2ab0854beb 100644 --- a/deps/uv/src/unix/kqueue.c +++ b/deps/uv/src/unix/kqueue.c @@ -141,6 +141,12 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { ARRAY_SIZE(events), timeout == -1 ? NULL : &spec); + /* Update loop->time unconditionally. It's tempting to skip the update when + * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the + * operating system didn't reschedule our process while in the syscall. + */ + SAVE_ERRNO(uv__update_time(loop)); + if (nfds == 0) { assert(timeout != -1); return; @@ -244,10 +250,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { update_timeout: assert(timeout > 0); - diff = uv_hrtime() / 1000000; - assert(diff >= base); - diff -= base; - + diff = loop->time - base; if (diff >= (uint64_t) timeout) return; diff --git a/deps/uv/src/unix/linux/linux-core.c b/deps/uv/src/unix/linux/linux-core.c index 95df66766c..b591314ff0 100644 --- a/deps/uv/src/unix/linux/linux-core.c +++ b/deps/uv/src/unix/linux/linux-core.c @@ -57,7 +57,6 @@ # define CLOCK_BOOTTIME 7 #endif -static char buf[MAXPATHLEN + 1]; static void* args_mem; static struct { @@ -182,6 +181,12 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { ARRAY_SIZE(events), timeout); + /* Update loop->time unconditionally. It's tempting to skip the update when + * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the + * operating system didn't reschedule our process while in the syscall. + */ + SAVE_ERRNO(uv__update_time(loop)); + if (nfds == 0) { assert(timeout != -1); return; @@ -243,10 +248,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { update_timeout: assert(timeout > 0); - diff = uv_hrtime() / 1000000; - assert(diff >= base); - diff -= base; - + diff = loop->time - base; if (diff >= (uint64_t) timeout) return; @@ -255,7 +257,7 @@ update_timeout: } -uint64_t uv_hrtime() { +uint64_t uv__hrtime(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec); @@ -379,6 +381,7 @@ uv_err_t uv_resident_set_memory(size_t* rss) { size_t page_size = getpagesize(); char *cbuf; int foundExeEnd; + char buf[PATH_MAX + 1]; f = fopen("/proc/self/stat", "r"); if (!f) return uv__new_sys_error(errno); @@ -547,11 +550,13 @@ static void read_models(unsigned int numcpus, uv_cpu_info_t* ci) { static const char model_marker[] = ""; static const char speed_marker[] = ""; #endif + static const char bogus_model[] = "unknown"; unsigned int model_idx; unsigned int speed_idx; char buf[1024]; char* model; FILE* fp; + char* inferred_model; fp = fopen("/proc/cpuinfo", "r"); if (fp == NULL) @@ -580,6 +585,26 @@ static void read_models(unsigned int numcpus, uv_cpu_info_t* ci) { } } fclose(fp); + + /* Now we want to make sure that all the models contain *something*: + * it's not safe to leave them as null. + */ + if (model_idx == 0) { + /* No models at all: fake up the first one. */ + ci[0].model = strndup(bogus_model, sizeof(bogus_model) - 1); + model_idx = 1; + } + + /* Not enough models, but we do have at least one. So we'll just + * copy the rest down: it might be better to indicate somehow that + * the remaining ones have been guessed. + */ + inferred_model = ci[model_idx - 1].model; + + while (model_idx < numcpus) { + ci[model_idx].model = strndup(inferred_model, strlen(inferred_model)); + model_idx++; + } } diff --git a/deps/uv/src/unix/linux/syscalls.c b/deps/uv/src/unix/linux/syscalls.c index 6536215b18..1f0174a6e7 100644 --- a/deps/uv/src/unix/linux/syscalls.c +++ b/deps/uv/src/unix/linux/syscalls.c @@ -25,14 +25,14 @@ #include #include -#if __i386__ +#if defined(__i386__) # ifndef __NR_socketcall # define __NR_socketcall 102 # endif #endif -#if __arm__ -# if __thumb__ || __ARM_EABI__ +#if defined(__arm__) +# if defined(__thumb__) || defined(__ARM_EABI__) # define UV_SYSCALL_BASE 0 # else # define UV_SYSCALL_BASE 0x900000 @@ -40,168 +40,168 @@ #endif /* __arm__ */ #ifndef __NR_accept4 -# if __x86_64__ +# if defined(__x86_64__) # define __NR_accept4 288 -# elif __i386__ +# elif defined(__i386__) /* Nothing. Handled through socketcall(). */ -# elif __arm__ +# elif defined(__arm__) # define __NR_accept4 (UV_SYSCALL_BASE + 366) # endif #endif /* __NR_accept4 */ #ifndef __NR_eventfd -# if __x86_64__ +# if defined(__x86_64__) # define __NR_eventfd 284 -# elif __i386__ +# elif defined(__i386__) # define __NR_eventfd 323 -# elif __arm__ +# elif defined(__arm__) # define __NR_eventfd (UV_SYSCALL_BASE + 351) # endif #endif /* __NR_eventfd */ #ifndef __NR_eventfd2 -# if __x86_64__ +# if defined(__x86_64__) # define __NR_eventfd2 290 -# elif __i386__ +# elif defined(__i386__) # define __NR_eventfd2 328 -# elif __arm__ +# elif defined(__arm__) # define __NR_eventfd2 (UV_SYSCALL_BASE + 356) # endif #endif /* __NR_eventfd2 */ #ifndef __NR_epoll_create -# if __x86_64__ +# if defined(__x86_64__) # define __NR_epoll_create 213 -# elif __i386__ +# elif defined(__i386__) # define __NR_epoll_create 254 -# elif __arm__ +# elif defined(__arm__) # define __NR_epoll_create (UV_SYSCALL_BASE + 250) # endif #endif /* __NR_epoll_create */ #ifndef __NR_epoll_create1 -# if __x86_64__ +# if defined(__x86_64__) # define __NR_epoll_create1 291 -# elif __i386__ +# elif defined(__i386__) # define __NR_epoll_create1 329 -# elif __arm__ +# elif defined(__arm__) # define __NR_epoll_create1 (UV_SYSCALL_BASE + 357) # endif #endif /* __NR_epoll_create1 */ #ifndef __NR_epoll_ctl -# if __x86_64__ +# if defined(__x86_64__) # define __NR_epoll_ctl 233 /* used to be 214 */ -# elif __i386__ +# elif defined(__i386__) # define __NR_epoll_ctl 255 -# elif __arm__ +# elif defined(__arm__) # define __NR_epoll_ctl (UV_SYSCALL_BASE + 251) # endif #endif /* __NR_epoll_ctl */ #ifndef __NR_epoll_wait -# if __x86_64__ +# if defined(__x86_64__) # define __NR_epoll_wait 232 /* used to be 215 */ -# elif __i386__ +# elif defined(__i386__) # define __NR_epoll_wait 256 -# elif __arm__ +# elif defined(__arm__) # define __NR_epoll_wait (UV_SYSCALL_BASE + 252) # endif #endif /* __NR_epoll_wait */ #ifndef __NR_epoll_pwait -# if __x86_64__ +# if defined(__x86_64__) # define __NR_epoll_pwait 281 -# elif __i386__ +# elif defined(__i386__) # define __NR_epoll_pwait 319 -# elif __arm__ +# elif defined(__arm__) # define __NR_epoll_pwait (UV_SYSCALL_BASE + 346) # endif #endif /* __NR_epoll_pwait */ #ifndef __NR_inotify_init -# if __x86_64__ +# if defined(__x86_64__) # define __NR_inotify_init 253 -# elif __i386__ +# elif defined(__i386__) # define __NR_inotify_init 291 -# elif __arm__ +# elif defined(__arm__) # define __NR_inotify_init (UV_SYSCALL_BASE + 316) # endif #endif /* __NR_inotify_init */ #ifndef __NR_inotify_init1 -# if __x86_64__ +# if defined(__x86_64__) # define __NR_inotify_init1 294 -# elif __i386__ +# elif defined(__i386__) # define __NR_inotify_init1 332 -# elif __arm__ +# elif defined(__arm__) # define __NR_inotify_init1 (UV_SYSCALL_BASE + 360) # endif #endif /* __NR_inotify_init1 */ #ifndef __NR_inotify_add_watch -# if __x86_64__ +# if defined(__x86_64__) # define __NR_inotify_add_watch 254 -# elif __i386__ +# elif defined(__i386__) # define __NR_inotify_add_watch 292 -# elif __arm__ +# elif defined(__arm__) # define __NR_inotify_add_watch (UV_SYSCALL_BASE + 317) # endif #endif /* __NR_inotify_add_watch */ #ifndef __NR_inotify_rm_watch -# if __x86_64__ +# if defined(__x86_64__) # define __NR_inotify_rm_watch 255 -# elif __i386__ +# elif defined(__i386__) # define __NR_inotify_rm_watch 293 -# elif __arm__ +# elif defined(__arm__) # define __NR_inotify_rm_watch (UV_SYSCALL_BASE + 318) # endif #endif /* __NR_inotify_rm_watch */ #ifndef __NR_pipe2 -# if __x86_64__ +# if defined(__x86_64__) # define __NR_pipe2 293 -# elif __i386__ +# elif defined(__i386__) # define __NR_pipe2 331 -# elif __arm__ +# elif defined(__arm__) # define __NR_pipe2 (UV_SYSCALL_BASE + 359) # endif #endif /* __NR_pipe2 */ #ifndef __NR_recvmmsg -# if __x86_64__ +# if defined(__x86_64__) # define __NR_recvmmsg 299 -# elif __i386__ +# elif defined(__i386__) # define __NR_recvmmsg 337 -# elif __arm__ +# elif defined(__arm__) # define __NR_recvmmsg (UV_SYSCALL_BASE + 365) # endif #endif /* __NR_recvmsg */ #ifndef __NR_sendmmsg -# if __x86_64__ +# if defined(__x86_64__) # define __NR_sendmmsg 307 -# elif __i386__ +# elif defined(__i386__) # define __NR_sendmmsg 345 -# elif __arm__ +# elif defined(__arm__) # define __NR_sendmmsg (UV_SYSCALL_BASE + 374) # endif #endif /* __NR_sendmmsg */ #ifndef __NR_utimensat -# if __x86_64__ +# if defined(__x86_64__) # define __NR_utimensat 280 -# elif __i386__ +# elif defined(__i386__) # define __NR_utimensat 320 -# elif __arm__ +# elif defined(__arm__) # define __NR_utimensat (UV_SYSCALL_BASE + 348) # endif #endif /* __NR_utimensat */ int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) { -#if __i386__ +#if defined(__i386__) unsigned long args[4]; int r; @@ -221,7 +221,7 @@ int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) { errno = ENOSYS; return r; -#elif __NR_accept4 +#elif defined(__NR_accept4) return syscall(__NR_accept4, fd, addr, addrlen, flags); #else return errno = ENOSYS, -1; @@ -230,7 +230,7 @@ int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) { int uv__eventfd(unsigned int count) { -#if __NR_eventfd +#if defined(__NR_eventfd) return syscall(__NR_eventfd, count); #else return errno = ENOSYS, -1; @@ -239,7 +239,7 @@ int uv__eventfd(unsigned int count) { int uv__eventfd2(unsigned int count, int flags) { -#if __NR_eventfd2 +#if defined(__NR_eventfd2) return syscall(__NR_eventfd2, count, flags); #else return errno = ENOSYS, -1; @@ -248,7 +248,7 @@ int uv__eventfd2(unsigned int count, int flags) { int uv__epoll_create(int size) { -#if __NR_epoll_create +#if defined(__NR_epoll_create) return syscall(__NR_epoll_create, size); #else return errno = ENOSYS, -1; @@ -257,7 +257,7 @@ int uv__epoll_create(int size) { int uv__epoll_create1(int flags) { -#if __NR_epoll_create1 +#if defined(__NR_epoll_create1) return syscall(__NR_epoll_create1, flags); #else return errno = ENOSYS, -1; @@ -266,7 +266,7 @@ int uv__epoll_create1(int flags) { int uv__epoll_ctl(int epfd, int op, int fd, struct uv__epoll_event* events) { -#if __NR_epoll_ctl +#if defined(__NR_epoll_ctl) return syscall(__NR_epoll_ctl, epfd, op, fd, events); #else return errno = ENOSYS, -1; @@ -278,7 +278,7 @@ int uv__epoll_wait(int epfd, struct uv__epoll_event* events, int nevents, int timeout) { -#if __NR_epoll_wait +#if defined(__NR_epoll_wait) return syscall(__NR_epoll_wait, epfd, events, nevents, timeout); #else return errno = ENOSYS, -1; @@ -291,7 +291,7 @@ int uv__epoll_pwait(int epfd, int nevents, int timeout, const sigset_t* sigmask) { -#if __NR_epoll_pwait +#if defined(__NR_epoll_pwait) return syscall(__NR_epoll_pwait, epfd, events, @@ -306,7 +306,7 @@ int uv__epoll_pwait(int epfd, int uv__inotify_init(void) { -#if __NR_inotify_init +#if defined(__NR_inotify_init) return syscall(__NR_inotify_init); #else return errno = ENOSYS, -1; @@ -315,7 +315,7 @@ int uv__inotify_init(void) { int uv__inotify_init1(int flags) { -#if __NR_inotify_init1 +#if defined(__NR_inotify_init1) return syscall(__NR_inotify_init1, flags); #else return errno = ENOSYS, -1; @@ -324,7 +324,7 @@ int uv__inotify_init1(int flags) { int uv__inotify_add_watch(int fd, const char* path, __u32 mask) { -#if __NR_inotify_add_watch +#if defined(__NR_inotify_add_watch) return syscall(__NR_inotify_add_watch, fd, path, mask); #else return errno = ENOSYS, -1; @@ -333,7 +333,7 @@ int uv__inotify_add_watch(int fd, const char* path, __u32 mask) { int uv__inotify_rm_watch(int fd, __s32 wd) { -#if __NR_inotify_rm_watch +#if defined(__NR_inotify_rm_watch) return syscall(__NR_inotify_rm_watch, fd, wd); #else return errno = ENOSYS, -1; @@ -342,7 +342,7 @@ int uv__inotify_rm_watch(int fd, __s32 wd) { int uv__pipe2(int pipefd[2], int flags) { -#if __NR_pipe2 +#if defined(__NR_pipe2) return syscall(__NR_pipe2, pipefd, flags); #else return errno = ENOSYS, -1; @@ -354,7 +354,7 @@ int uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen, unsigned int flags) { -#if __NR_sendmmsg +#if defined(__NR_sendmmsg) return syscall(__NR_sendmmsg, fd, mmsg, vlen, flags); #else return errno = ENOSYS, -1; @@ -367,7 +367,7 @@ int uv__recvmmsg(int fd, unsigned int vlen, unsigned int flags, struct timespec* timeout) { -#if __NR_recvmmsg +#if defined(__NR_recvmmsg) return syscall(__NR_recvmmsg, fd, mmsg, vlen, flags, timeout); #else return errno = ENOSYS, -1; @@ -380,7 +380,7 @@ int uv__utimesat(int dirfd, const struct timespec times[2], int flags) { -#if __NR_utimensat +#if defined(__NR_utimensat) return syscall(__NR_utimensat, dirfd, path, times, flags); #else return errno = ENOSYS, -1; diff --git a/deps/uv/src/unix/loop-watcher.c b/deps/uv/src/unix/loop-watcher.c index 9d1414b846..a07569e403 100644 --- a/deps/uv/src/unix/loop-watcher.c +++ b/deps/uv/src/unix/loop-watcher.c @@ -31,6 +31,8 @@ \ int uv_##name##_start(uv_##name##_t* handle, uv_##name##_cb cb) { \ if (uv__is_active(handle)) return 0; \ + if (cb == NULL) \ + return uv__set_artificial_error(handle->loop, UV_EINVAL); \ ngx_queue_insert_head(&handle->loop->name##_handles, &handle->queue); \ handle->name##_cb = cb; \ uv__handle_start(handle); \ @@ -49,7 +51,7 @@ ngx_queue_t* q; \ ngx_queue_foreach(q, &loop->name##_handles) { \ h = ngx_queue_data(q, uv_##name##_t, queue); \ - if (h->name##_cb) h->name##_cb(h, 0); \ + h->name##_cb(h, 0); \ } \ } \ \ diff --git a/deps/uv/src/unix/loop.c b/deps/uv/src/unix/loop.c index e63f12a622..5672abe9f0 100644 --- a/deps/uv/src/unix/loop.c +++ b/deps/uv/src/unix/loop.c @@ -49,7 +49,7 @@ int uv__loop_init(uv_loop_t* loop, int default_loop) { ngx_queue_init(&loop->watcher_queue); loop->closing_handles = NULL; - loop->time = uv_hrtime() / 1000000; + loop->time = uv__hrtime() / 1000000; loop->async_pipefd[0] = -1; loop->async_pipefd[1] = -1; loop->signal_pipefd[0] = -1; diff --git a/deps/uv/src/unix/netbsd.c b/deps/uv/src/unix/netbsd.c index d9fb426d65..0fbcf108c1 100644 --- a/deps/uv/src/unix/netbsd.c +++ b/deps/uv/src/unix/netbsd.c @@ -56,7 +56,7 @@ void uv__platform_loop_delete(uv_loop_t* loop) { } -uint64_t uv_hrtime(void) { +uint64_t uv__hrtime(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec); diff --git a/deps/uv/src/unix/openbsd.c b/deps/uv/src/unix/openbsd.c index 88f20b0153..4dfcd76b50 100644 --- a/deps/uv/src/unix/openbsd.c +++ b/deps/uv/src/unix/openbsd.c @@ -52,7 +52,7 @@ void uv__platform_loop_delete(uv_loop_t* loop) { } -uint64_t uv_hrtime(void) { +uint64_t uv__hrtime(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec); diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c index c4df81a974..4c5714fa04 100644 --- a/deps/uv/src/unix/process.c +++ b/deps/uv/src/unix/process.c @@ -112,7 +112,7 @@ static void uv__chld(uv_signal_t* handle, int signum) { int uv__make_socketpair(int fds[2], int flags) { -#if __linux__ +#if defined(__linux__) static int no_cloexec; if (no_cloexec) @@ -148,7 +148,7 @@ skip: int uv__make_pipe(int fds[2], int flags) { -#if __linux__ +#if defined(__linux__) static int no_pipe2; if (no_pipe2) @@ -185,77 +185,69 @@ skip: * zero on success. */ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) { - int fd = -1; - switch (container->flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | - UV_INHERIT_STREAM)) { - case UV_IGNORE: - return 0; - case UV_CREATE_PIPE: - assert(container->data.stream != NULL); - - if (container->data.stream->type != UV_NAMED_PIPE) { - errno = EINVAL; - return -1; - } + int mask; + int fd; - return uv__make_socketpair(fds, 0); - case UV_INHERIT_FD: - case UV_INHERIT_STREAM: - if (container->flags & UV_INHERIT_FD) { - fd = container->data.fd; - } else { - fd = uv__stream_fd(container->data.stream); - } + mask = UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | UV_INHERIT_STREAM; - if (fd == -1) { - errno = EINVAL; - return -1; - } + switch (container->flags & mask) { + case UV_IGNORE: + return 0; + + case UV_CREATE_PIPE: + assert(container->data.stream != NULL); + if (container->data.stream->type != UV_NAMED_PIPE) { + errno = EINVAL; + return -1; + } + return uv__make_socketpair(fds, 0); - fds[1] = fd; + case UV_INHERIT_FD: + case UV_INHERIT_STREAM: + if (container->flags & UV_INHERIT_FD) + fd = container->data.fd; + else + fd = uv__stream_fd(container->data.stream); - return 0; - default: - assert(0 && "Unexpected flags"); + if (fd == -1) { + errno = EINVAL; return -1; - } -} + } + fds[1] = fd; + return 0; -static int uv__process_stdio_flags(uv_stdio_container_t* container, - int writable) { - if (container->data.stream->type == UV_NAMED_PIPE && - ((uv_pipe_t*)container->data.stream)->ipc) { - return UV_STREAM_READABLE | UV_STREAM_WRITABLE; - } else if (writable) { - return UV_STREAM_WRITABLE; - } else { - return UV_STREAM_READABLE; + default: + assert(0 && "Unexpected flags"); + return -1; } } static int uv__process_open_stream(uv_stdio_container_t* container, - int fds[2], + int pipefds[2], int writable) { - int child_fd; int flags; - int fd; - - fd = fds[0]; - child_fd = fds[1]; - /* No need to create stream */ - if (!(container->flags & UV_CREATE_PIPE) || fd < 0) + if (!(container->flags & UV_CREATE_PIPE) || pipefds[0] < 0) return 0; - assert(child_fd >= 0); - close(child_fd); + if (close(pipefds[1])) + if (errno != EINTR && errno != EINPROGRESS) + abort(); - uv__nonblock(fd, 1); - flags = uv__process_stdio_flags(container, writable); + pipefds[1] = -1; + uv__nonblock(pipefds[0], 1); - return uv__stream_open((uv_stream_t*)container->data.stream, fd, flags); + if (container->data.stream->type == UV_NAMED_PIPE && + ((uv_pipe_t*)container->data.stream)->ipc) + flags = UV_STREAM_READABLE | UV_STREAM_WRITABLE; + else if (writable) + flags = UV_STREAM_WRITABLE; + else + flags = UV_STREAM_READABLE; + + return uv__stream_open(container->data.stream, pipefds[0], flags); } @@ -391,14 +383,6 @@ int uv_spawn(uv_loop_t* loop, if (uv__process_init_stdio(options.stdio + i, pipes[i])) goto error; - /* swap stdin file descriptors, it's the only writable stream */ - { - int* p = pipes[0]; - int t = p[0]; - p[0] = p[1]; - p[1] = t; - } - /* This pipe is used by the parent to wait until * the child has called `execve()`. We need this * to avoid the following race condition: diff --git a/deps/uv/src/unix/signal.c b/deps/uv/src/unix/signal.c index 359f45e8ae..d3ab6035bf 100644 --- a/deps/uv/src/unix/signal.c +++ b/deps/uv/src/unix/signal.c @@ -54,7 +54,7 @@ RB_GENERATE_STATIC(uv__signal_tree_s, uv__signal_compare) -static void uv__signal_global_init() { +static void uv__signal_global_init(void) { if (uv__make_pipe(uv__signal_lock_pipefd, 0)) abort(); @@ -69,7 +69,7 @@ void uv__signal_global_once_init(void) { -static int uv__signal_lock() { +static int uv__signal_lock(void) { int r; char data; @@ -81,7 +81,7 @@ static int uv__signal_lock() { } -static int uv__signal_unlock() { +static int uv__signal_unlock(void) { int r; char data = 42; @@ -133,7 +133,7 @@ inline static uv_signal_t* uv__signal_first_handle(int signum) { } -void uv__signal_handler(int signum) { +static void uv__signal_handler(int signum) { uv__signal_msg_t msg; uv_signal_t* handle; diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index a3193a9b07..77d74ea706 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -128,10 +128,10 @@ void uv__stream_init(uv_loop_t* loop, void uv__stream_osx_select(void* arg) { uv_stream_t* stream; uv__stream_select_t* s; - fd_set read; - fd_set write; - fd_set error; - struct timeval timeout; + char buf[1024]; + fd_set sread; + fd_set swrite; + fd_set serror; int events; int fd; int r; @@ -152,20 +152,19 @@ void uv__stream_osx_select(void* arg) { break; /* Watch fd using select(2) */ - FD_ZERO(&read); - FD_ZERO(&write); - FD_ZERO(&error); + FD_ZERO(&sread); + FD_ZERO(&swrite); + FD_ZERO(&serror); if (uv_is_readable(stream)) - FD_SET(fd, &read); + FD_SET(fd, &sread); if (uv_is_writable(stream)) - FD_SET(fd, &write); - FD_SET(fd, &error); - FD_SET(s->int_fd, &read); + FD_SET(fd, &swrite); + FD_SET(fd, &serror); + FD_SET(s->int_fd, &sread); - timeout.tv_sec = 0; - timeout.tv_usec = 250000; /* 250 ms timeout */ - r = select(max_fd + 1, &read, &write, &error, &timeout); + /* Wait indefinitely for fd events */ + r = select(max_fd + 1, &sread, &swrite, &serror, NULL); if (r == -1) { if (errno == EINTR) continue; @@ -178,13 +177,33 @@ void uv__stream_osx_select(void* arg) { if (r == 0) continue; + /* Empty socketpair's buffer in case of interruption */ + if (FD_ISSET(s->int_fd, &sread)) + while (1) { + r = read(s->int_fd, buf, sizeof(buf)); + + if (r == sizeof(buf)) + continue; + + if (r != -1) + break; + + if (errno == EAGAIN || errno == EWOULDBLOCK) + break; + + if (errno == EINTR) + continue; + + abort(); + } + /* Handle events */ events = 0; - if (FD_ISSET(fd, &read)) + if (FD_ISSET(fd, &sread)) events |= UV__POLLIN; - if (FD_ISSET(fd, &write)) + if (FD_ISSET(fd, &swrite)) events |= UV__POLLOUT; - if (FD_ISSET(fd, &error)) + if (FD_ISSET(fd, &serror)) events |= UV__POLLERR; uv_mutex_lock(&s->mutex); @@ -599,30 +618,10 @@ int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) { } -uv_write_t* uv_write_queue_head(uv_stream_t* stream) { - ngx_queue_t* q; - uv_write_t* req; - - if (ngx_queue_empty(&stream->write_queue)) { - return NULL; - } - - q = ngx_queue_head(&stream->write_queue); - if (!q) { - return NULL; - } - - req = ngx_queue_data(q, struct uv_write_s, queue); - assert(req); - - return req; -} - - static void uv__drain(uv_stream_t* stream) { uv_shutdown_t* req; - assert(!uv_write_queue_head(stream)); + assert(ngx_queue_empty(&stream->write_queue)); assert(stream->write_queue_size == 0); uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT); @@ -683,33 +682,24 @@ static void uv__write_req_finish(uv_write_t* req) { } -/* On success returns NULL. On error returns a pointer to the write request - * which had the error. - */ static void uv__write(uv_stream_t* stream) { - uv_write_t* req; struct iovec* iov; + ngx_queue_t* q; + uv_write_t* req; int iovcnt; ssize_t n; - if (stream->flags & UV_CLOSING) { - /* Handle was closed this tick. We've received a stale - * 'is writable' callback from the event loop, ignore. - */ - return; - } - start: assert(uv__stream_fd(stream) >= 0); - /* Get the request at the head of the queue. */ - req = uv_write_queue_head(stream); - if (!req) { + if (ngx_queue_empty(&stream->write_queue)) { assert(stream->write_queue_size == 0); return; } + q = ngx_queue_head(&stream->write_queue); + req = ngx_queue_data(q, uv_write_t, queue); assert(req->handle == stream); /* @@ -860,9 +850,8 @@ static void uv__write_callbacks(uv_stream_t* stream) { assert(ngx_queue_empty(&stream->write_completed_queue)); /* Write queue drained. */ - if (!uv_write_queue_head(stream)) { + if (ngx_queue_empty(&stream->write_queue)) uv__drain(stream); - } } @@ -1221,8 +1210,10 @@ int uv_write(uv_write_t* req, uv_stream_t* stream, uv_buf_t bufs[], int bufcnt, } -int uv__read_start_common(uv_stream_t* stream, uv_alloc_cb alloc_cb, - uv_read_cb read_cb, uv_read2_cb read2_cb) { +static int uv__read_start_common(uv_stream_t* stream, + uv_alloc_cb alloc_cb, + uv_read_cb read_cb, + uv_read2_cb read2_cb) { assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE || stream->type == UV_TTY); diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c index 48b1fca171..3fbb50c9be 100644 --- a/deps/uv/src/unix/sunos.c +++ b/deps/uv/src/unix/sunos.c @@ -39,15 +39,13 @@ #include #include -#if HAVE_PORTS_FS -# include -# include - -# define PORT_FIRED 0x69 -# define PORT_UNUSED 0x0 -# define PORT_LOADED 0x99 -# define PORT_DELETED -1 -#endif +#include +#include + +#define PORT_FIRED 0x69 +#define PORT_UNUSED 0x0 +#define PORT_LOADED 0x99 +#define PORT_DELETED -1 #if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64) #define PROCFS_FILE_OFFSET_BITS_HACK 1 @@ -152,6 +150,12 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { abort(); } + /* Update loop->time unconditionally. It's tempting to skip the update when + * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the + * operating system didn't reschedule our process while in the syscall. + */ + SAVE_ERRNO(uv__update_time(loop)); + if (events[0].portev_source == 0) { if (timeout == 0) return; @@ -213,10 +217,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { update_timeout: assert(timeout > 0); - diff = uv_hrtime() / 1000000; - assert(diff >= base); - diff -= base; - + diff = loop->time - base; if (diff >= (uint64_t) timeout) return; @@ -225,8 +226,8 @@ update_timeout: } -uint64_t uv_hrtime() { - return (gethrtime()); +uint64_t uv__hrtime(void) { + return gethrtime(); } @@ -272,7 +273,8 @@ void uv_loadavg(double avg[3]) { } -#if HAVE_PORTS_FS +#if defined(PORT_SOURCE_FILE) + static void uv__fs_event_rearm(uv_fs_event_t *handle) { if (handle->fd == -1) return; @@ -386,7 +388,7 @@ void uv__fs_event_close(uv_fs_event_t* handle) { uv__handle_stop(handle); } -#else /* !HAVE_PORTS_FS */ +#else /* !defined(PORT_SOURCE_FILE) */ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, @@ -402,7 +404,7 @@ void uv__fs_event_close(uv_fs_event_t* handle) { UNREACHABLE(); } -#endif /* HAVE_PORTS_FS */ +#endif /* defined(PORT_SOURCE_FILE) */ char** uv_setup_args(int argc, char** argv) { diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c index 0583cb474c..4fd5d2f58f 100644 --- a/deps/uv/src/unix/thread.c +++ b/deps/uv/src/unix/thread.c @@ -354,7 +354,7 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { struct timespec ts; uint64_t abstime; - abstime = uv_hrtime() + timeout; + abstime = uv__hrtime() + timeout; ts.tv_sec = abstime / NANOSEC; ts.tv_nsec = abstime % NANOSEC; r = pthread_cond_timedwait(cond, mutex, &ts); diff --git a/deps/uv/src/unix/threadpool.c b/deps/uv/src/unix/threadpool.c index ee428201a5..b071e4a56d 100644 --- a/deps/uv/src/unix/threadpool.c +++ b/deps/uv/src/unix/threadpool.c @@ -139,7 +139,7 @@ void uv__work_submit(uv_loop_t* loop, } -int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) { +static int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) { int cancelled; uv_mutex_lock(&mutex); @@ -158,6 +158,7 @@ int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) { w->work = uv__cancelled; uv_mutex_lock(&loop->wq_mutex); ngx_queue_insert_tail(&loop->wq, &w->wq); + uv_async_send(&loop->wq_async); uv_mutex_unlock(&loop->wq_mutex); return 0; diff --git a/deps/uv/src/unix/tty.c b/deps/uv/src/unix/tty.c index faf94716cc..49efee7f53 100644 --- a/deps/uv/src/unix/tty.c +++ b/deps/uv/src/unix/tty.c @@ -140,7 +140,7 @@ uv_handle_type uv_guess_handle(uv_file file) { } -void uv_tty_reset_mode() { +void uv_tty_reset_mode(void) { if (orig_termios_fd >= 0) { tcsetattr(orig_termios_fd, TCSANOW, &orig_termios); } diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c index 4b242f6466..f79b09cd80 100644 --- a/deps/uv/src/unix/udp.c +++ b/deps/uv/src/unix/udp.c @@ -556,7 +556,7 @@ int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, static int uv__setsockopt_maybe_char(uv_udp_t* handle, int option, int val) { -#if __sun +#if defined(__sun) char arg = val; #else int arg = val; diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c index 3df3399bc1..0876feda64 100644 --- a/deps/uv/src/win/core.c +++ b/deps/uv/src/win/core.c @@ -252,57 +252,47 @@ static void uv_poll_ex(uv_loop_t* loop, int block) { !ngx_queue_empty(&(loop)->active_reqs) || \ (loop)->endgame_handles != NULL) -#define UV_LOOP_ONCE(loop, poll) \ - do { \ - uv_update_time((loop)); \ - uv_process_timers((loop)); \ - \ - /* Call idle callbacks if nothing to do. */ \ - if ((loop)->pending_reqs_tail == NULL && \ - (loop)->endgame_handles == NULL) { \ - uv_idle_invoke((loop)); \ - } \ - \ - uv_process_reqs((loop)); \ - uv_process_endgames((loop)); \ - \ - if (!UV_LOOP_ALIVE((loop))) { \ - break; \ - } \ - \ - uv_prepare_invoke((loop)); \ - \ - poll((loop), (loop)->idle_handles == NULL && \ - (loop)->pending_reqs_tail == NULL && \ - (loop)->endgame_handles == NULL && \ - UV_LOOP_ALIVE((loop))); \ - \ - uv_check_invoke((loop)); \ - } while (0); - -#define UV_LOOP(loop, poll) \ - while (UV_LOOP_ALIVE((loop))) { \ - UV_LOOP_ONCE(loop, poll) \ - } +int uv_run2(uv_loop_t *loop, uv_run_mode mode) { + int r; + void (*poll)(uv_loop_t* loop, int block); + + if (pGetQueuedCompletionStatusEx) + poll = &uv_poll_ex; + else + poll = &uv_poll; + + r = UV_LOOP_ALIVE(loop); + while (r) { + uv_update_time(loop); + uv_process_timers(loop); + + /* Call idle callbacks if nothing to do. */ + if (loop->pending_reqs_tail == NULL && + loop->endgame_handles == NULL) { + uv_idle_invoke(loop); + } + uv_process_reqs(loop); + uv_process_endgames(loop); -int uv_run_once(uv_loop_t* loop) { - if (pGetQueuedCompletionStatusEx) { - UV_LOOP_ONCE(loop, uv_poll_ex); - } else { - UV_LOOP_ONCE(loop, uv_poll); + uv_prepare_invoke(loop); + + (*poll)(loop, loop->idle_handles == NULL && + loop->pending_reqs_tail == NULL && + loop->endgame_handles == NULL && + UV_LOOP_ALIVE(loop) && + !(mode & UV_RUN_NOWAIT)); + + uv_check_invoke(loop); + r = UV_LOOP_ALIVE(loop); + + if (mode & (UV_RUN_ONCE | UV_RUN_NOWAIT)) + break; } - return UV_LOOP_ALIVE(loop); + return r; } int uv_run(uv_loop_t* loop) { - if (pGetQueuedCompletionStatusEx) { - UV_LOOP(loop, uv_poll_ex); - } else { - UV_LOOP(loop, uv_poll); - } - - assert(!UV_LOOP_ALIVE((loop))); - return 0; + return uv_run2(loop, UV_RUN_DEFAULT); } diff --git a/deps/uv/src/win/loop-watcher.c b/deps/uv/src/win/loop-watcher.c index 9fff631c48..65080ff662 100644 --- a/deps/uv/src/win/loop-watcher.c +++ b/deps/uv/src/win/loop-watcher.c @@ -52,6 +52,9 @@ void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) { if (handle->flags & UV_HANDLE_ACTIVE) \ return 0; \ \ + if (cb == NULL) \ + return uv__set_artificial_error(handle->loop, UV_EINVAL); \ + \ old_head = loop->name##_handles; \ \ handle->name##_next = old_head; \ diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c index adb66a62e5..92f4604c27 100644 --- a/deps/uv/src/win/tty.c +++ b/deps/uv/src/win/tty.c @@ -1865,7 +1865,7 @@ void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle, } -void uv_tty_reset_mode() { +void uv_tty_reset_mode(void) { /* Not necessary to do anything. */ ; } diff --git a/deps/uv/test/benchmark-getaddrinfo.c b/deps/uv/test/benchmark-getaddrinfo.c index 8ee0c50add..4a57b4417f 100644 --- a/deps/uv/test/benchmark-getaddrinfo.c +++ b/deps/uv/test/benchmark-getaddrinfo.c @@ -26,7 +26,7 @@ #define CONCURRENT_CALLS 10 #define TOTAL_CALLS 10000 -const char* name = "localhost"; +static const char* name = "localhost"; static uv_loop_t* loop; diff --git a/deps/uv/test/benchmark-list.h b/deps/uv/test/benchmark-list.h index ed6d14158d..1e843071c0 100644 --- a/deps/uv/test/benchmark-list.h +++ b/deps/uv/test/benchmark-list.h @@ -73,6 +73,7 @@ BENCHMARK_DECLARE (async_pummel_4) BENCHMARK_DECLARE (async_pummel_8) BENCHMARK_DECLARE (spawn) BENCHMARK_DECLARE (thread_create) +BENCHMARK_DECLARE (million_async) BENCHMARK_DECLARE (million_timers) HELPER_DECLARE (tcp4_blackhole_server) HELPER_DECLARE (tcp_pump_server) @@ -157,5 +158,6 @@ TASK_LIST_START BENCHMARK_ENTRY (spawn) BENCHMARK_ENTRY (thread_create) + BENCHMARK_ENTRY (million_async) BENCHMARK_ENTRY (million_timers) TASK_LIST_END diff --git a/deps/uv/test/benchmark-million-async.c b/deps/uv/test/benchmark-million-async.c new file mode 100644 index 0000000000..e03a713471 --- /dev/null +++ b/deps/uv/test/benchmark-million-async.c @@ -0,0 +1,112 @@ +/* Copyright Joyent, Inc. and other Node 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 "task.h" +#include "uv.h" + +struct async_container { + unsigned async_events; + unsigned handles_seen; + uv_async_t async_handles[1024 * 1024]; +}; + +static volatile int done; +static uv_thread_t thread_id; +static struct async_container* container; + + +static unsigned fastrand(void) { + static unsigned g = 0; + g = g * 214013 + 2531011; + return g; +} + + +static void thread_cb(void* arg) { + unsigned i; + + while (done == 0) { + i = fastrand() % ARRAY_SIZE(container->async_handles); + uv_async_send(container->async_handles + i); + } +} + + +static void async_cb(uv_async_t* handle, int status) { + container->async_events++; + handle->data = handle; +} + + +static void timer_cb(uv_timer_t* handle, int status) { + unsigned i; + + done = 1; + ASSERT(0 == uv_thread_join(&thread_id)); + + for (i = 0; i < ARRAY_SIZE(container->async_handles); i++) { + uv_async_t* handle = container->async_handles + i; + + if (handle->data != NULL) + container->handles_seen++; + + uv_close((uv_handle_t*) handle, NULL); + } + + uv_close((uv_handle_t*) handle, NULL); +} + + +BENCHMARK_IMPL(million_async) { + uv_timer_t timer_handle; + uv_async_t* handle; + uv_loop_t* loop; + int timeout; + unsigned i; + + loop = uv_default_loop(); + timeout = 5000; + + container = malloc(sizeof(*container)); + ASSERT(container != NULL); + container->async_events = 0; + container->handles_seen = 0; + + for (i = 0; i < ARRAY_SIZE(container->async_handles); i++) { + handle = container->async_handles + i; + ASSERT(0 == uv_async_init(loop, handle, async_cb)); + handle->data = NULL; + } + + ASSERT(0 == uv_timer_init(loop, &timer_handle)); + ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, timeout, 0)); + ASSERT(0 == uv_thread_create(&thread_id, thread_cb, NULL)); + ASSERT(0 == uv_run(loop)); + printf("%s async events in %.1f seconds (%s/s, %s unique handles seen)\n", + fmt(container->async_events), + timeout / 1000., + fmt(container->async_events / (timeout / 1000.)), + fmt(container->handles_seen)); + free(container); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/uv/test/benchmark-ping-pongs.c b/deps/uv/test/benchmark-ping-pongs.c index e1de83df9d..4518ef8d2f 100644 --- a/deps/uv/test/benchmark-ping-pongs.c +++ b/deps/uv/test/benchmark-ping-pongs.c @@ -174,7 +174,7 @@ static void pinger_connect_cb(uv_connect_t* req, int status) { } -static void pinger_new() { +static void pinger_new(void) { int r; struct sockaddr_in client_addr = uv_ip4_addr("0.0.0.0", 0); struct sockaddr_in server_addr = uv_ip4_addr("127.0.0.1", TEST_PORT); diff --git a/deps/uv/test/benchmark-pump.c b/deps/uv/test/benchmark-pump.c index 2394425355..bf81c4f81a 100644 --- a/deps/uv/test/benchmark-pump.c +++ b/deps/uv/test/benchmark-pump.c @@ -117,7 +117,7 @@ static void show_stats(uv_timer_t* handle, int status) { } -static void read_show_stats() { +static void read_show_stats(void) { int64_t diff; uv_update_time(loop); @@ -129,13 +129,7 @@ static void read_show_stats() { -void write_sockets_close_cb(uv_handle_t* handle) { - /* If any client closes, the process is done. */ - exit(0); -} - - -void read_sockets_close_cb(uv_handle_t* handle) { +static void read_sockets_close_cb(uv_handle_t* handle) { free(handle); read_sockets--; @@ -149,7 +143,7 @@ void read_sockets_close_cb(uv_handle_t* handle) { } -static void start_stats_collection() { +static void start_stats_collection(void) { int r; /* Show-stats timer */ @@ -231,7 +225,7 @@ static void connect_cb(uv_connect_t* req, int status) { } -static void maybe_connect_some() { +static void maybe_connect_some(void) { uv_connect_t* req; uv_tcp_t* tcp; uv_pipe_t* pipe; @@ -302,7 +296,7 @@ typedef struct req_list_s { static req_list_t* req_freelist = NULL; -static uv_req_t* req_alloc() { +static uv_req_t* req_alloc(void) { req_list_t* req; req = req_freelist; @@ -407,7 +401,7 @@ HELPER_IMPL(pipe_pump_server) { } -void tcp_pump(int n) { +static void tcp_pump(int n) { ASSERT(n <= MAX_WRITE_HANDLES); TARGET_CONNECTIONS = n; type = TCP; @@ -425,7 +419,7 @@ void tcp_pump(int n) { } -void pipe_pump(int n) { +static void pipe_pump(int n) { ASSERT(n <= MAX_WRITE_HANDLES); TARGET_CONNECTIONS = n; type = PIPE; diff --git a/deps/uv/test/benchmark-spawn.c b/deps/uv/test/benchmark-spawn.c index 43a71834a6..ca0e8569e1 100644 --- a/deps/uv/test/benchmark-spawn.c +++ b/deps/uv/test/benchmark-spawn.c @@ -44,10 +44,10 @@ static int process_open; static int pipe_open; -static void spawn(); +static void spawn(void); -void maybe_spawn() { +static void maybe_spawn(void) { if (process_open == 0 && pipe_open == 0) { done++; if (done < N) { @@ -71,7 +71,7 @@ static void exit_cb(uv_process_t* process, int exit_status, int term_signal) { } -uv_buf_t on_alloc(uv_handle_t* handle, size_t suggested_size) { +static uv_buf_t on_alloc(uv_handle_t* handle, size_t suggested_size) { uv_buf_t buf; buf.base = output + output_used; buf.len = OUTPUT_SIZE - output_used; @@ -79,14 +79,14 @@ uv_buf_t on_alloc(uv_handle_t* handle, size_t suggested_size) { } -void pipe_close_cb(uv_handle_t* pipe) { +static void pipe_close_cb(uv_handle_t* pipe) { ASSERT(pipe_open == 1); pipe_open = 0; maybe_spawn(); } -void on_read(uv_stream_t* pipe, ssize_t nread, uv_buf_t buf) { +static void on_read(uv_stream_t* pipe, ssize_t nread, uv_buf_t buf) { uv_err_t err = uv_last_error(loop); if (nread > 0) { @@ -100,7 +100,7 @@ void on_read(uv_stream_t* pipe, ssize_t nread, uv_buf_t buf) { } -static void spawn() { +static void spawn(void) { uv_stdio_container_t stdio[2]; int r; diff --git a/deps/uv/test/dns-server.c b/deps/uv/test/dns-server.c index e541e781c6..f89c3bcfe8 100644 --- a/deps/uv/test/dns-server.c +++ b/deps/uv/test/dns-server.c @@ -63,9 +63,18 @@ static void on_connection(uv_stream_t*, int status); #define LEN_OFFSET 0 #define QUERYID_OFFSET 2 -unsigned char DNSRsp[] = {0, 43, 0, 0, 0x81, 0x80, 0, 1, 0, 1, 0, 0, 0, 0 }; -unsigned char qrecord[] = {5, 'e', 'c', 'h', 'o', 's', 3, 's', 'r', 'v', 0, 0, 1, 0, 1}; -unsigned char arecord[] = {0xc0, 0x0c, 0, 1, 0, 1, 0, 0, 5, 0xbd, 0, 4, 10, 0, 1, 1 }; + +static unsigned char DNSRsp[] = { + 0, 43, 0, 0, 0x81, 0x80, 0, 1, 0, 1, 0, 0, 0, 0 +}; + +static unsigned char qrecord[] = { + 5, 'e', 'c', 'h', 'o', 's', 3, 's', 'r', 'v', 0, 0, 1, 0, 1 +}; + +static unsigned char arecord[] = { + 0xc0, 0x0c, 0, 1, 0, 1, 0, 0, 5, 0xbd, 0, 4, 10, 0, 1, 1 +}; static void after_write(uv_write_t* req, int status) { diff --git a/deps/uv/test/runner-unix.c b/deps/uv/test/runner-unix.c index f6ea45e140..267cc7cbf4 100644 --- a/deps/uv/test/runner-unix.c +++ b/deps/uv/test/runner-unix.c @@ -313,7 +313,7 @@ void process_cleanup(process_info_t *p) { /* Move the console cursor one line up and back to the first column. */ -void rewind_cursor() { +void rewind_cursor(void) { fprintf(stderr, "\033[2K\r"); } diff --git a/deps/uv/test/runner.c b/deps/uv/test/runner.c index 5925ec7524..01d6c773d2 100644 --- a/deps/uv/test/runner.c +++ b/deps/uv/test/runner.c @@ -39,10 +39,18 @@ static void log_progress(int total, int passed, int failed, const char* name) { const char* fmt(double d) { + static char buf[1024]; + static char* p; uint64_t v; - char* p; - p = (char *) calloc(1, 32) + 31; /* leaks memory */ + if (p == NULL) + p = buf; + + p += 31; + + if (p >= buf + sizeof(buf)) + return ""; + v = (uint64_t) d; #if 0 /* works but we don't care about fractional precision */ diff --git a/deps/uv/test/runner.h b/deps/uv/test/runner.h index e1bd83bca2..3919007bb5 100644 --- a/deps/uv/test/runner.h +++ b/deps/uv/test/runner.h @@ -38,7 +38,7 @@ typedef struct { char *task_name; char *process_name; - int (*main)(); + int (*main)(void); int is_helper; int show_output; } task_entry_t, bench_entry_t; @@ -55,7 +55,7 @@ typedef struct { }; #define TEST_DECLARE(name) \ - int run_test_##name(); + int run_test_##name(void); #define TEST_ENTRY(name) \ { #name, #name, &run_test_##name, 0, 0 }, @@ -64,13 +64,13 @@ typedef struct { { #name, #name, &run_test_##name, 0, 1 }, #define BENCHMARK_DECLARE(name) \ - int run_benchmark_##name(); + int run_benchmark_##name(void); #define BENCHMARK_ENTRY(name) \ { #name, #name, &run_benchmark_##name, 0, 0 }, #define HELPER_DECLARE(name) \ - int run_helper_##name(); + int run_helper_##name(void); #define HELPER_ENTRY(task_name, name) \ { #task_name, #name, &run_helper_##name, 1, 0 }, @@ -123,7 +123,7 @@ void print_tests(FILE* stream); */ /* Do platform-specific initialization. */ -void platform_init(); +void platform_init(int argc, char** argv); /* Invoke "argv[0] test-name [test-part]". Store process info in *p. */ /* Make sure that all stdio output of the processes is buffered up. */ @@ -154,6 +154,6 @@ int process_reap(process_info_t *p); void process_cleanup(process_info_t *p); /* Move the console cursor one line up and back to the first column. */ -void rewind_cursor(); +void rewind_cursor(void); #endif /* RUNNER_H_ */ diff --git a/deps/uv/test/task.h b/deps/uv/test/task.h index b351c423be..de7c80ec3a 100644 --- a/deps/uv/test/task.h +++ b/deps/uv/test/task.h @@ -79,8 +79,6 @@ typedef enum { abort(); \ } while (0) - - /* Have our own assert, so we are sure it does not get optimized away in * a release build. */ @@ -103,15 +101,17 @@ typedef enum { uv_loop_delete(uv_default_loop()) /* Just sugar for wrapping the main() for a task or helper. */ -#define TEST_IMPL(name) \ - int run_test_##name() - -#define BENCHMARK_IMPL(name) \ - int run_benchmark_##name() +#define TEST_IMPL(name) \ + int run_test_##name(void); \ + int run_test_##name(void) -#define HELPER_IMPL(name) \ - int run_helper_##name() +#define BENCHMARK_IMPL(name) \ + int run_benchmark_##name(void); \ + int run_benchmark_##name(void) +#define HELPER_IMPL(name) \ + int run_helper_##name(void); \ + int run_helper_##name(void) /* Pause the calling thread for a number of milliseconds. */ void uv_sleep(int msec); diff --git a/deps/uv/test/test-async.c b/deps/uv/test/test-async.c index 26194a1fd3..6ab510bf71 100644 --- a/deps/uv/test/test-async.c +++ b/deps/uv/test/test-async.c @@ -35,7 +35,7 @@ static int prepare_cb_called; static int close_cb_called; -void thread_cb(void *arg) { +static void thread_cb(void *arg) { int n; int r; diff --git a/deps/uv/test/test-condvar-consumer-producer.c b/deps/uv/test/test-condvar-consumer-producer.c deleted file mode 100644 index a7bd5a657b..0000000000 --- a/deps/uv/test/test-condvar-consumer-producer.c +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright Joyent, Inc. and other Node 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 "task.h" - -#include -#include - -#define MAX_CONSUMERS 32 -#define MAX_LOOPS 1000 - -struct buffer_s { - ngx_queue_t queue; - int data; -}; -typedef struct buffer_s buffer_t; - -static ngx_queue_t queue; -static uv_mutex_t mutex; -static uv_cond_t empty; -static uv_cond_t full; - -static volatile int finished_consumers = 0; - - -static void produce(int value) { - buffer_t* buf; - - buf = malloc(sizeof(*buf)); - ngx_queue_init(&buf->queue); - buf->data = value; - ngx_queue_insert_tail(&queue, &buf->queue); -} - - -static int consume(void) { - ngx_queue_t* q; - buffer_t* buf; - int data; - - ASSERT(!ngx_queue_empty(&queue)); - q = ngx_queue_last(&queue); - ngx_queue_remove(q); - - buf = ngx_queue_data(q, buffer_t, queue); - data = buf->data; - free(buf); - - return data; -} - - -static void producer(void* arg) { - int i; - - (void) arg; - - for (i = 0; i < MAX_LOOPS * MAX_CONSUMERS; i++) { - uv_mutex_lock(&mutex); - while(!ngx_queue_empty(&queue)) - uv_cond_wait(&empty, &mutex); - produce(i); - uv_cond_signal(&full); - uv_mutex_unlock(&mutex); - } -} - - -static void consumer(void* arg) { - int i; - int value; - - (void) arg; - - for (i = 0; i < MAX_LOOPS; i++) { - uv_mutex_lock(&mutex); - while (ngx_queue_empty(&queue)) - uv_cond_wait(&full, &mutex); - value = consume(); - ASSERT(value < MAX_LOOPS * MAX_CONSUMERS); - uv_cond_signal(&empty); - uv_mutex_unlock(&mutex); - } - - finished_consumers++; -} - - -TEST_IMPL(consumer_producer) { - int i; - uv_thread_t cthreads[MAX_CONSUMERS]; - uv_thread_t pthread; - - ngx_queue_init(&queue); - ASSERT(0 == uv_mutex_init(&mutex)); - ASSERT(0 == uv_cond_init(&empty)); - ASSERT(0 == uv_cond_init(&full)); - - for (i = 0; i < MAX_CONSUMERS; i++) { - ASSERT(0 == uv_thread_create(&cthreads[i], consumer, NULL)); - } - - ASSERT(0 == uv_thread_create(&pthread, producer, NULL)); - - for (i = 0; i < MAX_CONSUMERS; i++) { - ASSERT(0 == uv_thread_join(&cthreads[i])); - } - - ASSERT(0 == uv_thread_join(&pthread)); - - LOGF("finished_consumers: %d\n", finished_consumers); - ASSERT(finished_consumers == MAX_CONSUMERS); - - uv_cond_destroy(&empty); - uv_cond_destroy(&full); - uv_mutex_destroy(&mutex); - - return 0; -} diff --git a/deps/uv/test/test-connection-fail.c b/deps/uv/test/test-connection-fail.c index 4219f4c606..d5cd82b24b 100644 --- a/deps/uv/test/test-connection-fail.c +++ b/deps/uv/test/test-connection-fail.c @@ -88,7 +88,7 @@ static void on_connect_without_close(uv_connect_t *req, int status) { } -void connection_fail(uv_connect_cb connect_cb) { +static void connection_fail(uv_connect_cb connect_cb) { struct sockaddr_in client_addr, server_addr; int r; diff --git a/deps/uv/test/test-delayed-accept.c b/deps/uv/test/test-delayed-accept.c index 064fb6a697..a5e09f9b51 100644 --- a/deps/uv/test/test-delayed-accept.c +++ b/deps/uv/test/test-delayed-accept.c @@ -100,7 +100,7 @@ static void connection_cb(uv_stream_t* tcp, int status) { } -static void start_server() { +static void start_server(void) { struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", TEST_PORT); uv_tcp_t* server = (uv_tcp_t*)malloc(sizeof *server); int r; @@ -153,7 +153,7 @@ static void connect_cb(uv_connect_t* req, int status) { } -static void client_connect() { +static void client_connect(void) { struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT); uv_tcp_t* client = (uv_tcp_t*)malloc(sizeof *client); uv_connect_t* connect_req = malloc(sizeof *connect_req); diff --git a/deps/uv/test/test-embed.c b/deps/uv/test/test-embed.c index e635596e7a..a8c61e7aa4 100644 --- a/deps/uv/test/test-embed.c +++ b/deps/uv/test/test-embed.c @@ -26,7 +26,11 @@ #include #ifndef HAVE_KQUEUE -# if __APPLE__ || __DragonFly__ || __FreeBSD__ || __OpenBSD__ || __NetBSD__ +# if defined(__APPLE__) || \ + defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__OpenBSD__) || \ + defined(__NetBSD__) # define HAVE_KQUEUE 1 # endif #endif @@ -84,7 +88,7 @@ static void embed_thread_runner(void* arg) { static void embed_cb(uv_async_t* async, int status) { - uv_run_once(uv_default_loop()); + uv_run2(uv_default_loop(), UV_RUN_ONCE); uv_sem_post(&embed_sem); } diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c index 249af9acdd..9218b8748f 100644 --- a/deps/uv/test/test-fs-event.c +++ b/deps/uv/test/test-fs-event.c @@ -26,7 +26,11 @@ #include #ifndef HAVE_KQUEUE -# if __APPLE__ || __DragonFly__ || __FreeBSD__ || __OpenBSD__ || __NetBSD__ +# if defined(__APPLE__) || \ + defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__OpenBSD__) || \ + defined(__NetBSD__) # define HAVE_KQUEUE 1 # endif #endif @@ -431,7 +435,7 @@ TEST_IMPL(fs_event_close_with_pending_event) { return 0; } -#if HAVE_KQUEUE +#if defined(HAVE_KQUEUE) /* kqueue doesn't register fs events if you don't have an active watcher. * The file descriptor needs to be part of the kqueue set of interest and diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 597ef9713a..ccf7793bd8 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -104,7 +104,7 @@ static char buf[32]; static char test_buf[] = "test-buffer\n"; -void check_permission(const char* filename, int mode) { +static void check_permission(const char* filename, int mode) { int r; uv_fs_t req; struct stat* s; diff --git a/deps/uv/test/test-getsockname.c b/deps/uv/test/test-getsockname.c index 043c891c5a..7e2ae69a5d 100644 --- a/deps/uv/test/test-getsockname.c +++ b/deps/uv/test/test-getsockname.c @@ -165,7 +165,7 @@ static void on_connect(uv_connect_t* req, int status) { } -static int tcp_listener() { +static int tcp_listener(void) { struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", server_port); struct sockaddr sockname, peername; int namelen; @@ -206,7 +206,7 @@ static int tcp_listener() { } -static void tcp_connector() { +static void tcp_connector(void) { struct sockaddr_in server_addr = uv_ip4_addr("127.0.0.1", server_port); struct sockaddr sockname; int r, namelen; @@ -261,7 +261,7 @@ static void udp_send(uv_udp_send_t* req, int status) { } -static int udp_listener() { +static int udp_listener(void) { struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", server_port); struct sockaddr sockname; int namelen; diff --git a/deps/uv/test/test-ipc.c b/deps/uv/test/test-ipc.c index c37d15183e..3bdc8ea8c3 100644 --- a/deps/uv/test/test-ipc.c +++ b/deps/uv/test/test-ipc.c @@ -108,7 +108,7 @@ static void connect_cb(uv_connect_t* req, int status) { } -static void make_many_connections() { +static void make_many_connections(void) { tcp_conn* conn; struct sockaddr_in addr; int r, i; @@ -406,7 +406,7 @@ TEST_IMPL(listen_no_simultaneous_accepts) { /* Everything here runs in a child process. */ -tcp_conn conn; +static tcp_conn conn; static void close_cb(uv_handle_t* handle) { @@ -578,7 +578,7 @@ int ipc_helper(int listen_after_write) { } -int ipc_helper_tcp_connection() { +int ipc_helper_tcp_connection(void) { /* * This is launched from test-ipc.c. stdin is a duplex channel that we * over which a handle will be transmitted. diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 9c59a2d47c..7fdf2f4d83 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -22,6 +22,7 @@ TEST_DECLARE (platform_output) TEST_DECLARE (callback_order) TEST_DECLARE (run_once) +TEST_DECLARE (run_nowait) TEST_DECLARE (barrier_1) TEST_DECLARE (barrier_2) TEST_DECLARE (barrier_3) @@ -30,7 +31,6 @@ TEST_DECLARE (condvar_2) TEST_DECLARE (condvar_3) TEST_DECLARE (condvar_4) TEST_DECLARE (condvar_5) -TEST_DECLARE (consumer_producer) TEST_DECLARE (semaphore_1) TEST_DECLARE (semaphore_2) TEST_DECLARE (semaphore_3) @@ -192,6 +192,7 @@ TEST_DECLARE (threadpool_multiple_event_loops) TEST_DECLARE (threadpool_cancel_getaddrinfo) TEST_DECLARE (threadpool_cancel_work) TEST_DECLARE (threadpool_cancel_fs) +TEST_DECLARE (threadpool_cancel_single) TEST_DECLARE (thread_mutex) TEST_DECLARE (thread_rwlock) TEST_DECLARE (thread_create) @@ -227,6 +228,7 @@ TASK_LIST_START TEST_ENTRY (callback_order) #endif TEST_ENTRY (run_once) + TEST_ENTRY (run_nowait) TEST_ENTRY (barrier_1) TEST_ENTRY (barrier_2) TEST_ENTRY (barrier_3) @@ -235,7 +237,6 @@ TASK_LIST_START TEST_ENTRY (condvar_3) TEST_ENTRY (condvar_4) TEST_ENTRY (condvar_5) - TEST_ENTRY (consumer_producer) TEST_ENTRY (semaphore_1) TEST_ENTRY (semaphore_2) TEST_ENTRY (semaphore_3) @@ -466,6 +467,7 @@ TASK_LIST_START TEST_ENTRY (threadpool_cancel_getaddrinfo) TEST_ENTRY (threadpool_cancel_work) TEST_ENTRY (threadpool_cancel_fs) + TEST_ENTRY (threadpool_cancel_single) TEST_ENTRY (thread_mutex) TEST_ENTRY (thread_rwlock) TEST_ENTRY (thread_create) diff --git a/deps/uv/test/test-multiple-listen.c b/deps/uv/test/test-multiple-listen.c index 18197d1826..aced132f99 100644 --- a/deps/uv/test/test-multiple-listen.c +++ b/deps/uv/test/test-multiple-listen.c @@ -44,7 +44,7 @@ static void connection_cb(uv_stream_t* tcp, int status) { } -static void start_server() { +static void start_server(void) { struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", TEST_PORT); int r; @@ -71,7 +71,7 @@ static void connect_cb(uv_connect_t* req, int status) { } -static void client_connect() { +static void client_connect(void) { struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT); uv_connect_t* connect_req = malloc(sizeof *connect_req); int r; diff --git a/deps/uv/test/test-ping-pong.c b/deps/uv/test/test-ping-pong.c index a7b31c73e1..e7f7e9afc3 100644 --- a/deps/uv/test/test-ping-pong.c +++ b/deps/uv/test/test-ping-pong.c @@ -47,8 +47,6 @@ typedef struct { char read_buffer[BUFSIZE]; } pinger_t; -void pinger_try_read(pinger_t* pinger); - static uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) { return uv_buf_init(malloc(size), size); @@ -145,7 +143,7 @@ static void pinger_on_connect(uv_connect_t *req, int status) { /* same ping-pong test, but using IPv6 connection */ -static void tcp_pinger_v6_new() { +static void tcp_pinger_v6_new(void) { int r; struct sockaddr_in6 server_addr = uv_ip6_addr("::1", TEST_PORT); pinger_t *pinger; @@ -170,7 +168,7 @@ static void tcp_pinger_v6_new() { } -static void tcp_pinger_new() { +static void tcp_pinger_new(void) { int r; struct sockaddr_in server_addr = uv_ip4_addr("127.0.0.1", TEST_PORT); pinger_t *pinger; @@ -195,7 +193,7 @@ static void tcp_pinger_new() { } -static void pipe_pinger_new() { +static void pipe_pinger_new(void) { int r; pinger_t *pinger; diff --git a/deps/uv/test/test-poll.c b/deps/uv/test/test-poll.c index eb5cb8487f..039e95c508 100644 --- a/deps/uv/test/test-poll.c +++ b/deps/uv/test/test-poll.c @@ -72,7 +72,7 @@ static int valid_writable_wakeups = 0; static int spurious_writable_wakeups = 0; -static int got_eagain() { +static int got_eagain(void) { #ifdef _WIN32 return WSAGetLastError() == WSAEWOULDBLOCK; #else @@ -495,7 +495,7 @@ static void server_poll_cb(uv_poll_t* handle, int status, int events) { } -static void start_server() { +static void start_server(void) { uv_os_sock_t sock; server_context_t* context; int r; @@ -511,7 +511,7 @@ static void start_server() { } -static void start_client() { +static void start_client(void) { uv_os_sock_t sock; connection_context_t* context; struct sockaddr_in server_addr = uv_ip4_addr("127.0.0.1", TEST_PORT); @@ -531,7 +531,7 @@ static void start_client() { } -static void start_poll_test() { +static void start_poll_test(void) { int i, r; #ifdef _WIN32 diff --git a/deps/uv/test/test-ref.c b/deps/uv/test/test-ref.c index bc0030d34a..7b1de1ddfc 100644 --- a/deps/uv/test/test-ref.c +++ b/deps/uv/test/test-ref.c @@ -58,6 +58,11 @@ static void fail_cb(void) { } +static void fail_cb2(void) { + ASSERT(0 && "fail_cb2 should not have been called"); +} + + static void req_cb(uv_handle_t* req, int status) { req_cb_called++; } @@ -104,7 +109,7 @@ TEST_IMPL(ref) { TEST_IMPL(idle_ref) { uv_idle_t h; uv_idle_init(uv_default_loop(), &h); - uv_idle_start(&h, NULL); + uv_idle_start(&h, (uv_idle_cb) fail_cb2); uv_unref((uv_handle_t*)&h); uv_run(uv_default_loop()); do_close(&h); @@ -127,7 +132,7 @@ TEST_IMPL(async_ref) { TEST_IMPL(prepare_ref) { uv_prepare_t h; uv_prepare_init(uv_default_loop(), &h); - uv_prepare_start(&h, NULL); + uv_prepare_start(&h, (uv_prepare_cb) fail_cb2); uv_unref((uv_handle_t*)&h); uv_run(uv_default_loop()); do_close(&h); @@ -139,7 +144,7 @@ TEST_IMPL(prepare_ref) { TEST_IMPL(check_ref) { uv_check_t h; uv_check_init(uv_default_loop(), &h); - uv_check_start(&h, NULL); + uv_check_start(&h, (uv_check_cb) fail_cb2); uv_unref((uv_handle_t*)&h); uv_run(uv_default_loop()); do_close(&h); @@ -235,19 +240,12 @@ TEST_IMPL(tcp_ref2) { } -static void tcp_ref2b_close_cb(uv_handle_t* handle) { - (*(int*) handle->data)++; -} - - TEST_IMPL(tcp_ref2b) { - int close_cb_called = 0; uv_tcp_t h; - h.data = &close_cb_called; uv_tcp_init(uv_default_loop(), &h); uv_listen((uv_stream_t*)&h, 128, (uv_connection_cb)fail_cb); uv_unref((uv_handle_t*)&h); - uv_close((uv_handle_t*)&h, tcp_ref2b_close_cb); + uv_close((uv_handle_t*)&h, close_cb); uv_run(uv_default_loop()); ASSERT(close_cb_called == 1); MAKE_VALGRIND_HAPPY(); diff --git a/deps/uv/test/test-run-nowait.c b/deps/uv/test/test-run-nowait.c new file mode 100644 index 0000000000..fe8dd8943a --- /dev/null +++ b/deps/uv/test/test-run-nowait.c @@ -0,0 +1,46 @@ +/* Copyright Joyent, Inc. and other Node 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 "task.h" + +static uv_timer_t timer_handle; +static int timer_called = 0; + + +static void timer_cb(uv_timer_t* handle, int status) { + ASSERT(handle == &timer_handle); + ASSERT(status == 0); + timer_called = 1; +} + + +TEST_IMPL(run_nowait) { + int r; + uv_timer_init(uv_default_loop(), &timer_handle); + uv_timer_start(&timer_handle, timer_cb, 100, 100); + + r = uv_run2(uv_default_loop(), UV_RUN_NOWAIT); + ASSERT(r != 0); + ASSERT(timer_called == 0); + + return 0; +} diff --git a/deps/uv/test/test-run-once.c b/deps/uv/test/test-run-once.c index b425a42305..ecd82a2ca5 100644 --- a/deps/uv/test/test-run-once.c +++ b/deps/uv/test/test-run-once.c @@ -41,7 +41,7 @@ TEST_IMPL(run_once) { uv_idle_init(uv_default_loop(), &idle_handle); uv_idle_start(&idle_handle, idle_cb); - while (uv_run_once(uv_default_loop())); + while (uv_run2(uv_default_loop(), UV_RUN_ONCE)); ASSERT(idle_counter == NUM_TICKS); MAKE_VALGRIND_HAPPY(); diff --git a/deps/uv/test/test-shutdown-eof.c b/deps/uv/test/test-shutdown-eof.c index 22f6da53e9..6e55a7deb6 100644 --- a/deps/uv/test/test-shutdown-eof.c +++ b/deps/uv/test/test-shutdown-eof.c @@ -110,7 +110,7 @@ static void connect_cb(uv_connect_t *req, int status) { } -void tcp_close_cb(uv_handle_t* handle) { +static void tcp_close_cb(uv_handle_t* handle) { ASSERT(handle == (uv_handle_t*) &tcp); ASSERT(called_connect_cb == 1); @@ -122,13 +122,13 @@ void tcp_close_cb(uv_handle_t* handle) { } -void timer_close_cb(uv_handle_t* handle) { +static void timer_close_cb(uv_handle_t* handle) { ASSERT(handle == (uv_handle_t*) &timer); called_timer_close_cb++; } -void timer_cb(uv_timer_t* handle, int status) { +static void timer_cb(uv_timer_t* handle, int status) { ASSERT(handle == &timer); uv_close((uv_handle_t*) handle, timer_close_cb); diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c index 48ab239bb5..c97595f145 100644 --- a/deps/uv/test/test-spawn.c +++ b/deps/uv/test/test-spawn.c @@ -106,7 +106,7 @@ static uv_buf_t on_alloc(uv_handle_t* handle, size_t suggested_size) { } -void on_read(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf) { +static void on_read(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf) { uv_err_t err = uv_last_error(uv_default_loop()); if (nread > 0) { @@ -118,7 +118,7 @@ void on_read(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf) { } -void write_cb(uv_write_t* req, int status) { +static void write_cb(uv_write_t* req, int status) { ASSERT(status == 0); uv_close((uv_handle_t*)req->handle, close_cb); } diff --git a/deps/uv/test/test-stdio-over-pipes.c b/deps/uv/test/test-stdio-over-pipes.c index aeb7bd9245..c0028eecfa 100644 --- a/deps/uv/test/test-stdio-over-pipes.c +++ b/deps/uv/test/test-stdio-over-pipes.c @@ -34,7 +34,8 @@ static int close_cb_called; static int exit_cb_called; static int on_read_cb_called; static int after_write_cb_called; -uv_pipe_t out, in; +static uv_pipe_t in; +static uv_pipe_t out; static uv_loop_t* loop; #define OUTPUT_SIZE 1024 static char output[OUTPUT_SIZE]; @@ -182,7 +183,7 @@ static uv_buf_t on_read_alloc(uv_handle_t* handle, size_t suggested_size) { } -int stdio_over_pipes_helper() { +int stdio_over_pipes_helper(void) { /* Write several buffers to test that the write order is preserved. */ char* buffers[] = { "he", diff --git a/deps/uv/test/test-threadpool-cancel.c b/deps/uv/test/test-threadpool-cancel.c index db0397afe0..970e9fee56 100644 --- a/deps/uv/test/test-threadpool-cancel.c +++ b/deps/uv/test/test-threadpool-cancel.c @@ -156,6 +156,15 @@ static void timer_cb(uv_timer_t* handle, int status) { } +static void nop_work_cb(uv_work_t* req) { +} + + +static void nop_done_cb(uv_work_t* req, int status) { + req->data = "OK"; +} + + TEST_IMPL(threadpool_cancel_getaddrinfo) { uv_getaddrinfo_t reqs[4]; struct cancel_info ci; @@ -264,3 +273,35 @@ TEST_IMPL(threadpool_cancel_fs) { return 0; } + + +TEST_IMPL(threadpool_cancel_single) { + uv_loop_t* loop; + uv_work_t req; + int cancelled; + int i; + + loop = uv_default_loop(); + for (i = 0; i < 5000; i++) { + req.data = NULL; + ASSERT(0 == uv_queue_work(loop, &req, nop_work_cb, nop_done_cb)); + + cancelled = uv_cancel((uv_req_t*) &req); + if (cancelled == 0) + break; + + ASSERT(0 == uv_run(loop)); + } + + if (cancelled != 0) { + fputs("Failed to cancel a work req in 5,000 iterations, giving up.\n", + stderr); + return 1; + } + + ASSERT(req.data == NULL); + ASSERT(0 == uv_run(loop)); + ASSERT(req.data != NULL); /* Should have been updated by nop_done_cb(). */ + + return 0; +} diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index ac6f7f04ec..f40e46a75b 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -31,10 +31,17 @@ 'include_dirs': [ 'include' ], 'conditions': [ ['OS != "win"', { - 'defines': [ '_LARGEFILE_SOURCE', '_FILE_OFFSET_BITS=64' ], + 'defines': [ + '_LARGEFILE_SOURCE', + '_FILE_OFFSET_BITS=64', + '_POSIX_C_SOURCE=200112', + ], }], ['OS == "mac"', { - 'defines': [ '_DARWIN_USE_64_BIT_INODE=1' ], + 'defines': [ + '_DARWIN_USE_64_BIT_INODE=1', + '_DARWIN_C_SOURCE', # _POSIX_C_SOURCE hides SysV definitions. + ], }], ], }, @@ -275,6 +282,7 @@ 'test/test-poll-close.c', 'test/test-process-title.c', 'test/test-ref.c', + 'test/test-run-nowait.c', 'test/test-run-once.c', 'test/test-semaphore.c', 'test/test-shutdown-close.c', @@ -306,7 +314,6 @@ 'test/test-thread.c', 'test/test-barrier.c', 'test/test-condvar.c', - 'test/test-condvar-consumer-producer.c', 'test/test-timer-again.c', 'test/test-timer.c', 'test/test-tty.c', @@ -364,6 +371,7 @@ 'test/benchmark-getaddrinfo.c', 'test/benchmark-list.h', 'test/benchmark-loop-count.c', + 'test/benchmark-million-async.c', 'test/benchmark-million-timers.c', 'test/benchmark-multi-accept.c', 'test/benchmark-ping-pongs.c',