uv: upgrade to 85f6b79
authorBen Noordhuis <info@bnoordhuis.nl>
Wed, 28 Dec 2011 23:18:23 +0000 (00:18 +0100)
committerBen Noordhuis <info@bnoordhuis.nl>
Wed, 28 Dec 2011 23:18:23 +0000 (00:18 +0100)
deps/uv/include/uv-private/uv-unix.h
deps/uv/include/uv.h
deps/uv/src/unix/uv-eio.c
deps/uv/test/test-list.h
deps/uv/test/test-thread.c

index 9953734..24ef37c 100644 (file)
@@ -63,6 +63,8 @@ typedef void* uv_lib_t;
    * definition of ares_timeout(). \
    */ \
   ev_timer timer; \
+  /* Poll result queue */ \
+  eio_channel uv_eio_channel; \
   struct ev_loop* ev;
 
 #define UV_REQ_BUFSML_SIZE (4)
index 9ff318f..7e089ef 100644 (file)
@@ -1400,8 +1400,6 @@ struct uv_loop_s {
   uv_async_t uv_eio_want_poll_notifier;
   uv_async_t uv_eio_done_poll_notifier;
   uv_idle_t uv_eio_poller;
-  /* Poll result queue */
-  eio_channel uv_eio_channel;
   /* Diagnostic counters */
   uv_counters_t counters;
   /* The last error */
index 7c83f2c..8656ea6 100644 (file)
@@ -96,6 +96,18 @@ static void uv_eio_done_poll(eio_channel *channel) {
 }
 
 
+static void uv__eio_init(void) {
+  eio_init(uv_eio_want_poll, uv_eio_done_poll);
+  /*
+   * Don't handle more than 10 reqs on each eio_poll(). This is to avoid
+   * race conditions. See Node's test/simple/test-eio-race.js
+   */
+  eio_set_max_poll_reqs(10);
+}
+
+static uv_once_t uv__eio_init_once_guard = UV_ONCE_INIT;
+
+
 void uv_eio_init(uv_loop_t* loop) {
   if (loop->counters.eio_init == 0) {
     loop->counters.eio_init++;
@@ -112,11 +124,6 @@ void uv_eio_init(uv_loop_t* loop) {
         uv_eio_done_poll_notifier_cb);
     uv_unref(loop);
 
-    eio_init(uv_eio_want_poll, uv_eio_done_poll);
-    /*
-     * Don't handle more than 10 reqs on each eio_poll(). This is to avoid
-     * race conditions. See Node's test/simple/test-eio-race.js
-     */
-    eio_set_max_poll_reqs(10);
+    uv_once(&uv__eio_init_once_guard, uv__eio_init);
   }
 }
index 51b8472..f5f0541 100644 (file)
@@ -119,6 +119,7 @@ TEST_DECLARE   (fs_readdir_empty_dir)
 TEST_DECLARE   (fs_readdir_file)
 TEST_DECLARE   (fs_open_dir)
 TEST_DECLARE   (threadpool_queue_work_simple)
+TEST_DECLARE   (threadpool_multiple_event_loops)
 TEST_DECLARE   (thread_mutex)
 TEST_DECLARE   (thread_rwlock)
 TEST_DECLARE   (thread_create)
@@ -285,6 +286,7 @@ TASK_LIST_START
   TEST_ENTRY  (fs_readdir_file)
   TEST_ENTRY  (fs_open_dir)
   TEST_ENTRY  (threadpool_queue_work_simple)
+  TEST_ENTRY  (threadpool_multiple_event_loops)
   TEST_ENTRY  (thread_mutex)
   TEST_ENTRY  (thread_rwlock)
   TEST_ENTRY  (thread_create)
index 48b31b1..5c0bb75 100644 (file)
 #include "task.h"
 
 #include <stdio.h>
+#include <stddef.h>
 #include <stdlib.h>
 
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+#define container_of(ptr, type, member) \
+  ((type *) ((char *) (ptr) - offsetof(type, member)))
+
+struct getaddrinfo_req {
+  uv_thread_t thread_id;
+  unsigned int counter;
+  uv_loop_t* loop;
+  uv_getaddrinfo_t handle;
+};
+
+
+struct fs_req {
+  uv_thread_t thread_id;
+  unsigned int counter;
+  uv_loop_t* loop;
+  uv_fs_t handle;
+};
+
+static void getaddrinfo_do(struct getaddrinfo_req* req);
+static void getaddrinfo_cb(uv_getaddrinfo_t* handle,
+                           int status,
+                           struct addrinfo* res);
+static void fs_do(struct fs_req* req);
+static void fs_cb(uv_fs_t* handle);
 
 static volatile int thread_called;
 
 
+static void getaddrinfo_do(struct getaddrinfo_req* req) {
+  int r;
+
+  ASSERT(req->thread_id == uv_thread_self());
+
+  r = uv_getaddrinfo(req->loop,
+                     &req->handle,
+                     getaddrinfo_cb,
+                     "localhost",
+                     NULL,
+                     NULL);
+  ASSERT(r == 0);
+}
+
+
+static void getaddrinfo_cb(uv_getaddrinfo_t* handle,
+                           int status,
+                           struct addrinfo* res) {
+  struct getaddrinfo_req* req;
+
+  ASSERT(status == 0);
+
+  req = container_of(handle, struct getaddrinfo_req, handle);
+  uv_freeaddrinfo(res);
+
+  if (--req->counter)
+    getaddrinfo_do(req);
+}
+
+
+static void fs_do(struct fs_req* req) {
+  int r;
+
+  ASSERT(req->thread_id == uv_thread_self());
+
+  r = uv_fs_stat(req->loop, &req->handle, ".", fs_cb);
+  ASSERT(r == 0);
+}
+
+
+static void fs_cb(uv_fs_t* handle) {
+  struct fs_req* req = container_of(handle, struct fs_req, handle);
+
+  if (--req->counter)
+    fs_do(req);
+}
+
+
+static void do_work(void* arg) {
+  struct getaddrinfo_req getaddrinfo_reqs[16];
+  struct fs_req fs_reqs[16];
+  uv_thread_t self;
+  uv_loop_t* loop;
+  size_t i;
+  int r;
+
+  self = uv_thread_self();
+
+  loop = uv_loop_new();
+  ASSERT(loop != NULL);
+
+  for (i = 0; i < ARRAY_SIZE(getaddrinfo_reqs); i++) {
+    struct getaddrinfo_req* req = getaddrinfo_reqs + i;
+    req->thread_id = self;
+    req->counter = 16;
+    req->loop = loop;
+    getaddrinfo_do(req);
+  }
+
+  for (i = 0; i < ARRAY_SIZE(fs_reqs); i++) {
+    struct fs_req* req = fs_reqs + i;
+    req->thread_id = self;
+    req->counter = 16;
+    req->loop = loop;
+    fs_do(req);
+  }
+
+  r = uv_run(loop);
+  ASSERT(r == 0);
+
+  uv_loop_delete(loop);
+}
+
+
 static void thread_entry(void* arg) {
   ASSERT(arg == (void *) 42);
   thread_called++;
@@ -56,3 +167,25 @@ TEST_IMPL(thread_self) {
   tid = uv_thread_self();
   return 0;
 }
+
+
+/* Hilariously bad test name. Run a lot of tasks in the thread pool and verify
+ * that each "finished" callback is run in its originating thread.
+ */
+TEST_IMPL(threadpool_multiple_event_loops) {
+  uv_thread_t threads[8];
+  size_t i;
+  int r;
+
+  for (i = 0; i < ARRAY_SIZE(threads); i++) {
+    r = uv_thread_create(threads + i, do_work, NULL);
+    ASSERT(r == 0);
+  }
+
+  for (i = 0; i < ARRAY_SIZE(threads); i++) {
+    r = uv_thread_join(threads + i);
+    ASSERT(r == 0);
+  }
+
+  return 0;
+}