uv: Upgrade to v0.11.5
authorisaacs <i@izs.me>
Wed, 26 Jun 2013 17:48:10 +0000 (10:48 -0700)
committerisaacs <i@izs.me>
Wed, 26 Jun 2013 17:48:23 +0000 (10:48 -0700)
32 files changed:
deps/uv/AUTHORS
deps/uv/ChangeLog
deps/uv/LICENSE
deps/uv/README.md
deps/uv/android-configure [new file with mode: 0755]
deps/uv/checksparse.sh
deps/uv/common.gypi
deps/uv/config-unix.mk
deps/uv/gyp_uv
deps/uv/include/uv-private/pthread-fixes.h [new file with mode: 0644]
deps/uv/include/uv-private/uv-unix.h
deps/uv/include/uv.h
deps/uv/src/queue.h
deps/uv/src/unix/error.c
deps/uv/src/unix/internal.h
deps/uv/src/unix/linux-core.c
deps/uv/src/unix/linux-syscalls.h
deps/uv/src/unix/pthread-fixes.c [new file with mode: 0644]
deps/uv/src/unix/stream.c
deps/uv/src/unix/thread.c
deps/uv/src/uv-common.c
deps/uv/src/version.c
deps/uv/src/win/internal.h
deps/uv/src/win/pipe.c
deps/uv/src/win/stream.c
deps/uv/src/win/tcp.c
deps/uv/src/win/util.c
deps/uv/test/task.h
deps/uv/test/test-fs-event.c
deps/uv/test/test-fs.c
deps/uv/test/test-spawn.c
deps/uv/uv.gyp

index 4c36fae..2d0f01d 100644 (file)
@@ -88,3 +88,5 @@ Miroslav Bajtoš <miro.bajtos@gmail.com>
 Elliot Saba <staticfloat@gmail.com>
 Sean Silva <chisophugis@gmail.com>
 Wynn Wilkes <wynnw@movenetworks.com>
+Linus Mårtensson <linus.martensson@sonymobile.com>
+Andrei Sedoi <bsnote@gmail.com>
index 113d170..53f2ed4 100644 (file)
@@ -1,4 +1,80 @@
-2013.05.30, Version 0.11.4 (Unstable)
+2013.06.27, Version 0.11.5 (Unstable)
+
+Changes since version 0.11.4:
+
+* build: remove CSTDFLAG, use only CFLAGS (Ben Noordhuis)
+
+* unix: support for android builds (Linus Mårtensson)
+
+* unix: avoid extra read, short-circuit on POLLHUP (Ben Noordhuis)
+
+* uv: support android libuv standalone build (Linus Mårtensson)
+
+* src: make queue.h c++ compatible (Ben Noordhuis)
+
+* unix: s/ngx-queue.h/queue.h/ in checksparse.sh (Ben Noordhuis)
+
+* unix: unconditionally stop handle on close (Ben Noordhuis)
+
+* freebsd: don't enable dtrace if it's not available (Brian White)
+
+* build: make HAVE_DTRACE=0 should disable dtrace (Timothy J. Fontaine)
+
+* unix: remove overzealous assert (Ben Noordhuis)
+
+* unix: remove unused function uv_fatal_error() (Ben Noordhuis)
+
+* unix, windows: clean up uv_thread_create() (Ben Noordhuis)
+
+* queue: fix pointer truncation on LLP64 platforms (Bert Belder)
+
+* build: set OS=="android" for android builds (Linus Mårtensson)
+
+* windows: don't use uppercase in include filename (Ben Noordhuis)
+
+* stream: add an API to make streams do blocking writes (Henry Rawas)
+
+* windows: use WSAGetLastError(), not errno (Ben Noordhuis)
+
+
+2013.06.13, Version 0.10.11 (Stable), c3b75406a66a10222a589cb173e8f469e9665c7e
+
+Changes since version 0.10.10:
+
+* unix: unconditionally stop handle on close (Ben Noordhuis)
+
+* freebsd: don't enable dtrace if it's not available (Brian White)
+
+* build: make HAVE_DTRACE=0 should disable dtrace (Timothy J. Fontaine)
+
+* unix: remove overzealous assert (Ben Noordhuis)
+
+* unix: clear UV_STREAM_SHUTTING after shutdown() (Ben Noordhuis)
+
+* unix: fix busy loop, write if POLLERR or POLLHUP (Ben Noordhuis)
+
+
+2013.06.05, Version 0.10.10 (Stable), 0d95a88bd35fce93863c57a460be613aea34d2c5
+
+Changes since version 0.10.9:
+
+* include: document uv_update_time() and uv_now() (Ben Noordhuis)
+
+* linux: fix cpu model parsing on newer arm kernels (Ben Noordhuis)
+
+* linux: fix a memory leak in uv_cpu_info() error path (Ben Noordhuis)
+
+* linux: don't ignore out-of-memory errors in uv_cpu_info() (Ben Noordhuis)
+
+* unix, windows: move uv_now() to uv-common.c (Ben Noordhuis)
+
+* test: fix a compilation problem in test-osx-select.c that was caused by the
+  use of c-style comments (Bert Belder)
+
+* darwin: use uv_fs_sendfile() use the sendfile api correctly (Wynn Wilkes)
+
+
+2013.05.30, Version 0.11.4 (Unstable), e43e5b3d954a0989db5588aa110e1fe4fe6e0219
 
 Changes since version 0.11.3:
 
index 4718e34..8db13ac 100644 (file)
@@ -37,3 +37,6 @@ The externally maintained libraries used by libuv are:
 
   - stdint-msvc2008.h (from msinttypes), copyright Alexander Chemeris. Three
     clause BSD license.
+
+  - pthread-fixes.h, pthread-fixes.c, copyright Google Inc. and Sony Mobile
+    Communications AB. Three clause BSD license.
index e0d38c4..f4f3ce2 100644 (file)
@@ -70,6 +70,10 @@ Out-of-tree builds are supported:
 
     make builddir_name=/path/to/builddir
 
+To build a shared object:
+
+    make libuv.so  # libuv.dylib on OS X
+
 To build with Visual Studio run the vcbuild.bat file which will
 checkout the GYP code into build/gyp and generate the uv.sln and
 related files.
@@ -106,6 +110,16 @@ Note for Linux users: compile your project with `-D_GNU_SOURCE` when you
 include `uv.h`. GYP builds take care of that automatically. If you use
 autotools, add a `AC_GNU_SOURCE` declaration to your `configure.ac`.
 
+To build for android, locate your android NDK path, then run:
+
+    source ./android-configure NDK_PATH
+    make
+
+To build for android with gyp, add "gyp" to the configuration:
+
+    source ./android-configure NDK_PATH gyp
+    make -C out
+
 ## Supported Platforms
 
 Microsoft Windows operating systems since Windows XP SP2. It can be built
diff --git a/deps/uv/android-configure b/deps/uv/android-configure
new file mode 100755 (executable)
index 0000000..d5c937e
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+export TOOLCHAIN=$PWD/android-toolchain
+mkdir -p $TOOLCHAIN
+$1/build/tools/make-standalone-toolchain.sh \
+    --toolchain=arm-linux-androideabi-4.7 \
+    --arch=arm \
+    --install-dir=$TOOLCHAIN \
+    --platform=android-9
+export PATH=$TOOLCHAIN/bin:$PATH
+export AR=arm-linux-androideabi-ar
+export CC=arm-linux-androideabi-gcc
+export CXX=arm-linux-androideabi-g++
+export LINK=arm-linux-androideabi-g++
+export PLATFORM=android
+
+if [ $2 -a $2 == 'gyp' ]
+  then
+    ./gyp_uv -Dtarget_arch=arm -DOS=android
+fi
index f06b27d..65ff72b 100755 (executable)
@@ -27,12 +27,12 @@ SPARSE_FLAGS=${SPARSE_FLAGS:-"
 "}
 
 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/queue.h
 src/unix/async.c
 src/unix/core.c
 src/unix/dl.c
@@ -222,7 +222,7 @@ SunOS)
   ;;
 esac
 
-for ARCH in __i386__ __x86_64__ __arm__; do
+for ARCH in __i386__ __x86_64__ __arm__ __mips__; do
   $SPARSE $SPARSE_FLAGS -D$ARCH=1 $SOURCES
 done
 
index c346282..7f2e8c3 100644 (file)
           }]
         ]
       }],
-      [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
+      ['OS in "freebsd linux openbsd solaris android"', {
         'cflags': [ '-Wall' ],
         'cflags_cc': [ '-fno-rtti', '-fno-exceptions' ],
         'target_conditions': [
           [ 'OS=="solaris"', {
             'cflags': [ '-pthreads' ],
             'ldflags': [ '-pthreads' ],
-          }, {
+          }],
+          [ 'OS not in "solaris android"', {
             'cflags': [ '-pthread' ],
             'ldflags': [ '-pthread' ],
           }],
index 67aaa14..7b99ac1 100644 (file)
@@ -19,8 +19,7 @@
 # IN THE SOFTWARE.
 
 E=
-CSTDFLAG=--std=c89 -pedantic -Wall -Wextra -Wno-unused-parameter
-CFLAGS += -g
+CFLAGS += -g -Wall -Wextra -Wno-unused-parameter
 CPPFLAGS += -I$(SRCDIR)/src
 LDFLAGS=-lm
 
@@ -31,7 +30,6 @@ RUNNER_SRC=test/runner-unix.c
 RUNNER_CFLAGS=$(CFLAGS) -I$(SRCDIR)/test
 RUNNER_LDFLAGS=-L"$(CURDIR)" -luv
 
-HAVE_DTRACE=
 DTRACE_OBJS=
 DTRACE_HEADER=
 
@@ -60,14 +58,16 @@ OBJS += src/inet.o
 OBJS += src/version.o
 
 ifeq (sunos,$(PLATFORM))
-HAVE_DTRACE=1
+HAVE_DTRACE ?= 1
 CPPFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500
 LDFLAGS+=-lkstat -lnsl -lsendfile -lsocket
 # Library dependencies are not transitive.
 OBJS += src/unix/sunos.o
+ifeq (1, $(HAVE_DTRACE))
 OBJS += src/unix/dtrace.o
 DTRACE_OBJS += src/unix/core.o
 endif
+endif
 
 ifeq (aix,$(PLATFORM))
 CPPFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500
@@ -76,7 +76,7 @@ OBJS += src/unix/aix.o
 endif
 
 ifeq (darwin,$(PLATFORM))
-HAVE_DTRACE=1
+HAVE_DTRACE ?= 1
 # dtrace(1) probes contain dollar signs on OS X. Mute the warnings they
 # generate but only when CC=clang, -Wno-dollar-in-identifier-extension
 # is a clang extension.
@@ -96,17 +96,31 @@ OBJS += src/unix/darwin-proctitle.o
 endif
 
 ifeq (linux,$(PLATFORM))
-CSTDFLAG += -D_GNU_SOURCE
+CFLAGS += -D_GNU_SOURCE
+LDFLAGS+=-ldl -lrt
+RUNNER_CFLAGS += -D_GNU_SOURCE
+OBJS += src/unix/linux-core.o \
+        src/unix/linux-inotify.o \
+        src/unix/linux-syscalls.o \
+        src/unix/proctitle.o
+endif
+
+ifeq (android,$(PLATFORM))
+CFLAGS += -D_GNU_SOURCE
 LDFLAGS+=-ldl -lrt
 RUNNER_CFLAGS += -D_GNU_SOURCE
 OBJS += src/unix/linux-core.o \
         src/unix/linux-inotify.o \
         src/unix/linux-syscalls.o \
         src/unix/proctitle.o
+else
+CFLAGS += -std=c89
 endif
 
 ifeq (freebsd,$(PLATFORM))
-HAVE_DTRACE=1
+ifeq ($(shell dtrace -l 1>&2 2>/dev/null; echo $$?),0)
+HAVE_DTRACE ?= 1
+endif
 LDFLAGS+=-lkvm
 OBJS += src/unix/freebsd.o
 OBJS += src/unix/kqueue.o
@@ -133,8 +147,10 @@ endif
 ifeq (sunos,$(PLATFORM))
 RUNNER_LDFLAGS += -pthreads
 else
+ifneq (android, $(PLATFORM))
 RUNNER_LDFLAGS += -pthread
 endif
+endif
 
 ifeq ($(HAVE_DTRACE), 1)
 DTRACE_HEADER = src/unix/uv-dtrace.h
@@ -170,13 +186,13 @@ src/.buildstamp src/unix/.buildstamp test/.buildstamp:
        touch $@
 
 src/unix/%.o src/unix/%.pic.o: src/unix/%.c include/uv.h include/uv-private/uv-unix.h src/unix/internal.h src/unix/.buildstamp $(DTRACE_HEADER)
-       $(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
+       $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
 
 src/%.o src/%.pic.o: src/%.c include/uv.h include/uv-private/uv-unix.h src/.buildstamp
-       $(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
+       $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
 
 test/%.o: test/%.c include/uv.h test/.buildstamp
-       $(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
+       $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
 
 clean-platform:
        $(RM) test/run-{tests,benchmarks}.dSYM $(OBJS) $(OBJS:%.o=%.pic.o) src/unix/uv-dtrace.h
index ab59451..651bd09 100755 (executable)
@@ -24,6 +24,7 @@ def host_arch():
   if machine == 'i386': return 'ia32'
   if machine == 'x86_64': return 'x64'
   if machine.startswith('arm'): return 'arm'
+  if machine.startswith('mips'): return 'mips'
   return machine  # Return as-is and hope for the best.
 
 
diff --git a/deps/uv/include/uv-private/pthread-fixes.h b/deps/uv/include/uv-private/pthread-fixes.h
new file mode 100644 (file)
index 0000000..230ce31
--- /dev/null
@@ -0,0 +1,59 @@
+/* Copyright (c) 2013, Sony Mobile Communications AB
+ * Copyright (c) 2012, Google Inc.
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+
+     * Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above
+   copyright notice, this list of conditions and the following disclaimer
+   in the documentation and/or other materials provided with the
+   distribution.
+       * Neither the name of Google Inc. nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_H
+#define GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_H
+
+#include <pthread.h>
+
+
+/*Android doesn't provide pthread_barrier_t for now.*/
+#ifndef PTHREAD_BARRIER_SERIAL_THREAD
+
+/* Anything except 0 will do here.*/
+#define PTHREAD_BARRIER_SERIAL_THREAD  0x12345
+
+typedef struct {
+  pthread_mutex_t  mutex;
+  pthread_cond_t   cond;
+  unsigned         count;
+} pthread_barrier_t;
+
+int pthread_barrier_init(pthread_barrier_t* barrier,
+                         const void* barrier_attr,
+                         unsigned count);
+
+int pthread_barrier_wait(pthread_barrier_t* barrier);
+int pthread_barrier_destroy(pthread_barrier_t *barrier);
+#endif  /* defined(PTHREAD_BARRIER_SERIAL_THREAD) */
+
+int pthread_yield(void);
+#endif  /* GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_H */
index 385c32a..4c05a71 100644 (file)
@@ -37,6 +37,9 @@
 
 #include <semaphore.h>
 #include <pthread.h>
+#ifdef __ANDROID__
+#include "pthread-fixes.h"
+#endif
 #include <signal.h>
 
 #if defined(__linux__)
index f51aea6..bb443e0 100644 (file)
@@ -349,6 +349,8 @@ typedef uv_buf_t (*uv_alloc_cb)(uv_handle_t* handle, size_t suggested_size);
  * Trying to read from the stream again is undefined.
  *
  * The callee is responsible for freeing the buffer, libuv does not reuse it.
+ * The buffer may be a null buffer (where buf.base=NULL and buf.len=0) on EOF
+ * or error.
  */
 typedef void (*uv_read_cb)(uv_stream_t* stream, ssize_t nread, uv_buf_t buf);
 
@@ -674,6 +676,31 @@ UV_EXTERN int uv_is_writable(const uv_stream_t* handle);
 
 
 /*
+ * Enable or disable blocking mode for a stream.
+ *
+ * When blocking mode is enabled all writes complete synchronously. The
+ * interface remains unchanged otherwise, e.g. completion or failure of the
+ * operation will still be reported through a callback which is made
+ * asychronously.
+ *
+ * Relying too much on this API is not recommended. It is likely to change
+ * significantly in the future.
+ *
+ * On windows this currently works only for uv_pipe_t instances. On unix it
+ * works for tcp, pipe and tty instances. Be aware that changing the blocking
+ * mode on unix sets or clears the O_NONBLOCK bit. If you are sharing a handle
+ * with another process, the other process is affected by the change too,
+ * which can lead to unexpected results.
+ *
+ * Also libuv currently makes no ordering guarantee when the blocking mode
+ * is changed after write requests have already been submitted. Therefore it is
+ * recommended to set the blocking mode immediately after opening or creating
+ * the stream.
+ */
+UV_EXTERN int uv_stream_set_blocking(uv_stream_t* handle, int blocking);
+
+
+/*
  * Used to determine whether a stream is closing or closed.
  *
  * N.B. is only valid between the initialization of the handle
@@ -1869,8 +1896,6 @@ UV_EXTERN extern uint64_t uv_hrtime(void);
  * Note that this function works on a best-effort basis: there is no guarantee
  * that libuv can discover all file descriptors that were inherited. In general
  * it does a better job on Windows than it does on unix.
- *
- * TODO(bb): insert snarky remark to annoy bnoordhuis and the folks at joyent.
  */
 UV_EXTERN void uv_disable_stdio_inheritance(void);
 
index a88ce9a..2f5ab61 100644 (file)
@@ -16,6 +16,8 @@
 #ifndef QUEUE_H_
 #define QUEUE_H_
 
+#include <stdint.h>
+
 typedef void *QUEUE[2];
 
 /* Private macros. */
@@ -26,10 +28,10 @@ typedef void *QUEUE[2];
 
 /* Public macros. */
 #define QUEUE_DATA(ptr, type, field)                                          \
-  ((type *) ((char *) (ptr) - ((long) &((type *) 0)->field)))
+  ((type *) ((char *) (ptr) - ((uintptr_t) &((type *) 0)->field)))
 
 #define QUEUE_FOREACH(q, h)                                                   \
-  for ((q) = (*(h))[0]; (q) != (h); (q) = (*(q))[0])
+  for ((q) = (QUEUE *) (*(h))[0]; (q) != (h); (q) = (QUEUE *) (*(q))[0])
 
 #define QUEUE_EMPTY(q)                                                        \
   (QUEUE_NEXT(q) == (q))
index 05ab482..74e1bac 100644 (file)
 #include <assert.h>
 
 
-/* TODO Expose callback to user to handle fatal error like V8 does. */
-void uv_fatal_error(const int errorno, const char* syscall) {
-  char* buf = NULL;
-  const char* errmsg;
-
-  if (buf) {
-    errmsg = buf;
-  } else {
-    errmsg = "Unknown error";
-  }
-
-  if (syscall) {
-    fprintf(stderr, "\nlibuv fatal error. %s: (%d) %s\n", syscall, errorno,
-        errmsg);
-  } else {
-    fprintf(stderr, "\nlibuv fatal error. (%d) %s\n", errorno, errmsg);
-  }
-
-  abort();
-}
-
-
 uv_err_code uv_translate_sys_error(int sys_errno) {
   switch (sys_errno) {
     case 0: return UV_OK;
index 2f4d526..9b593d9 100644 (file)
 
 /* handle flags */
 enum {
-  UV_CLOSING          = 0x01,   /* uv_close() called but not finished. */
-  UV_CLOSED           = 0x02,   /* close(2) finished. */
-  UV_STREAM_READING   = 0x04,   /* uv_read_start() called. */
-  UV_STREAM_SHUTTING  = 0x08,   /* uv_shutdown() called but not complete. */
-  UV_STREAM_SHUT      = 0x10,   /* Write side closed. */
-  UV_STREAM_READABLE  = 0x20,   /* The stream is readable */
-  UV_STREAM_WRITABLE  = 0x40,   /* The stream is writable */
-  UV_STREAM_BLOCKING  = 0x80,   /* Synchronous writes. */
-  UV_TCP_NODELAY      = 0x100,  /* Disable Nagle. */
-  UV_TCP_KEEPALIVE    = 0x200,  /* Turn on keep-alive. */
-  UV_TCP_SINGLE_ACCEPT = 0x400  /* Only accept() when idle. */
+  UV_CLOSING              = 0x01,   /* uv_close() called but not finished. */
+  UV_CLOSED               = 0x02,   /* close(2) finished. */
+  UV_STREAM_READING       = 0x04,   /* uv_read_start() called. */
+  UV_STREAM_SHUTTING      = 0x08,   /* uv_shutdown() called but not complete. */
+  UV_STREAM_SHUT          = 0x10,   /* Write side closed. */
+  UV_STREAM_READABLE      = 0x20,   /* The stream is readable */
+  UV_STREAM_WRITABLE      = 0x40,   /* The stream is writable */
+  UV_STREAM_BLOCKING      = 0x80,   /* Synchronous writes. */
+  UV_STREAM_READ_PARTIAL  = 0x100,  /* read(2) read less than requested. */
+  UV_STREAM_READ_EOF      = 0x200,  /* read(2) read EOF. */
+  UV_TCP_NODELAY          = 0x400,  /* Disable Nagle. */
+  UV_TCP_KEEPALIVE        = 0x800,  /* Turn on keep-alive. */
+  UV_TCP_SINGLE_ACCEPT    = 0x1000  /* Only accept() when idle. */
 };
 
 /* core */
@@ -142,7 +144,6 @@ void uv__run_prepare(uv_loop_t* loop);
 
 /* error */
 uv_err_code uv_translate_sys_error(int sys_errno);
-void uv_fatal_error(const int errorno, const char* syscall);
 
 /* stream */
 void uv__stream_init(uv_loop_t* loop, uv_stream_t* stream,
index 23af789..f18da7a 100644 (file)
 #include <fcntl.h>
 #include <time.h>
 
+#ifndef __ANDROID__
 #define HAVE_IFADDRS_H 1
+#endif
+
 #ifdef __UCLIBC__
 # if __UCLIBC_MAJOR__ < 0 || __UCLIBC_MINOR__ < 9 || __UCLIBC_SUBLEVEL__ < 32
 #  undef HAVE_IFADDRS_H
@@ -427,7 +430,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
   char* model;
   FILE* fp;
 
-  /* Most are unused on non-ARM and non-x86 architectures. */
+  /* Most are unused on non-ARM, non-MIPS and non-x86 architectures. */
   (void) &model_marker;
   (void) &speed_marker;
   (void) &speed_idx;
@@ -438,7 +441,10 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
   model_idx = 0;
   speed_idx = 0;
 
-#if defined(__arm__) || defined(__i386__) || defined(__x86_64__)
+#if defined(__arm__) || \
+    defined(__i386__) || \
+    defined(__mips__) || \
+    defined(__x86_64__)
   fp = fopen("/proc/cpuinfo", "r");
   if (fp == NULL)
     return -1;
@@ -456,10 +462,14 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
         continue;
       }
     }
-#if defined(__arm__)
-    /* Fallback for pre-3.8 kernels. */
+#if defined(__arm__) || defined(__mips__)
     if (model_idx < numcpus) {
+#if defined(__arm__)
+      /* Fallback for pre-3.8 kernels. */
       static const char model_marker[] = "Processor\t: ";
+#else  /* defined(__mips__) */
+      static const char model_marker[] = "cpu model\t\t: ";
+#endif
       if (strncmp(buf, model_marker, sizeof(model_marker) - 1) == 0) {
         model = buf + sizeof(model_marker) - 1;
         model = strndup(model, strlen(model) - 1);  /* Strip newline. */
@@ -471,18 +481,18 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
         continue;
       }
     }
-#else  /* !__arm____ */
+#else  /* !__arm__ && !__mips__ */
     if (speed_idx < numcpus) {
       if (strncmp(buf, speed_marker, sizeof(speed_marker) - 1) == 0) {
         ci[speed_idx++].speed = atoi(buf + sizeof(speed_marker) - 1);
         continue;
       }
     }
-#endif  /* __arm__ */
+#endif  /* __arm__ || __mips__ */
   }
 
   fclose(fp);
-#endif  /* __arm__ || __i386__ || __x86_64__ */
+#endif  /* __arm__ || __i386__ || __mips__ || __x86_64__ */
 
   /* Now we want to make sure that all the models contain *something* because
    * it's not safe to leave them as null. Copy the last entry unless there
index ba44974..1ad9518 100644 (file)
@@ -28,6 +28,7 @@
 #include <stdint.h>
 #include <signal.h>
 #include <sys/types.h>
+#include <sys/time.h>
 #include <sys/socket.h>
 
 #if defined(__alpha__)
diff --git a/deps/uv/src/unix/pthread-fixes.c b/deps/uv/src/unix/pthread-fixes.c
new file mode 100644 (file)
index 0000000..2e4c542
--- /dev/null
@@ -0,0 +1,80 @@
+/* Copyright (c) 2013, Sony Mobile Communications AB
+ * Copyright (c) 2012, Google Inc.
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+
+     * Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above
+   copyright notice, this list of conditions and the following disclaimer
+   in the documentation and/or other materials provided with the
+   distribution.
+       * Neither the name of Google Inc. nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*Android doesn't provide pthread_barrier_t for now.*/
+#ifndef PTHREAD_BARRIER_SERIAL_THREAD
+
+#include "pthread-fixes.h"
+
+int pthread_barrier_init(pthread_barrier_t* barrier,
+                         const void* barrier_attr,
+                         unsigned count) {
+  barrier->count = count;
+  pthread_mutex_init(&barrier->mutex, NULL);
+  pthread_cond_init(&barrier->cond, NULL);
+  return 0;
+}
+
+int pthread_barrier_wait(pthread_barrier_t* barrier) {
+  /* Lock the mutex*/
+  pthread_mutex_lock(&barrier->mutex);
+  /* Decrement the count. If this is the first thread to reach 0, wake up
+     waiters, unlock the mutex, then return PTHREAD_BARRIER_SERIAL_THREAD.*/
+  if (--barrier->count == 0) {
+    /* First thread to reach the barrier */
+    pthread_cond_broadcast(&barrier->cond);
+    pthread_mutex_unlock(&barrier->mutex);
+    return PTHREAD_BARRIER_SERIAL_THREAD;
+  }
+  /* Otherwise, wait for other threads until the count reaches 0, then
+     return 0 to indicate this is not the first thread.*/
+  do {
+    pthread_cond_wait(&barrier->cond, &barrier->mutex);
+  } while (barrier->count > 0);
+
+  pthread_mutex_unlock(&barrier->mutex);
+  return 0;
+}
+
+int pthread_barrier_destroy(pthread_barrier_t *barrier) {
+  barrier->count = 0;
+  pthread_cond_destroy(&barrier->cond);
+  pthread_mutex_destroy(&barrier->mutex);
+  return 0;
+}
+
+#endif  /* defined(PTHREAD_BARRIER_SERIAL_THREAD) */
+
+int pthread_yield(void) {
+  sched_yield();
+  return 0;
+}
index 7936380..9688fbe 100644 (file)
@@ -613,6 +613,7 @@ int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {
 
 static void uv__drain(uv_stream_t* stream) {
   uv_shutdown_t* req;
+  int status;
 
   assert(QUEUE_EMPTY(&stream->write_queue));
   uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT);
@@ -625,21 +626,17 @@ static void uv__drain(uv_stream_t* stream) {
 
     req = stream->shutdown_req;
     stream->shutdown_req = NULL;
+    stream->flags &= ~UV_STREAM_SHUTTING;
     uv__req_unregister(stream->loop, req);
 
-    if (shutdown(uv__stream_fd(stream), SHUT_WR)) {
-      /* Error. Report it. User should call uv_close(). */
+    status = shutdown(uv__stream_fd(stream), SHUT_WR);
+    if (status)
       uv__set_sys_error(stream->loop, errno);
-      if (req->cb) {
-        req->cb(req, -1);
-      }
-    } else {
-      uv__set_sys_error(stream->loop, 0);
-      ((uv_handle_t*) stream)->flags |= UV_STREAM_SHUT;
-      if (req->cb) {
-        req->cb(req, 0);
-      }
-    }
+    else
+      stream->flags |= UV_STREAM_SHUT;
+
+    if (req->cb != NULL)
+      req->cb(req, status);
   }
 }
 
@@ -696,11 +693,24 @@ static int uv__handle_fd(uv_handle_t* handle) {
   }
 }
 
+static int uv__getiovmax() {
+#if defined(IOV_MAX)
+  return IOV_MAX;
+#elif defined(_SC_IOV_MAX)
+  static int iovmax = -1;
+  if (iovmax == -1)
+    iovmax = sysconf(_SC_IOV_MAX);
+  return iovmax;
+#else
+  return 1024;
+#endif
+}
 
 static void uv__write(uv_stream_t* stream) {
   struct iovec* iov;
   QUEUE* q;
   uv_write_t* req;
+  int iovmax;
   int iovcnt;
   ssize_t n;
 
@@ -723,9 +733,11 @@ start:
   iov = (struct iovec*) &(req->bufs[req->write_index]);
   iovcnt = req->bufcnt - req->write_index;
 
+  iovmax = uv__getiovmax();
+
   /* Limit iov count to avoid EINVALs from writev() */
-  if (iovcnt > IOV_MAX)
-    iovcnt = IOV_MAX;
+  if (iovcnt > iovmax)
+    iovcnt = iovmax;
 
   /*
    * Now do the actual writev. Note that we've been updating the pointers
@@ -915,6 +927,27 @@ static uv_handle_type uv__handle_type(int fd) {
 }
 
 
+static void uv__stream_read_cb(uv_stream_t* stream,
+                               int status,
+                               uv_buf_t buf,
+                               uv_handle_type type) {
+  if (stream->read_cb != NULL)
+    stream->read_cb(stream, status, buf);
+  else
+    stream->read2_cb((uv_pipe_t*) stream, status, buf, type);
+}
+
+
+static void uv__stream_eof(uv_stream_t* stream, uv_buf_t buf) {
+  stream->flags |= UV_STREAM_READ_EOF;
+  uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN);
+  if (!uv__io_active(&stream->io_watcher, UV__POLLOUT))
+    uv__handle_stop(stream);
+  uv__set_artificial_error(stream->loop, UV_EOF);
+  uv__stream_read_cb(stream, -1, buf, UV_UNKNOWN_HANDLE);
+}
+
+
 static void uv__read(uv_stream_t* stream) {
   uv_buf_t buf;
   ssize_t nread;
@@ -923,6 +956,8 @@ static void uv__read(uv_stream_t* stream) {
   char cmsg_space[64];
   int count;
 
+  stream->flags &= ~UV_STREAM_READ_PARTIAL;
+
   /* Prevent loop starvation when the data comes in as fast as (or faster than)
    * we can read it. XXX Need to rearm fd if we switch to edge-triggered I/O.
    */
@@ -964,15 +999,6 @@ static void uv__read(uv_stream_t* stream) {
       while (nread < 0 && errno == EINTR);
     }
 
-#define INVOKE_READ_CB(stream, status, buf, type)                             \
-    do {                                                                      \
-      if ((stream)->read_cb != NULL)                                          \
-        (stream)->read_cb((stream), (status), (buf));                         \
-      else                                                                    \
-        (stream)->read2_cb((uv_pipe_t*) (stream), (status), (buf), (type));   \
-    }                                                                         \
-    while (0)
-
     if (nread < 0) {
       /* Error */
       if (errno == EAGAIN || errno == EWOULDBLOCK) {
@@ -981,22 +1007,17 @@ static void uv__read(uv_stream_t* stream) {
           uv__io_start(stream->loop, &stream->io_watcher, UV__POLLIN);
         }
         uv__set_sys_error(stream->loop, EAGAIN);
-        INVOKE_READ_CB(stream, 0, buf, UV_UNKNOWN_HANDLE);
+        uv__stream_read_cb(stream, 0, buf, UV_UNKNOWN_HANDLE);
       } else {
         /* Error. User should call uv_close(). */
         uv__set_sys_error(stream->loop, errno);
-        INVOKE_READ_CB(stream, -1, buf, UV_UNKNOWN_HANDLE);
+        uv__stream_read_cb(stream, -1, buf, UV_UNKNOWN_HANDLE);
         assert(!uv__io_active(&stream->io_watcher, UV__POLLIN) &&
                "stream->read_cb(status=-1) did not call uv_close()");
       }
       return;
     } else if (nread == 0) {
-      /* EOF */
-      uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN);
-      if (!uv__io_active(&stream->io_watcher, UV__POLLOUT))
-        uv__handle_stop(stream);
-      uv__set_artificial_error(stream->loop, UV_EOF);
-      INVOKE_READ_CB(stream, -1, buf, UV_UNKNOWN_HANDLE);
+      uv__stream_eof(stream, buf);
       return;
     } else {
       /* Successful read */
@@ -1047,6 +1068,7 @@ static void uv__read(uv_stream_t* stream) {
 
       /* Return if we didn't fill the buffer, there is no more data to read. */
       if (nread < buflen) {
+        stream->flags |= UV_STREAM_READ_PARTIAL;
         return;
       }
     }
@@ -1095,17 +1117,33 @@ static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
     return;
   }
 
-  if (events & (UV__POLLIN | UV__POLLERR | UV__POLLHUP)) {
-    assert(uv__stream_fd(stream) >= 0);
+  assert(uv__stream_fd(stream) >= 0);
 
+  /* Ignore POLLHUP here. Even it it's set, there may still be data to read. */
+  if (events & (UV__POLLIN | UV__POLLERR))
     uv__read(stream);
 
-    if (uv__stream_fd(stream) == -1)
-      return; /* read_cb closed stream. */
+  if (uv__stream_fd(stream) == -1)
+    return;  /* read_cb closed stream. */
+
+  /* Short-circuit iff POLLHUP is set, the user is still interested in read
+   * events and uv__read() reported a partial read but not EOF. If the EOF
+   * flag is set, uv__read() called read_cb with err=UV_EOF and we don't
+   * have to do anything. If the partial read flag is not set, we can't
+   * report the EOF yet because there is still data to read.
+   */
+  if ((events & UV__POLLHUP) &&
+      (stream->flags & UV_STREAM_READING) &&
+      (stream->flags & UV_STREAM_READ_PARTIAL) &&
+      !(stream->flags & UV_STREAM_READ_EOF)) {
+    uv_buf_t buf = { NULL, 0 };
+    uv__stream_eof(stream, buf);
   }
 
-  if (events & UV__POLLOUT) {
-    assert(uv__stream_fd(stream) >= 0);
+  if (uv__stream_fd(stream) == -1)
+    return;  /* read_cb closed stream. */
+
+  if (events & (UV__POLLOUT | UV__POLLERR | UV__POLLHUP)) {
     uv__write(stream);
     uv__write_callbacks(stream);
   }
@@ -1378,8 +1416,9 @@ void uv__stream_close(uv_stream_t* handle) {
   }
 #endif /* defined(__APPLE__) */
 
-  uv_read_stop(handle);
   uv__io_close(handle->loop, &handle->io_watcher);
+  uv_read_stop(handle);
+  uv__handle_stop(handle);
 
   close(handle->io_watcher.fd);
   handle->io_watcher.fd = -1;
@@ -1391,3 +1430,8 @@ void uv__stream_close(uv_stream_t* handle) {
 
   assert(!uv__io_active(&handle->io_watcher, UV__POLLIN | UV__POLLOUT));
 }
+
+
+int uv_stream_set_blocking(uv_stream_t* handle, int blocking) {
+  assert(0 && "implement me");
+}
index e44a77f..0cf65a5 100644 (file)
@@ -26,9 +26,7 @@
 #include <assert.h>
 #include <errno.h>
 
-#if defined(__APPLE__) && defined(__MACH__)
 #include <sys/time.h>
-#endif /* defined(__APPLE__) && defined(__MACH__) */
 
 #undef NANOSEC
 #define NANOSEC ((uint64_t) 1e9)
@@ -283,8 +281,10 @@ int uv_cond_init(uv_cond_t* cond) {
   if (pthread_condattr_init(&attr))
     return -1;
 
+#if !defined(__ANDROID__)
   if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC))
     goto error2;
+#endif
 
   if (pthread_cond_init(cond, &attr))
     goto error2;
@@ -336,7 +336,15 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
   timeout += uv__hrtime();
   ts.tv_sec = timeout / NANOSEC;
   ts.tv_nsec = timeout % NANOSEC;
+#if defined(__ANDROID__)
+  /*
+   * The bionic pthread implementation doesn't support CLOCK_MONOTONIC,
+   * but has this alternative function instead.
+   */
+  r = pthread_cond_timedwait_monotonic_np(cond, mutex, &ts);
+#else
   r = pthread_cond_timedwait(cond, mutex, &ts);
+#endif /* __ANDROID__ */
 #endif
 
 
index 3956e0b..64a2599 100644 (file)
@@ -301,37 +301,37 @@ int uv_udp_recv_stop(uv_udp_t* handle) {
   return uv__udp_recv_stop(handle);
 }
 
+
+struct thread_ctx {
+  void (*entry)(void* arg);
+  void* arg;
+};
+
+
 #ifdef _WIN32
-static UINT __stdcall uv__thread_start(void *ctx_v)
+static UINT __stdcall uv__thread_start(void* arg)
 #else
-static void *uv__thread_start(void *ctx_v)
+static void* uv__thread_start(void *arg)
 #endif
 {
-  void (*entry)(void *arg);
-  void *arg;
-
-  struct {
-    void (*entry)(void *arg);
-    void *arg;
-  } *ctx;
+  struct thread_ctx *ctx_p;
+  struct thread_ctx ctx;
 
-  ctx = ctx_v;
-  arg = ctx->arg;
-  entry = ctx->entry;
-  free(ctx);
-  entry(arg);
+  ctx_p = arg;
+  ctx = *ctx_p;
+  free(ctx_p);
+  ctx.entry(ctx.arg);
 
   return 0;
 }
 
 
 int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
-  struct {
-    void (*entry)(void *arg);
-    void *arg;
-  } *ctx;
+  struct thread_ctx* ctx;
+  int err;
 
-  if ((ctx = malloc(sizeof *ctx)) == NULL)
+  ctx = malloc(sizeof(*ctx));
+  if (ctx == NULL)
     return -1;
 
   ctx->entry = entry;
@@ -339,15 +339,15 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
 
 #ifdef _WIN32
   *tid = (HANDLE) _beginthreadex(NULL, 0, uv__thread_start, ctx, 0, NULL);
-  if (*tid == 0) {
+  err = *tid ? 0 : errno;
 #else
-  if (pthread_create(tid, NULL, uv__thread_start, ctx)) {
+  err = pthread_create(tid, NULL, uv__thread_start, ctx);
 #endif
+
+  if (err)
     free(ctx);
-    return -1;
-  }
 
-  return 0;
+  return err ? -1 : 0;
 }
 
 
index 9114afb..9ec64f6 100644 (file)
@@ -31,7 +31,7 @@
 
 #define UV_VERSION_MAJOR 0
 #define UV_VERSION_MINOR 11
-#define UV_VERSION_PATCH 4
+#define UV_VERSION_PATCH 5
 #define UV_VERSION_IS_RELEASE 1
 
 
index f0909cd..525eda5 100644 (file)
@@ -58,6 +58,7 @@
 #define UV_HANDLE_SYNC_BYPASS_IOCP              0x00040000
 #define UV_HANDLE_ZERO_READ                     0x00080000
 #define UV_HANDLE_EMULATE_IOCP                  0x00100000
+#define UV_HANDLE_BLOCKING_WRITES               0x00200000
 
 /* Only used by uv_tcp_t handles. */
 #define UV_HANDLE_IPV6                          0x01000000
index 0fb70ea..8df2fcc 100644 (file)
@@ -1128,6 +1128,13 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req,
     /* Write the header or the whole frame. */
     memset(&ipc_header_req->overlapped, 0, sizeof(ipc_header_req->overlapped));
 
+    /* Using overlapped IO, but wait for completion before returning.
+       This write is blocking because ipc_frame is on stack. */
+    ipc_header_req->overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL);
+    if (!ipc_header_req->overlapped.hEvent) {
+      uv_fatal_error(GetLastError(), "CreateEvent");
+    }
+
     result = WriteFile(handle->handle,
                         &ipc_frame,
                         ipc_frame.header.flags & UV_IPC_TCP_SERVER ?
@@ -1136,18 +1143,22 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req,
                         &ipc_header_req->overlapped);
     if (!result && GetLastError() != ERROR_IO_PENDING) {
       uv__set_sys_error(loop, GetLastError());
+      CloseHandle(ipc_header_req->overlapped.hEvent);
       return -1;
     }
 
-    if (result) {
-      /* Request completed immediately. */
-      ipc_header_req->queued_bytes = 0;
-    } else {
-      /* Request queued by the kernel. */
-      ipc_header_req->queued_bytes = ipc_frame.header.flags & UV_IPC_TCP_SERVER ?
-        sizeof(ipc_frame) : sizeof(ipc_frame.header);
-      handle->write_queue_size += ipc_header_req->queued_bytes;
+    if (!result) {
+      /* Request not completed immediately. Wait for it.*/
+      if (WaitForSingleObject(ipc_header_req->overlapped.hEvent, INFINITE) !=
+          WAIT_OBJECT_0) {
+        uv__set_sys_error(loop, GetLastError());
+        CloseHandle(ipc_header_req->overlapped.hEvent);
+        return -1;
+      }
     }
+    ipc_header_req->queued_bytes = 0;
+    CloseHandle(ipc_header_req->overlapped.hEvent);
+    ipc_header_req->overlapped.hEvent = NULL;
 
     REGISTER_HANDLE_REQ(loop, handle, ipc_header_req);
     handle->reqs_pending++;
@@ -1159,7 +1170,29 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req,
     }
   }
 
-  if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
+  if ((handle->flags &
+      (UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) ==
+      (UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) {
+    DWORD bytes;
+    result = WriteFile(handle->handle,
+                       bufs[0].base,
+                       bufs[0].len,
+                       &bytes,
+                       NULL);
+
+    if (!result) {
+      return uv__set_sys_error(loop, GetLastError());
+    } else {
+      /* Request completed immediately. */
+      req->queued_bytes = 0;
+    }
+
+    REGISTER_HANDLE_REQ(loop, handle, req);
+    handle->reqs_pending++;
+    handle->write_reqs_pending++;
+    POST_COMPLETION_FOR_REQ(loop, req);
+    return 0;
+  } else if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
     req->write_buffer = bufs[0];
     uv_insert_non_overlapped_write_req(handle, req);
     if (handle->write_reqs_pending == 0) {
@@ -1169,6 +1202,44 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req,
     /* Request queued by the kernel. */
     req->queued_bytes = uv_count_bufs(bufs, bufcnt);
     handle->write_queue_size += req->queued_bytes;
+  } else if (handle->flags & UV_HANDLE_BLOCKING_WRITES) {
+    /* Using overlapped IO, but wait for completion before returning */
+    req->overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL);
+    if (!req->overlapped.hEvent) {
+      uv_fatal_error(GetLastError(), "CreateEvent");
+    }
+
+    result = WriteFile(handle->handle,
+                       bufs[0].base,
+                       bufs[0].len,
+                       NULL,
+                       &req->overlapped);
+
+    if (!result && GetLastError() != ERROR_IO_PENDING) {
+      uv__set_sys_error(loop, GetLastError());
+      CloseHandle(req->overlapped.hEvent);
+      return -1;
+    }
+
+    if (result) {
+      /* Request completed immediately. */
+      req->queued_bytes = 0;
+    } else {
+      /* Request queued by the kernel. */
+      if (WaitForSingleObject(ipc_header_req->overlapped.hEvent, INFINITE) !=
+          WAIT_OBJECT_0) {
+        uv__set_sys_error(loop, GetLastError());
+        CloseHandle(ipc_header_req->overlapped.hEvent);
+        return -1;
+      }
+    }
+    CloseHandle(req->overlapped.hEvent);
+
+    REGISTER_HANDLE_REQ(loop, handle, req);
+    handle->reqs_pending++;
+    handle->write_reqs_pending++;
+    POST_COMPLETION_FOR_REQ(loop, req);
+    return 0;
   } else {
     result = WriteFile(handle->handle,
                        bufs[0].base,
index edc5407..2648585 100644 (file)
@@ -196,3 +196,13 @@ int uv_is_readable(const uv_stream_t* handle) {
 int uv_is_writable(const uv_stream_t* handle) {
   return !!(handle->flags & UV_HANDLE_WRITABLE);
 }
+
+
+int uv_stream_set_blocking(uv_stream_t* handle, int blocking) {
+  if (blocking != 0)
+    handle->flags |= UV_HANDLE_BLOCKING_WRITES;
+  else
+    handle->flags &= ~UV_HANDLE_BLOCKING_WRITES;
+
+  return 0;
+}
index c3ef653..59a36de 100644 (file)
@@ -50,7 +50,7 @@ static int uv__tcp_nodelay(uv_tcp_t* handle, SOCKET socket, int enable) {
                  TCP_NODELAY,
                  (const char*)&enable,
                  sizeof enable) == -1) {
-    uv__set_sys_error(handle->loop, errno);
+    uv__set_sys_error(handle->loop, WSAGetLastError());
     return -1;
   }
   return 0;
@@ -63,7 +63,7 @@ static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsign
                  SO_KEEPALIVE,
                  (const char*)&enable,
                  sizeof enable) == -1) {
-    uv__set_sys_error(handle->loop, errno);
+    uv__set_sys_error(handle->loop, WSAGetLastError());
     return -1;
   }
 
@@ -72,7 +72,7 @@ static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsign
                            TCP_KEEPALIVE,
                            (const char*)&delay,
                            sizeof delay) == -1) {
-    uv__set_sys_error(handle->loop, errno);
+    uv__set_sys_error(handle->loop, WSAGetLastError());
     return -1;
   }
 
index 8eedb49..ed7f115 100644 (file)
@@ -31,7 +31,7 @@
 #include "uv.h"
 #include "internal.h"
 
-#include <Winsock2.h>
+#include <winsock2.h>
 #include <iphlpapi.h>
 #include <psapi.h>
 #include <tlhelp32.h>
index 308201e..1e3f8df 100644 (file)
 # define TEST_PIPENAME_2 "/tmp/uv-test-sock2"
 #endif
 
+#ifdef _WIN32
+# include <io.h>
+# ifndef S_IRUSR
+#  define S_IRUSR _S_IREAD
+# endif
+# ifndef S_IWUSR
+#  define S_IWUSR _S_IWRITE
+# endif
+#endif
+
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
 #define container_of(ptr, type, member) \
index 37f9cf2..e989511 100644 (file)
@@ -56,7 +56,7 @@ static void create_file(uv_loop_t* loop, const char* name) {
   uv_fs_t req;
 
   r = uv_fs_open(loop, &req, name, O_WRONLY | O_CREAT,
-      S_IWRITE | S_IREAD, NULL);
+      S_IWUSR | S_IRUSR, NULL);
   ASSERT(r != -1);
   file = r;
   uv_fs_req_cleanup(&req);
index 6459d12..1ab958f 100644 (file)
@@ -600,7 +600,7 @@ TEST_IMPL(fs_file_async) {
   loop = uv_default_loop();
 
   r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT,
-      S_IREAD | S_IWRITE, create_cb);
+      S_IRUSR | S_IWUSR, create_cb);
   ASSERT(r == 0);
   uv_run(loop, UV_RUN_DEFAULT);
 
@@ -663,7 +663,7 @@ TEST_IMPL(fs_file_sync) {
   loop = uv_default_loop();
 
   r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT,
-      S_IWRITE | S_IREAD, NULL);
+      S_IWUSR | S_IRUSR, NULL);
   ASSERT(r != -1);
   ASSERT(open_req1.result != -1);
   uv_fs_req_cleanup(&open_req1);
@@ -756,7 +756,7 @@ TEST_IMPL(fs_async_dir) {
 
   /* Create 2 files synchronously. */
   r = uv_fs_open(loop, &open_req1, "test_dir/file1", O_WRONLY | O_CREAT,
-      S_IWRITE | S_IREAD, NULL);
+      S_IWUSR | S_IRUSR, NULL);
   ASSERT(r != -1);
   uv_fs_req_cleanup(&open_req1);
   r = uv_fs_close(loop, &close_req, open_req1.result, NULL);
@@ -764,7 +764,7 @@ TEST_IMPL(fs_async_dir) {
   uv_fs_req_cleanup(&close_req);
 
   r = uv_fs_open(loop, &open_req1, "test_dir/file2", O_WRONLY | O_CREAT,
-      S_IWRITE | S_IREAD, NULL);
+      S_IWUSR | S_IRUSR, NULL);
   ASSERT(r != -1);
   uv_fs_req_cleanup(&open_req1);
   r = uv_fs_close(loop, &close_req, open_req1.result, NULL);
@@ -840,7 +840,7 @@ TEST_IMPL(fs_async_sendfile) {
   unlink("test_file");
   unlink("test_file2");
 
-  f = open("test_file", O_WRONLY | O_CREAT, S_IWRITE | S_IREAD);
+  f = open("test_file", O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR);
   ASSERT(f != -1);
 
   r = write(f, "begin\n", 6);
@@ -862,7 +862,7 @@ TEST_IMPL(fs_async_sendfile) {
   uv_fs_req_cleanup(&open_req1);
 
   r = uv_fs_open(loop, &open_req2, "test_file2", O_WRONLY | O_CREAT,
-      S_IWRITE | S_IREAD, NULL);
+      S_IWUSR | S_IRUSR, NULL);
   ASSERT(r != -1);
   ASSERT(open_req2.result != -1);
   uv_fs_req_cleanup(&open_req2);
@@ -909,7 +909,7 @@ TEST_IMPL(fs_fstat) {
   loop = uv_default_loop();
 
   r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT,
-      S_IWRITE | S_IREAD, NULL);
+      S_IWUSR | S_IRUSR, NULL);
   ASSERT(r != -1);
   ASSERT(req.result != -1);
   file = req.result;
@@ -1003,7 +1003,7 @@ TEST_IMPL(fs_chmod) {
   loop = uv_default_loop();
 
   r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT,
-      S_IWRITE | S_IREAD, NULL);
+      S_IWUSR | S_IRUSR, NULL);
   ASSERT(r != -1);
   ASSERT(req.result != -1);
   file = req.result;
@@ -1100,7 +1100,7 @@ TEST_IMPL(fs_chown) {
   loop = uv_default_loop();
 
   r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT,
-      S_IWRITE | S_IREAD, NULL);
+      S_IWUSR | S_IRUSR, NULL);
   ASSERT(r != -1);
   ASSERT(req.result != -1);
   file = req.result;
@@ -1166,7 +1166,7 @@ TEST_IMPL(fs_link) {
   loop = uv_default_loop();
 
   r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT,
-      S_IWRITE | S_IREAD, NULL);
+      S_IWUSR | S_IRUSR, NULL);
   ASSERT(r != -1);
   ASSERT(req.result != -1);
   file = req.result;
@@ -1274,7 +1274,7 @@ TEST_IMPL(fs_symlink) {
   loop = uv_default_loop();
 
   r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT,
-      S_IWRITE | S_IREAD, NULL);
+      S_IWUSR | S_IRUSR, NULL);
   ASSERT(r != -1);
   ASSERT(req.result != -1);
   file = req.result;
@@ -1439,7 +1439,7 @@ TEST_IMPL(fs_symlink_dir) {
   uv_fs_req_cleanup(&req);
 
   r = uv_fs_open(loop, &open_req1, "test_dir/file1", O_WRONLY | O_CREAT,
-      S_IWRITE | S_IREAD, NULL);
+      S_IWUSR | S_IRUSR, NULL);
   ASSERT(r != -1);
   uv_fs_req_cleanup(&open_req1);
   r = uv_fs_close(loop, &close_req, open_req1.result, NULL);
@@ -1447,7 +1447,7 @@ TEST_IMPL(fs_symlink_dir) {
   uv_fs_req_cleanup(&close_req);
 
   r = uv_fs_open(loop, &open_req1, "test_dir/file2", O_WRONLY | O_CREAT,
-      S_IWRITE | S_IREAD, NULL);
+      S_IWUSR | S_IRUSR, NULL);
   ASSERT(r != -1);
   uv_fs_req_cleanup(&open_req1);
   r = uv_fs_close(loop, &close_req, open_req1.result, NULL);
@@ -1504,7 +1504,7 @@ TEST_IMPL(fs_utime) {
   loop = uv_default_loop();
   unlink(path);
   r = uv_fs_open(loop, &req, path, O_RDWR | O_CREAT,
-      S_IWRITE | S_IREAD, NULL);
+      S_IWUSR | S_IRUSR, NULL);
   ASSERT(r != -1);
   ASSERT(req.result != -1);
   uv_fs_req_cleanup(&req);
@@ -1589,7 +1589,7 @@ TEST_IMPL(fs_futime) {
   loop = uv_default_loop();
   unlink(path);
   r = uv_fs_open(loop, &req, path, O_RDWR | O_CREAT,
-      S_IWRITE | S_IREAD, NULL);
+      S_IWUSR | S_IRUSR, NULL);
   ASSERT(r != -1);
   ASSERT(req.result != -1);
   uv_fs_req_cleanup(&req);
@@ -1747,7 +1747,7 @@ TEST_IMPL(fs_file_open_append) {
   loop = uv_default_loop();
 
   r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT,
-      S_IWRITE | S_IREAD, NULL);
+      S_IWUSR | S_IRUSR, NULL);
   ASSERT(r != -1);
   ASSERT(open_req1.result != -1);
   uv_fs_req_cleanup(&open_req1);
@@ -1779,7 +1779,7 @@ TEST_IMPL(fs_file_open_append) {
   ASSERT(close_req.result != -1);
   uv_fs_req_cleanup(&close_req);
 
-  r = uv_fs_open(loop, &open_req1, "test_file", O_RDONLY, S_IREAD, NULL);
+  r = uv_fs_open(loop, &open_req1, "test_file", O_RDONLY, S_IRUSR, NULL);
   ASSERT(r != -1);
   ASSERT(open_req1.result != -1);
   uv_fs_req_cleanup(&open_req1);
@@ -1817,7 +1817,7 @@ TEST_IMPL(fs_rename_to_existing_file) {
   loop = uv_default_loop();
 
   r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT,
-      S_IWRITE | S_IREAD, NULL);
+      S_IWUSR | S_IRUSR, NULL);
   ASSERT(r != -1);
   ASSERT(open_req1.result != -1);
   uv_fs_req_cleanup(&open_req1);
@@ -1834,7 +1834,7 @@ TEST_IMPL(fs_rename_to_existing_file) {
   uv_fs_req_cleanup(&close_req);
 
   r = uv_fs_open(loop, &open_req1, "test_file2", O_WRONLY | O_CREAT,
-      S_IWRITE | S_IREAD, NULL);
+      S_IWUSR | S_IRUSR, NULL);
   ASSERT(r != -1);
   ASSERT(open_req1.result != -1);
   uv_fs_req_cleanup(&open_req1);
@@ -1885,7 +1885,7 @@ TEST_IMPL(fs_read_file_eof) {
   loop = uv_default_loop();
 
   r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT,
-      S_IWRITE | S_IREAD, NULL);
+      S_IWUSR | S_IRUSR, NULL);
   ASSERT(r != -1);
   ASSERT(open_req1.result != -1);
   uv_fs_req_cleanup(&open_req1);
index 56eca9c..afa8d91 100644 (file)
@@ -222,7 +222,7 @@ TEST_IMPL(spawn_stdout_to_file) {
   init_process_options("spawn_helper2", exit_cb);
 
   r = uv_fs_open(uv_default_loop(), &fs_req, "stdout_file", O_CREAT | O_RDWR,
-      S_IREAD | S_IWRITE, NULL);
+      S_IRUSR | S_IWUSR, NULL);
   ASSERT(r != -1);
   uv_fs_req_cleanup(&fs_req);
 
index 2e22885..e000b18 100644 (file)
@@ -20,7 +20,8 @@
         'conditions': [
           ['OS=="solaris"', {
             'cflags': [ '-pthreads' ],
-          }, {
+          }],
+          ['OS not in "solaris android"', {
             'cflags': [ '-pthread' ],
           }],
         ],
             'conditions': [
               ['OS=="solaris"', {
                 'ldflags': [ '-pthreads' ],
-              }, {
+              }],
+              ['OS != "solaris" and OS != "android"', {
                 'ldflags': [ '-pthread' ],
               }],
             ],
             }],
           ],
         }],
-        [ 'OS=="linux" or OS=="mac"', {
+        [ 'OS in "linux mac android"', {
           'sources': [ 'src/unix/proctitle.c' ],
         }],
         [ 'OS=="mac"', {
             'libraries': [ '-ldl', '-lrt' ],
           },
         }],
+        [ 'OS=="android"', {
+          'sources': [
+            'src/unix/linux-core.c',
+            'src/unix/linux-inotify.c',
+            'src/unix/linux-syscalls.c',
+            'src/unix/linux-syscalls.h',
+            'src/unix/pthread-fixes.c',
+          ],
+          'link_settings': {
+            'libraries': [ '-ldl' ],
+          },
+        }],
         [ 'OS=="solaris"', {
           'sources': [ 'src/unix/sunos.c' ],
           'defines': [