uv: upgrade to e4680cc
authorBen Noordhuis <info@bnoordhuis.nl>
Fri, 18 Nov 2011 12:07:01 +0000 (13:07 +0100)
committerBen Noordhuis <info@bnoordhuis.nl>
Fri, 18 Nov 2011 12:07:01 +0000 (13:07 +0100)
19 files changed:
deps/uv/config-unix.mk
deps/uv/include/uv-private/uv-unix.h
deps/uv/include/uv-private/uv-win.h
deps/uv/include/uv.h
deps/uv/src/unix/core.c
deps/uv/src/unix/internal.h
deps/uv/src/unix/kqueue.c
deps/uv/src/unix/process.c
deps/uv/src/unix/stream.c
deps/uv/src/unix/thread.c [new file with mode: 0644]
deps/uv/src/win/handle.c
deps/uv/src/win/thread.c [new file with mode: 0644]
deps/uv/src/win/threads.c [deleted file]
deps/uv/src/win/winapi.c
deps/uv/src/win/winapi.h
deps/uv/test/test-fs-event.c
deps/uv/test/test-list.h
deps/uv/test/test-mutexes.c [new file with mode: 0644]
deps/uv/uv.gyp

index 8fe7254..c8220c5 100644 (file)
@@ -33,6 +33,7 @@ OBJS += src/unix/fs.o
 OBJS += src/unix/cares.o
 OBJS += src/unix/udp.o
 OBJS += src/unix/error.o
+OBJS += src/unix/thread.o
 OBJS += src/unix/process.o
 OBJS += src/unix/tcp.o
 OBJS += src/unix/pipe.o
index 21078fe..abbccc2 100644 (file)
@@ -34,6 +34,7 @@
 #include <arpa/inet.h>
 #include <netdb.h>
 #include <termios.h>
+#include <pthread.h>
 
 /* Note: May be cast to struct iovec. See writev(2). */
 typedef struct {
@@ -43,6 +44,9 @@ typedef struct {
 
 typedef int uv_file;
 
+typedef pthread_mutex_t uv_mutex_t;
+typedef pthread_rwlock_t uv_rwlock_t;
+
 /* Platform-specific definitions for uv_dlopen support. */
 typedef void* uv_lib_t;
 #define UV_DYNAMIC /* empty */
index 5d46109..e5afd32 100644 (file)
@@ -137,6 +137,17 @@ typedef struct uv_buf_t {
 
 typedef int uv_file;
 
+typedef CRITICAL_SECTION uv_mutex_t;
+
+typedef union {
+  SRWLOCK srwlock_;
+  struct {
+    uv_mutex_t read_mutex_;
+    uv_mutex_t write_mutex_;
+    unsigned int num_readers_;
+  } fallback_;
+} uv_rwlock_t;
+
 /* Platform-specific definitions for uv_dlopen support. */
 typedef HMODULE uv_lib_t;
 #define UV_DYNAMIC FAR WINAPI
index a2c4f2a..3da160a 100644 (file)
@@ -1243,6 +1243,20 @@ UV_EXTERN uv_err_t uv_dlclose(uv_lib_t library);
  */
 UV_EXTERN uv_err_t uv_dlsym(uv_lib_t library, const char* name, void** ptr);
 
+UV_EXTERN int uv_mutex_init(uv_mutex_t* handle);
+UV_EXTERN void uv_mutex_destroy(uv_mutex_t* handle);
+UV_EXTERN void uv_mutex_lock(uv_mutex_t* handle);
+UV_EXTERN int uv_mutex_trylock(uv_mutex_t* handle);
+UV_EXTERN void uv_mutex_unlock(uv_mutex_t* handle);
+
+UV_EXTERN int uv_rwlock_init(uv_rwlock_t* rwlock);
+UV_EXTERN void uv_rwlock_destroy(uv_rwlock_t* rwlock);
+UV_EXTERN void uv_rwlock_rdlock(uv_rwlock_t* rwlock);
+UV_EXTERN int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock);
+UV_EXTERN void uv_rwlock_rdunlock(uv_rwlock_t* rwlock);
+UV_EXTERN void uv_rwlock_wrlock(uv_rwlock_t* rwlock);
+UV_EXTERN int uv_rwlock_trywrlock(uv_rwlock_t* rwlock);
+UV_EXTERN void uv_rwlock_wrunlock(uv_rwlock_t* rwlock);
 
 /* the presence of these unions force similar struct layout */
 union uv_any_handle {
index 4d83241..ac00569 100644 (file)
@@ -727,8 +727,8 @@ int uv__accept(int sockfd, struct sockaddr* saddr, socklen_t slen) {
   assert(sockfd >= 0);
 
   while (1) {
-#if HAVE_ACCEPT4
-    peerfd = accept4(sockfd, saddr, &slen, SOCK_NONBLOCK | SOCK_CLOEXEC);
+#if HAVE_SYS_ACCEPT4
+    peerfd = sys_accept4(sockfd, saddr, &slen, SOCK_NONBLOCK | SOCK_CLOEXEC);
 
     if (peerfd != -1)
       break;
index 12ab621..4784bcf 100644 (file)
 #include <stddef.h> /* offsetof */
 
 #undef HAVE_FUTIMES
-#undef HAVE_PIPE2
-#undef HAVE_ACCEPT4
 #undef HAVE_KQUEUE
 #undef HAVE_PORTS_FS
 
 #if defined(__linux__)
 
-#include <linux/version.h>
-#include <features.h>
+# undef HAVE_SYS_UTIMESAT
+# undef HAVE_SYS_PIPE2
+# undef HAVE_SYS_ACCEPT4
 
-/* futimes() requires linux >= 2.6.22 and glib >= 2.6 */
-#if LINUX_VERSION_CODE >= 0x20616 && __GLIBC_PREREQ(2, 6)
-#define HAVE_FUTIMES 1
-#endif
+# undef _GNU_SOURCE
+# define _GNU_SOURCE
 
-/* pipe2() requires linux >= 2.6.27 and glibc >= 2.9 */
-#if LINUX_VERSION_CODE >= 0x2061B && __GLIBC_PREREQ(2, 9)
-#define HAVE_PIPE2 1
-#endif
+# include <linux/version.h>
+# include <sys/syscall.h>
+# include <features.h>
+# include <unistd.h>
 
-/* accept4() requires linux >= 2.6.28 and glib >= 2.10 */
-#if LINUX_VERSION_CODE >= 0x2061C && __GLIBC_PREREQ(2, 10)
-#define HAVE_ACCEPT4 1
-#endif
+# if __NR_utimensat
+#  define HAVE_SYS_UTIMESAT 1
+# endif
+# if __NR_pipe2
+#  define HAVE_SYS_PIPE2 1
+# endif
+# if __NR_accept4
+#  define HAVE_SYS_ACCEPT4 1
+# endif
+
+# if HAVE_SYS_UTIMESAT
+inline static int sys_utimesat(int dirfd,
+                               const char* path,
+                               const struct timespec times[2],
+                               int flags)
+{
+  return syscall(__NR_utimensat, dirfd, path, times, flags);
+}
+inline static int sys_futimes(int fd, const struct timeval times[2])
+{
+  struct timespec ts[2];
+  ts[0].tv_sec = times[0].tv_sec, ts[0].tv_nsec = times[0].tv_usec * 1000;
+  ts[1].tv_sec = times[1].tv_sec, ts[1].tv_nsec = times[1].tv_usec * 1000;
+  return sys_utimesat(fd, NULL, ts, 0);
+}
+#  undef HAVE_FUTIMES
+#  define HAVE_FUTIMES 1
+#  define futimes(fd, times) sys_futimes(fd, times)
+# endif /* HAVE_SYS_FUTIMESAT */
+
+# if HAVE_SYS_PIPE2
+inline static int sys_pipe2(int pipefd[2], int flags)
+{
+  return syscall(__NR_pipe2, pipefd, flags);
+}
+# endif /* HAVE_SYS_PIPE2 */
+
+# if HAVE_SYS_ACCEPT4
+inline static int sys_accept4(int fd,
+                              struct sockaddr* addr,
+                              socklen_t* addrlen,
+                              int flags)
+{
+  return syscall(__NR_accept4, fd, addr, addrlen, flags);
+}
+# endif /* HAVE_SYS_ACCEPT4 */
 
 #endif /* __linux__ */
 
index 00180cd..ad80a26 100644 (file)
@@ -116,6 +116,7 @@ int uv_fs_event_init(uv_loop_t* loop,
 
 
 void uv__fs_event_destroy(uv_fs_event_t* handle) {
+  uv__fs_event_stop(handle);
   free(handle->filename);
   uv__close(handle->fd);
   handle->fd = -1;
index c5a4592..5581d8b 100644 (file)
@@ -104,7 +104,7 @@ static int uv__make_socketpair(int fds[2], int flags) {
 
 
 static int uv__make_pipe(int fds[2], int flags) {
-#if HAVE_PIPE2
+#if HAVE_SYS_PIPE2
   int fl;
 
   fl = O_CLOEXEC;
@@ -112,7 +112,7 @@ static int uv__make_pipe(int fds[2], int flags) {
   if (flags & UV__F_NONBLOCK)
     fl |= O_NONBLOCK;
 
-  if (pipe2(fds, fl) == 0)
+  if (sys_pipe2(fds, fl) == 0)
     return 0;
 
   if (errno != ENOSYS)
index 2573781..3cdeaa8 100644 (file)
@@ -145,7 +145,7 @@ void uv__stream_destroy(uv_stream_t* stream) {
 
     req = ngx_queue_data(q, uv_write_t, queue);
     if (req->cb) {
-      uv__set_sys_error(stream->loop, req->error);
+      uv__set_artificial_error(stream->loop, req->error);
       req->cb(req, req->error ? -1 : 0);
     }
   }
@@ -490,7 +490,7 @@ static void uv__write_callbacks(uv_stream_t* stream) {
 
     /* NOTE: call callback AFTER freeing the request data. */
     if (req->cb) {
-      uv__set_sys_error(stream->loop, req->error);
+      uv__set_artificial_error(stream->loop, req->error);
       req->cb(req, req->error ? -1 : 0);
     }
 
diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c
new file mode 100644 (file)
index 0000000..b5c0f19
--- /dev/null
@@ -0,0 +1,141 @@
+/* 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 "internal.h"
+
+#include <pthread.h>
+#include <errno.h>
+
+
+#ifdef NDEBUG
+# define CHECK(r) ((void) (r))
+#else
+# include <stdio.h>
+# include <stdlib.h>
+# define CHECK(r)                                 \
+    do {                                          \
+      int __r = (r);                              \
+      if (__r) errno = __r, perror(#r), abort();  \
+    }                                             \
+    while (0)
+#endif
+
+
+int uv_mutex_init(uv_mutex_t* mutex) {
+  if (pthread_mutex_init(mutex, NULL))
+    return -1;
+  else
+    return 0;
+}
+
+
+void uv_mutex_destroy(uv_mutex_t* mutex) {
+  CHECK(pthread_mutex_destroy(mutex));
+}
+
+
+void uv_mutex_lock(uv_mutex_t* mutex) {
+  CHECK(pthread_mutex_lock(mutex));
+}
+
+
+int uv_mutex_trylock(uv_mutex_t* mutex) {
+  int r;
+
+  r = pthread_mutex_trylock(mutex);
+
+  if (r && r != EAGAIN)
+    CHECK(r);
+
+  if (r)
+    return -1;
+  else
+    return 0;
+}
+
+
+void uv_mutex_unlock(uv_mutex_t* mutex) {
+  CHECK(pthread_mutex_unlock(mutex));
+}
+
+
+int uv_rwlock_init(uv_rwlock_t* rwlock) {
+  if (pthread_rwlock_init(rwlock, NULL))
+    return -1;
+  else
+    return 0;
+}
+
+
+void uv_rwlock_destroy(uv_rwlock_t* rwlock) {
+  CHECK(pthread_rwlock_destroy(rwlock));
+}
+
+
+void uv_rwlock_rdlock(uv_rwlock_t* rwlock) {
+  CHECK(pthread_rwlock_rdlock(rwlock));
+}
+
+
+int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) {
+  int r;
+
+  r = pthread_rwlock_tryrdlock(rwlock);
+
+  if (r && r != EAGAIN)
+    CHECK(r);
+
+  if (r)
+    return -1;
+  else
+    return 0;
+}
+
+
+void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) {
+  CHECK(pthread_rwlock_unlock(rwlock));
+}
+
+
+void uv_rwlock_wrlock(uv_rwlock_t* rwlock) {
+  CHECK(pthread_rwlock_wrlock(rwlock));
+}
+
+
+int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) {
+  int r;
+
+  r = pthread_rwlock_trywrlock(rwlock);
+
+  if (r && r != EAGAIN)
+    CHECK(r);
+
+  if (r)
+    return -1;
+  else
+    return 0;
+}
+
+
+void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) {
+  CHECK(pthread_rwlock_unlock(rwlock));
+}
index b67139c..ba0af75 100644 (file)
@@ -35,7 +35,7 @@ uv_handle_type uv_guess_handle(uv_file file) {
       if (GetConsoleMode(handle, &mode)) {
         return UV_TTY;
       } else {
-        return UV_UNKNOWN_HANDLE;
+        return UV_FILE;
       }
 
     case FILE_TYPE_PIPE:
diff --git a/deps/uv/src/win/thread.c b/deps/uv/src/win/thread.c
new file mode 100644 (file)
index 0000000..1ee1a10
--- /dev/null
@@ -0,0 +1,320 @@
+/* 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 "../uv-common.h"
+#include "internal.h"
+#include <assert.h>
+
+#define HAVE_SRWLOCK_API() (pTryAcquireSRWLockShared != NULL)
+
+#ifdef _MSC_VER /* msvc */
+# define inline __inline
+# define NOINLINE __declspec (noinline)
+#else  /* gcc */
+# define inline inline
+# define NOINLINE __attribute__ ((noinline))
+#endif
+
+
+inline static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock);
+inline static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock);
+inline static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock);
+
+inline static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock);
+inline static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock);
+inline static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock);
+inline static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock);
+
+
+static NOINLINE void uv__once_inner(uv_once_t* guard,
+    void (*callback)(void)) {
+  DWORD result;
+  HANDLE existing_event, created_event;
+  HANDLE* event_ptr;
+
+  /* Fetch and align event_ptr */
+  event_ptr = (HANDLE*) (((uintptr_t) &guard->event + (sizeof(HANDLE) - 1)) &
+    ~(sizeof(HANDLE) - 1));
+
+  created_event = CreateEvent(NULL, 1, 0, NULL);
+  if (created_event == 0) {
+    /* Could fail in a low-memory situation? */
+    uv_fatal_error(GetLastError(), "CreateEvent");
+  }
+
+  existing_event = InterlockedCompareExchangePointer(event_ptr,
+                                                     created_event,
+                                                     NULL);
+
+  if (existing_event == NULL) {
+    /* We won the race */
+    callback();
+
+    result = SetEvent(created_event);
+    assert(result);
+    guard->ran = 1;
+
+  } else {
+    /* We lost the race. Destroy the event we created and wait for the */
+    /* existing one to become signaled. */
+    CloseHandle(created_event);
+    result = WaitForSingleObject(existing_event, INFINITE);
+    assert(result == WAIT_OBJECT_0);
+  }
+}
+
+
+void uv_once(uv_once_t* guard, void (*callback)(void)) {
+  /* Fast case - avoid WaitForSingleObject. */
+  if (guard->ran) {
+    return;
+  }
+
+  uv__once_inner(guard, callback);
+}
+
+int uv_mutex_init(uv_mutex_t* mutex) {
+  InitializeCriticalSection(mutex);
+  return 0;
+}
+
+
+void uv_mutex_destroy(uv_mutex_t* mutex) {
+  DeleteCriticalSection(mutex);
+}
+
+
+void uv_mutex_lock(uv_mutex_t* mutex) {
+  EnterCriticalSection(mutex);
+}
+
+
+int uv_mutex_trylock(uv_mutex_t* mutex) {
+  if (TryEnterCriticalSection(mutex))
+    return 0;
+  else
+    return -1;
+}
+
+
+void uv_mutex_unlock(uv_mutex_t* mutex) {
+  LeaveCriticalSection(mutex);
+}
+
+
+int uv_rwlock_init(uv_rwlock_t* rwlock) {
+  if (HAVE_SRWLOCK_API())
+    return uv__rwlock_srwlock_init(rwlock);
+  else
+    return uv__rwlock_fallback_init(rwlock);
+}
+
+
+void uv_rwlock_destroy(uv_rwlock_t* rwlock) {
+  if (HAVE_SRWLOCK_API())
+    uv__rwlock_srwlock_destroy(rwlock);
+  else
+    uv__rwlock_fallback_destroy(rwlock);
+}
+
+
+void uv_rwlock_rdlock(uv_rwlock_t* rwlock) {
+  if (HAVE_SRWLOCK_API())
+    uv__rwlock_srwlock_rdlock(rwlock);
+  else
+    uv__rwlock_fallback_rdlock(rwlock);
+}
+
+
+int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) {
+  if (HAVE_SRWLOCK_API())
+    return uv__rwlock_srwlock_tryrdlock(rwlock);
+  else
+    return uv__rwlock_fallback_tryrdlock(rwlock);
+}
+
+
+void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) {
+  if (HAVE_SRWLOCK_API())
+    uv__rwlock_srwlock_rdunlock(rwlock);
+  else
+    uv__rwlock_fallback_rdunlock(rwlock);
+}
+
+
+void uv_rwlock_wrlock(uv_rwlock_t* rwlock) {
+  if (HAVE_SRWLOCK_API())
+    uv__rwlock_srwlock_wrlock(rwlock);
+  else
+    uv__rwlock_fallback_wrlock(rwlock);
+}
+
+
+int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) {
+  if (HAVE_SRWLOCK_API())
+    return uv__rwlock_srwlock_trywrlock(rwlock);
+  else
+    return uv__rwlock_fallback_trywrlock(rwlock);
+}
+
+
+void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) {
+  if (HAVE_SRWLOCK_API())
+    uv__rwlock_srwlock_wrunlock(rwlock);
+  else
+    uv__rwlock_fallback_wrunlock(rwlock);
+}
+
+
+inline static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock) {
+  pInitializeSRWLock(&rwlock->srwlock_);
+  return 0;
+}
+
+
+inline static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock) {
+  (void) rwlock;
+}
+
+
+inline static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock) {
+  pAcquireSRWLockShared(&rwlock->srwlock_);
+}
+
+
+inline static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock) {
+  if (pTryAcquireSRWLockShared(&rwlock->srwlock_))
+    return 0;
+  else
+    return -1;
+}
+
+
+inline static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock) {
+  pReleaseSRWLockShared(&rwlock->srwlock_);
+}
+
+
+inline static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock) {
+  pAcquireSRWLockExclusive(&rwlock->srwlock_);
+}
+
+
+inline static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock) {
+  if (pTryAcquireSRWLockExclusive(&rwlock->srwlock_))
+    return 0;
+  else
+    return -1;
+}
+
+
+inline static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock) {
+  pReleaseSRWLockExclusive(&rwlock->srwlock_);
+}
+
+
+inline static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock) {
+  if (uv_mutex_init(&rwlock->fallback_.read_mutex_))
+    return -1;
+
+  if (uv_mutex_init(&rwlock->fallback_.write_mutex_)) {
+    uv_mutex_destroy(&rwlock->fallback_.read_mutex_);
+    return -1;
+  }
+
+  rwlock->fallback_.num_readers_ = 0;
+
+  return 0;
+}
+
+
+inline static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock) {
+  uv_mutex_destroy(&rwlock->fallback_.read_mutex_);
+  uv_mutex_destroy(&rwlock->fallback_.write_mutex_);
+}
+
+
+inline static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock) {
+  uv_mutex_lock(&rwlock->fallback_.read_mutex_);
+
+  if (++rwlock->fallback_.num_readers_ == 1)
+    uv_mutex_lock(&rwlock->fallback_.write_mutex_);
+
+  uv_mutex_unlock(&rwlock->fallback_.read_mutex_);
+}
+
+
+inline static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock) {
+  int ret;
+
+  ret = -1;
+
+  if (uv_mutex_trylock(&rwlock->fallback_.read_mutex_))
+    goto out;
+
+  if (rwlock->fallback_.num_readers_ == 0)
+    ret = uv_mutex_trylock(&rwlock->fallback_.write_mutex_);
+  else
+    ret = 0;
+
+  if (ret == 0)
+    rwlock->fallback_.num_readers_++;
+
+  uv_mutex_unlock(&rwlock->fallback_.read_mutex_);
+
+out:
+  return ret;
+}
+
+
+inline static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock) {
+  uv_mutex_lock(&rwlock->fallback_.read_mutex_);
+
+  if (--rwlock->fallback_.num_readers_ == 0)
+    uv_mutex_unlock(&rwlock->fallback_.write_mutex_);
+
+  uv_mutex_unlock(&rwlock->fallback_.read_mutex_);
+}
+
+
+inline static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock) {
+  uv_mutex_lock(&rwlock->fallback_.write_mutex_);
+}
+
+
+inline static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock) {
+  return uv_mutex_trylock(&rwlock->fallback_.write_mutex_);
+}
+
+
+inline static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock) {
+  uv_mutex_unlock(&rwlock->fallback_.write_mutex_);
+}
diff --git a/deps/uv/src/win/threads.c b/deps/uv/src/win/threads.c
deleted file mode 100644 (file)
index 1fc6b73..0000000
+++ /dev/null
@@ -1,81 +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 <assert.h>
-
-#include "uv.h"
-#include "../uv-common.h"
-#include "internal.h"
-
-
-#ifdef _MSC_VER /* msvc */
-# define NOINLINE __declspec (noinline)
-#else  /* gcc */
-# define NOINLINE __attribute__ ((noinline))
-#endif
-
-
-static NOINLINE void uv__once_inner(uv_once_t* guard,
-    void (*callback)(void)) {
-  DWORD result;
-  HANDLE existing_event, created_event;
-  HANDLE* event_ptr;
-
-  /* Fetch and align event_ptr */
-  event_ptr = (HANDLE*) (((uintptr_t) &guard->event + (sizeof(HANDLE) - 1)) &
-    ~(sizeof(HANDLE) - 1));
-
-  created_event = CreateEvent(NULL, 1, 0, NULL);
-  if (created_event == 0) {
-    /* Could fail in a low-memory situation? */
-    uv_fatal_error(GetLastError(), "CreateEvent");
-  }
-
-  existing_event = InterlockedCompareExchangePointer(event_ptr,
-                                                     created_event,
-                                                     NULL);
-
-  if (existing_event == NULL) {
-    /* We won the race */
-    callback();
-
-    result = SetEvent(created_event);
-    assert(result);
-    guard->ran = 1;
-
-  } else {
-    /* We lost the race. Destroy the event we created and wait for the */
-    /* existing one to become signaled. */
-    CloseHandle(created_event);
-    result = WaitForSingleObject(existing_event, INFINITE);
-    assert(result == WAIT_OBJECT_0);
-  }
-}
-
-
-void uv_once(uv_once_t* guard, void (*callback)(void)) {
-  /* Fast case - avoid WaitForSingleObject. */
-  if (guard->ran) {
-    return;
-  }
-
-  uv__once_inner(guard, callback);
-}
index cc21361..ff6912d 100644 (file)
@@ -33,6 +33,13 @@ sNtSetInformationFile pNtSetInformationFile;
 sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
 sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;
 sCreateSymbolicLinkW pCreateSymbolicLinkW;
+sInitializeSRWLock pInitializeSRWLock;
+sAcquireSRWLockShared pAcquireSRWLockShared;
+sAcquireSRWLockExclusive pAcquireSRWLockExclusive;
+sTryAcquireSRWLockShared pTryAcquireSRWLockShared;
+sTryAcquireSRWLockExclusive pTryAcquireSRWLockExclusive;
+sReleaseSRWLockShared pReleaseSRWLockShared;
+sReleaseSRWLockExclusive pReleaseSRWLockExclusive;
 
 
 void uv_winapi_init() {
@@ -86,4 +93,25 @@ void uv_winapi_init() {
 
   pCreateSymbolicLinkW = (sCreateSymbolicLinkW)
     GetProcAddress(kernel32_module, "CreateSymbolicLinkW");
+
+  pInitializeSRWLock = (sInitializeSRWLock)
+    GetProcAddress(kernel32_module, "InitializeSRWLock");
+
+  pAcquireSRWLockShared = (sAcquireSRWLockShared)
+    GetProcAddress(kernel32_module, "AcquireSRWLockShared");
+
+  pAcquireSRWLockExclusive = (sAcquireSRWLockExclusive)
+    GetProcAddress(kernel32_module, "AcquireSRWLockExclusive");
+
+  pTryAcquireSRWLockShared = (sTryAcquireSRWLockShared)
+    GetProcAddress(kernel32_module, "TryAcquireSRWLockShared");
+
+  pTryAcquireSRWLockExclusive = (sTryAcquireSRWLockExclusive)
+    GetProcAddress(kernel32_module, "TryAcquireSRWLockExclusive");
+
+  pReleaseSRWLockShared = (sReleaseSRWLockShared)
+    GetProcAddress(kernel32_module, "ReleaseSRWLockShared");
+
+  pReleaseSRWLockExclusive = (sReleaseSRWLockExclusive)
+    GetProcAddress(kernel32_module, "ReleaseSRWLockExclusive");
 }
index e0038f1..8144939 100644 (file)
@@ -4350,6 +4350,26 @@ typedef BOOLEAN (WINAPI* sCreateSymbolicLinkW)
                  LPCWSTR lpTargetFileName,
                  DWORD dwFlags);
 
+typedef VOID (WINAPI* sInitializeSRWLock)
+             (PSRWLOCK SRWLock);
+
+typedef VOID (WINAPI* sAcquireSRWLockShared)
+             (PSRWLOCK SRWLock);
+
+typedef VOID (WINAPI* sAcquireSRWLockExclusive)
+             (PSRWLOCK SRWLock);
+
+typedef BOOL (WINAPI* sTryAcquireSRWLockShared)
+             (PSRWLOCK SRWLock);
+
+typedef BOOL (WINAPI* sTryAcquireSRWLockExclusive)
+             (PSRWLOCK SRWLock);
+
+typedef VOID (WINAPI* sReleaseSRWLockShared)
+             (PSRWLOCK SRWLock);
+
+typedef VOID (WINAPI* sReleaseSRWLockExclusive)
+             (PSRWLOCK SRWLock);
 
 /* Ntapi function pointers */
 extern sRtlNtStatusToDosError pRtlNtStatusToDosError;
@@ -4362,5 +4382,12 @@ extern sNtSetInformationFile pNtSetInformationFile;
 extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
 extern sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;
 extern sCreateSymbolicLinkW pCreateSymbolicLinkW;
+extern sInitializeSRWLock pInitializeSRWLock;
+extern sAcquireSRWLockShared pAcquireSRWLockShared;
+extern sAcquireSRWLockExclusive pAcquireSRWLockExclusive;
+extern sTryAcquireSRWLockShared pTryAcquireSRWLockShared;
+extern sTryAcquireSRWLockExclusive pTryAcquireSRWLockExclusive;
+extern sReleaseSRWLockShared pReleaseSRWLockShared;
+extern sReleaseSRWLockExclusive pReleaseSRWLockExclusive;
 
 #endif /* UV_WIN_WINAPI_H_ */
index c1f23fe..59bdebc 100644 (file)
@@ -267,4 +267,44 @@ TEST_IMPL(fs_event_no_callback_on_close) {
   r = uv_fs_rmdir(loop, &fs_req, "watch_dir", NULL);
 
   return 0;
-}
\ No newline at end of file
+}
+
+
+static void fs_event_fail(uv_fs_event_t* handle, const char* filename,
+  int events, int status) {
+  ASSERT(0 && "should never be called");
+}
+
+
+static void timer_cb(uv_timer_t* handle, int status) {
+  int r;
+
+  ASSERT(status == 0);
+
+  r = uv_fs_event_init(handle->loop, &fs_event, ".", fs_event_fail, 0);
+  ASSERT(r != -1);
+
+  uv_close((uv_handle_t*)&fs_event, close_cb);
+  uv_close((uv_handle_t*)handle, close_cb);
+}
+
+
+TEST_IMPL(fs_event_immediate_close) {
+  uv_timer_t timer;
+  uv_loop_t* loop;
+  int r;
+
+  loop = uv_default_loop();
+
+  r = uv_timer_init(loop, &timer);
+  ASSERT(r == 0);
+
+  r = uv_timer_start(&timer, timer_cb, 1, 0);
+  ASSERT(r == 0);
+
+  uv_run(loop);
+
+  ASSERT(close_cb_called == 2);
+
+  return 0;
+}
index 9051fdb..7240157 100644 (file)
@@ -110,10 +110,13 @@ TEST_DECLARE   (fs_event_watch_dir)
 TEST_DECLARE   (fs_event_watch_file)
 TEST_DECLARE   (fs_event_watch_file_current_dir)
 TEST_DECLARE   (fs_event_no_callback_on_close)
+TEST_DECLARE   (fs_event_immediate_close)
 TEST_DECLARE   (fs_readdir_empty_dir)
 TEST_DECLARE   (fs_readdir_file)
 TEST_DECLARE   (fs_open_dir)
 TEST_DECLARE   (threadpool_queue_work_simple)
+TEST_DECLARE   (thread_mutex)
+TEST_DECLARE   (thread_rwlock)
 #ifdef _WIN32
 TEST_DECLARE   (spawn_detect_pipe_name_collisions_on_windows)
 TEST_DECLARE   (argument_escaping)
@@ -261,10 +264,13 @@ TASK_LIST_START
   TEST_ENTRY  (fs_event_watch_file)
   TEST_ENTRY  (fs_event_watch_file_current_dir)
   TEST_ENTRY  (fs_event_no_callback_on_close)
+  TEST_ENTRY  (fs_event_immediate_close)
   TEST_ENTRY  (fs_readdir_empty_dir)
   TEST_ENTRY  (fs_readdir_file)
   TEST_ENTRY  (fs_open_dir)
   TEST_ENTRY  (threadpool_queue_work_simple)
+  TEST_ENTRY  (thread_mutex)
+  TEST_ENTRY  (thread_rwlock)
 
 #if 0
   /* These are for testing the test runner. */
diff --git a/deps/uv/test/test-mutexes.c b/deps/uv/test/test-mutexes.c
new file mode 100644 (file)
index 0000000..896f46b
--- /dev/null
@@ -0,0 +1,63 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+
+
+/* The mutex and rwlock tests are really poor.
+ * They're very basic sanity checks and nothing more.
+ * Apologies if that rhymes.
+ */
+
+TEST_IMPL(thread_mutex) {
+  uv_mutex_t mutex;
+  int r;
+
+  r = uv_mutex_init(&mutex);
+  ASSERT(r == 0);
+
+  uv_mutex_lock(&mutex);
+  uv_mutex_unlock(&mutex);
+  uv_mutex_destroy(&mutex);
+
+  return 0;
+}
+
+
+TEST_IMPL(thread_rwlock) {
+  uv_rwlock_t rwlock;
+  int r;
+
+  r = uv_rwlock_init(&rwlock);
+  ASSERT(r == 0);
+
+  uv_rwlock_rdlock(&rwlock);
+  uv_rwlock_rdunlock(&rwlock);
+  uv_rwlock_wrlock(&rwlock);
+  uv_rwlock_wrunlock(&rwlock);
+  uv_rwlock_destroy(&rwlock);
+
+  return 0;
+}
index 83129b5..ae65232 100644 (file)
             'src/win/internal.h',
             'src/win/loop-watcher.c',
             'src/win/pipe.c',
+            'src/win/thread.c',
             'src/win/process.c',
             'src/win/req.c',
             'src/win/stream.c',
             'src/win/tcp.c',
             'src/win/tty.c',
             'src/win/threadpool.c',
-            'src/win/threads.c',
             'src/win/timer.c',
             'src/win/udp.c',
             'src/win/util.c',
             'src/unix/cares.c',
             'src/unix/dl.c',
             'src/unix/error.c',
+            'src/unix/thread.c',
             'src/unix/process.c',
             'src/unix/internal.h',
             'src/unix/eio/ecb.h',
         'test/test-tcp-write-to-half-open-connection.c',
         'test/test-tcp-writealot.c',
         'test/test-threadpool.c',
+        'test/test-mutexes.c',
         'test/test-timer-again.c',
         'test/test-timer.c',
         'test/test-tty.c',