You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2020/08/17 14:09:56 UTC

[incubator-nuttx-apps] branch master updated: system: add libuv port for NuttX

This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new 18158ed  system: add libuv port for NuttX
18158ed is described below

commit 18158ed271ceaa0a379707d7d3e94fc8077a59ac
Author: spiriou <si...@korys.io>
AuthorDate: Fri Aug 7 19:49:12 2020 +0200

    system: add libuv port for NuttX
---
 system/libuv/.gitignore                            |    1 +
 .../libuv/0001-initial-libuv-port-to-nuttx.patch   | 7308 ++++++++++++++++++++
 system/libuv/Make.defs                             |   32 +
 system/libuv/Makefile                              |   23 +
 system/libuv/libuv/Kconfig                         |  123 +
 system/libuv/libuv/Make.defs                       |   31 +
 system/libuv/libuv/Makefile                        |  121 +
 system/libuv/tests/Kconfig                         |   35 +
 system/libuv/tests/Make.defs                       |   23 +
 system/libuv/tests/Makefile                        |   70 +
 system/libuv/tests/runner-nuttx.c                  |  152 +
 system/libuv/tests/runner-nuttx.h                  |   46 +
 system/libuv/tests/test_main.c                     |   56 +
 13 files changed, 8021 insertions(+)

diff --git a/system/libuv/.gitignore b/system/libuv/.gitignore
new file mode 100644
index 0000000..9e1d259
--- /dev/null
+++ b/system/libuv/.gitignore
@@ -0,0 +1 @@
+/Kconfig
diff --git a/system/libuv/0001-initial-libuv-port-to-nuttx.patch b/system/libuv/0001-initial-libuv-port-to-nuttx.patch
new file mode 100644
index 0000000..d7d4e1b
--- /dev/null
+++ b/system/libuv/0001-initial-libuv-port-to-nuttx.patch
@@ -0,0 +1,7308 @@
+From e589c4790e8367c5d3c0c37ba20338539ee6f76e Mon Sep 17 00:00:00 2001
+From: Simon Piriou <sp...@gmail.com>
+Date: Fri, 7 Aug 2020 19:48:02 +0200
+Subject: [PATCH] initial libuv port to nuttx
+
+---
+ include/uv.h                        |  108 ++-
+ include/uv/nuttx.h                  |   67 ++
+ include/uv/unix.h                   |  146 +++-
+ src/inet.c                          |   50 +-
+ src/queue.h                         |    4 +-
+ src/random.c                        |    4 +
+ src/unix/async.c                    |   71 +-
+ src/unix/core.c                     |  178 ++++-
+ src/unix/fs.c                       |   62 +-
+ src/unix/internal.h                 |   30 +-
+ src/unix/loop.c                     |   98 ++-
+ src/unix/no-proctitle.c             |   28 +
+ src/unix/nuttx.c                    |  238 ++++++
+ src/unix/nuttx_stream.c             | 1077 +++++++++++++++++++++++++++
+ src/unix/nuttx_tcp.c                |  311 ++++++++
+ src/unix/nuttx_threadpool.c         |  361 +++++++++
+ src/unix/nuttx_timer.c              |  199 +++++
+ src/unix/poll.c                     |   26 +
+ src/unix/process.c                  |   35 +-
+ src/unix/random-devurandom.c        |   19 +-
+ src/unix/thread.c                   |   35 +-
+ src/uv-common.c                     |  175 ++++-
+ src/uv-common.h                     |   31 +
+ test/echo-server.c                  |   62 +-
+ test/runner.c                       |   63 +-
+ test/runner.h                       |   28 +-
+ test/task.h                         |   58 +-
+ test/test-active.c                  |   12 +-
+ test/test-async.c                   |   36 +-
+ test/test-fs-copyfile.c             |   27 +-
+ test/test-fs-poll.c                 |  162 ++--
+ test/test-idle.c                    |   20 +-
+ test/test-ip4-addr.c                |    2 +-
+ test/test-list.h                    |   75 +-
+ test/test-loop-close.c              |   13 +-
+ test/test-loop-stop.c               |   24 +-
+ test/test-loop-time.c               |   44 +-
+ test/test-poll-close.c              |   15 +-
+ test/test-random.c                  |   23 +-
+ test/test-tcp-read-stop.c           |   13 +-
+ test/test-tcp-write-after-connect.c |   17 +-
+ test/test-threadpool.c              |   28 +-
+ test/test-timer-again.c             |   28 +-
+ test/test-timer-from-check.c        |   21 +-
+ test/test-timer.c                   |  160 ++--
+ test/test-walk-handles.c            |    8 +-
+ 46 files changed, 3929 insertions(+), 363 deletions(-)
+ create mode 100644 include/uv/nuttx.h
+ create mode 100644 src/unix/nuttx.c
+ create mode 100644 src/unix/nuttx_stream.c
+ create mode 100644 src/unix/nuttx_tcp.c
+ create mode 100644 src/unix/nuttx_threadpool.c
+ create mode 100644 src/unix/nuttx_timer.c
+
+diff --git a/include/uv.h b/include/uv.h
+index fec663136..e4b989afb 100644
+--- a/include/uv.h
++++ b/include/uv.h
+@@ -1,3 +1,23 @@
++/****************************************************************************
++ * include/uv.h
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+@@ -23,6 +43,12 @@
+ 
+ #ifndef UV_H
+ #define UV_H
++
++/* FIXME hack to enable NuttX build target */
++#ifndef __NUTTX__
++#define __NUTTX__ 1
++#endif
++
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+@@ -265,22 +291,46 @@ typedef void* (*uv_realloc_func)(void* ptr, size_t size);
+ typedef void* (*uv_calloc_func)(size_t count, size_t size);
+ typedef void (*uv_free_func)(void* ptr);
+ 
+-UV_EXTERN void uv_library_shutdown(void);
++#ifdef CONFIG_LIBUV_CONTEXT
++struct uv_context_s;
++typedef struct uv_context_s uv_context_t;
+ 
+-UV_EXTERN int uv_replace_allocator(uv_malloc_func malloc_func,
+-                                   uv_realloc_func realloc_func,
+-                                   uv_calloc_func calloc_func,
+-                                   uv_free_func free_func);
++UV_EXTERN void uv_library_init(uv_context_t* ctx);
++UV_EXTERN void uv_library_shutdown(uv_context_t* ctx);
++
++UV_EXTERN uv_loop_t* uv_default_loop(uv_context_t *ctx);
++UV_EXTERN int uv_loop_init(uv_loop_t* loop, uv_context_t* ctx);
++
++/*
++ * NOTE:
++ *  This function is DEPRECATED (to be removed after 0.12), users should
++ *  allocate the loop manually and use uv_loop_init instead.
++ */
++UV_EXTERN uv_loop_t* uv_loop_new(uv_context_t *ctx);
++
++#else /* CONFIG_LIBUV_CONTEXT */
++
++UV_EXTERN void uv_library_shutdown(void);
+ 
+ UV_EXTERN uv_loop_t* uv_default_loop(void);
+ UV_EXTERN int uv_loop_init(uv_loop_t* loop);
+-UV_EXTERN int uv_loop_close(uv_loop_t* loop);
++
+ /*
+  * NOTE:
+  *  This function is DEPRECATED (to be removed after 0.12), users should
+  *  allocate the loop manually and use uv_loop_init instead.
+  */
+ UV_EXTERN uv_loop_t* uv_loop_new(void);
++
++#endif
++
++UV_EXTERN int uv_replace_allocator(uv_malloc_func malloc_func,
++                                   uv_realloc_func realloc_func,
++                                   uv_calloc_func calloc_func,
++                                   uv_free_func free_func);
++
++UV_EXTERN int uv_loop_close(uv_loop_t* loop);
++
+ /*
+  * NOTE:
+  *  This function is DEPRECATED (to be removed after 0.12). Users should use
+@@ -300,7 +350,7 @@ UV_EXTERN void uv_unref(uv_handle_t*);
+ UV_EXTERN int uv_has_ref(const uv_handle_t*);
+ 
+ UV_EXTERN void uv_update_time(uv_loop_t*);
+-UV_EXTERN uint64_t uv_now(const uv_loop_t*);
++UV_EXTERN uv_time_t uv_now(const uv_loop_t*);
+ 
+ UV_EXTERN int uv_backend_fd(const uv_loop_t*);
+ UV_EXTERN int uv_backend_timeout(const uv_loop_t*);
+@@ -423,7 +473,7 @@ struct uv_shutdown_s {
+   UV_SHUTDOWN_PRIVATE_FIELDS
+ };
+ 
+-
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+ #define UV_HANDLE_FIELDS                                                      \
+   /* public */                                                                \
+   void* data;                                                                 \
+@@ -439,6 +489,20 @@ struct uv_shutdown_s {
+   } u;                                                                        \
+   UV_HANDLE_PRIVATE_FIELDS                                                    \
+ 
++#else
++#define UV_HANDLE_FIELDS                                                      \
++  /* public */                                                                \
++  void* data;                                                                 \
++  /* read-only */                                                             \
++  uv_loop_t* loop;                                                            \
++  uv_handle_type type;                                                        \
++  /* private */                                                               \
++  uv_close_cb close_cb;                                                       \
++  void* handle_queue[2];                                                      \
++  UV_HANDLE_PRIVATE_FIELDS                                                    \
++
++#endif
++
+ /* The abstract base class of all handles. */
+ struct uv_handle_s {
+   UV_HANDLE_FIELDS
+@@ -857,12 +921,12 @@ struct uv_timer_s {
+ UV_EXTERN int uv_timer_init(uv_loop_t*, uv_timer_t* handle);
+ UV_EXTERN int uv_timer_start(uv_timer_t* handle,
+                              uv_timer_cb cb,
+-                             uint64_t timeout,
+-                             uint64_t repeat);
++                             uv_interval_t timeout,
++                             uv_interval_t repeat);
+ UV_EXTERN int uv_timer_stop(uv_timer_t* handle);
+ UV_EXTERN int uv_timer_again(uv_timer_t* handle);
+-UV_EXTERN void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat);
+-UV_EXTERN uint64_t uv_timer_get_repeat(const uv_timer_t* handle);
++UV_EXTERN void uv_timer_set_repeat(uv_timer_t* handle, uv_interval_t repeat);
++UV_EXTERN uv_interval_t uv_timer_get_repeat(const uv_timer_t* handle);
+ 
+ 
+ /*
+@@ -1770,6 +1834,10 @@ union uv_any_req {
+ struct uv_loop_s {
+   /* User data - use this for whatever. */
+   void* data;
++#ifdef CONFIG_LIBUV_CONTEXT
++  uv_context_t *context;
++#endif
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+   /* Loop reference counting. */
+   unsigned int active_handles;
+   void* handle_queue[2];
+@@ -1779,12 +1847,28 @@ struct uv_loop_s {
+   } active_reqs;
+   /* Internal flag to signal loop stop. */
+   unsigned int stop_flag;
++#else
++  void* handle_queue[2];
++  union {
++    uint8_t count;
++  } active_reqs;
++  /* Loop reference counting. */
++  uint8_t active_handles;
++  /* Internal flag to signal loop stop. */
++  uint8_t stop_flag;
++#endif
+   UV_LOOP_PRIVATE_FIELDS
+ };
+ 
+ UV_EXTERN void* uv_loop_get_data(const uv_loop_t*);
+ UV_EXTERN void uv_loop_set_data(uv_loop_t*, void* data);
+ 
++#ifdef CONFIG_LIBUV_CONTEXT
++struct uv_context_s {
++  UV_PLATFORM_CONTEXT_FIELDS
++};
++#endif
++
+ /* Don't export the private CPP symbols. */
+ #undef UV_HANDLE_TYPE_PRIVATE
+ #undef UV_REQ_TYPE_PRIVATE
+diff --git a/include/uv/nuttx.h b/include/uv/nuttx.h
+new file mode 100644
+index 000000000..62574f93b
+--- /dev/null
++++ b/include/uv/nuttx.h
+@@ -0,0 +1,67 @@
++/****************************************************************************
++ * libs/libuv/include/uv/nuttx.h
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
++#ifndef UV_NUTTX_H
++#define UV_NUTTX_H
++
++#include <nuttx/config.h>
++#include <poll.h>
++
++#ifdef CONFIG_LIBUV_WQ
++typedef struct uv_wq_context_s {
++#ifndef CONFIG_LIBUV_CONTEXT
++  pthread_once_t once;
++#endif
++  pthread_cond_t cond;
++  pthread_mutex_t mutex;
++  unsigned int idle_threads;
++  pthread_t default_threads[CONFIG_LIBUV_WQ_THREADS_COUNT];
++  void *exit_message[2];
++  void *wq[2];
++} uv_wq_context_t;
++#endif
++
++#ifdef CONFIG_LIBUV_TIMER_NUTTX
++typedef uint32_t uv_time_t;
++typedef int32_t  uv_interval_t;
++#else
++typedef uint64_t uv_time_t;
++typedef uint64_t uv_interval_t;
++#endif
++
++#define UV_PLATFORM_LOOP_FIELDS                                               \
++  struct    pollfd poll_fds[CONFIG_LIBUV_NPOLLWAITERS];                       \
++  size_t    poll_fds_used;
++
++#ifdef CONFIG_LIBUV_CONTEXT
++#ifdef CONFIG_LIBUV_WQ
++#define UV_PLATFORM_CONTEXT_PRIVATE_WQ_FIELDS                                 \
++  uv_wq_context_t wq;
++#else
++#define UV_PLATFORM_CONTEXT_PRIVATE_WQ_FIELDS
++#endif /* CONFIG_LIBUV_WQ */
++
++#define UV_PLATFORM_CONTEXT_FIELDS                                            \
++  UV_PLATFORM_CONTEXT_PRIVATE_WQ_FIELDS                                       \
++  uv_loop_t default_loop;                                                     \
++  uv_loop_t *default_loop_ptr;
++#endif /* CONFIG_LIBUV_CONTEXT */
++
++#endif /* UV_NUTTX_H */
+diff --git a/include/uv/unix.h b/include/uv/unix.h
+index 3a131638f..294708654 100644
+--- a/include/uv/unix.h
++++ b/include/uv/unix.h
+@@ -1,3 +1,23 @@
++/****************************************************************************
++ * include/uv/unix.h
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+@@ -45,7 +65,9 @@
+ 
+ #include "uv/threadpool.h"
+ 
+-#if defined(__linux__)
++#if defined(__NUTTX__)
++# include "uv/nuttx.h"
++#elif defined(__linux__)
+ # include "uv/linux.h"
+ #elif defined (__MVS__)
+ # include "uv/os390.h"
+@@ -93,7 +115,9 @@ typedef struct uv__io_s uv__io_t;
+ 
+ struct uv__io_s {
+   uv__io_cb cb;
++#if 0
+   void* pending_queue[2];
++#endif
+   void* watcher_queue[2];
+   unsigned int pevents; /* Pending event mask i.e. mask at next tick. */
+   unsigned int events;  /* Current event mask. */
+@@ -218,37 +242,103 @@ typedef struct {
+   char* errmsg;
+ } uv_lib_t;
+ 
+-#define UV_LOOP_PRIVATE_FIELDS                                                \
+-  unsigned long flags;                                                        \
+-  int backend_fd;                                                             \
+-  void* pending_queue[2];                                                     \
+-  void* watcher_queue[2];                                                     \
+-  uv__io_t** watchers;                                                        \
+-  unsigned int nwatchers;                                                     \
+-  unsigned int nfds;                                                          \
+-  void* wq[2];                                                                \
+-  uv_mutex_t wq_mutex;                                                        \
+-  uv_async_t wq_async;                                                        \
+-  uv_rwlock_t cloexec_lock;                                                   \
+-  uv_handle_t* closing_handles;                                               \
++#ifdef CONFIG_LIBUV_SIGNAL
++#define UV_LOOP_PRIVATE_SIGNAL_FIELDS                                         \
++  int signal_pipefd[2];                                                       \
++  uv__io_t signal_io_watcher;
++#else
++#define UV_LOOP_PRIVATE_SIGNAL_FIELDS
++#endif
++
++#ifdef CONFIG_LIBUV_PROCESS
++#define UV_LOOP_PRIVATE_PROCESS_FIELDS                                        \
+   void* process_handles[2];                                                   \
+-  void* prepare_handles[2];                                                   \
+-  void* check_handles[2];                                                     \
+-  void* idle_handles[2];                                                      \
++  uv_signal_t child_watcher;
++#else
++#define UV_LOOP_PRIVATE_PROCESS_FIELDS
++#endif
++
++#ifdef CONFIG_LIBUV_ASYNC
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
++#define UV_LOOP_PRIVATE_ASYNC_FIELDS                                          \
+   void* async_handles[2];                                                     \
+   void (*async_unused)(void);  /* TODO(bnoordhuis) Remove in libuv v2. */     \
+   uv__io_t async_io_watcher;                                                  \
+-  int async_wfd;                                                              \
++  int async_wfd;
++#else
++#define UV_LOOP_PRIVATE_ASYNC_FIELDS                                          \
++  void* async_handles[2];                                                     \
++  uv__io_t async_io_watcher;
++#endif /* CONFIG_LIBUV_LOW_FOOTPRINT */
++#else
++#define UV_LOOP_PRIVATE_ASYNC_FIELDS
++#endif
++
++#ifdef CONFIG_LIBUV_TIMER
++#ifdef CONFIG_LIBUV_TIMER_NUTTX
++#define UV_LOOP_PRIVATE_TIMER_FIELDS                                          \
++  uv_timer_t *timer_head;
++#else
++#define UV_LOOP_PRIVATE_TIMER_FIELDS                                          \
+   struct {                                                                    \
+     void* min;                                                                \
+     unsigned int nelts;                                                       \
+   } timer_heap;                                                               \
+-  uint64_t timer_counter;                                                     \
+-  uint64_t time;                                                              \
+-  int signal_pipefd[2];                                                       \
+-  uv__io_t signal_io_watcher;                                                 \
+-  uv_signal_t child_watcher;                                                  \
++  uint64_t timer_counter;
++#endif
++#else
++#define UV_LOOP_PRIVATE_TIMER_FIELDS
++#endif
++
++#ifdef CONFIG_LIBUV_WQ
++#define UV_LOOP_PRIVATE_WQ_FIELDS                                             \
++  void* wq[2];                                                                \
++  uv_mutex_t wq_mutex;                                                        \
++  uv_async_t wq_async;
++#else
++#define UV_LOOP_PRIVATE_WQ_FIELDS
++#endif
++
++#ifdef CONFIG_LIBUV_LOOP_WATCHERS
++#define UV_LOOP_PRIVATE_WATCHERS_FIELDS                                       \
++  void* prepare_handles[2];                                                   \
++  void* check_handles[2];                                                     \
++  void* idle_handles[2];
++#else
++#define UV_LOOP_PRIVATE_WATCHERS_FIELDS
++#endif
++
++#ifdef CONFIG_LIBUV_LOW_FOOTPRINT
++#define UV_LOOP_PRIVATE_PERFS_FIELDS
++#else
++#define UV_LOOP_PRIVATE_PERFS_FIELDS                                          \
++  unsigned long flags;                                                        \
++  int backend_fd;                                                             \
++  uv_rwlock_t cloexec_lock;                                                   \
+   int emfile_fd;                                                              \
++  uv__io_t** watchers;                                                        \
++  unsigned int nwatchers;                                                     \
++  unsigned int nfds;
++#endif
++
++#if 0
++#define UV_LOOP_PRIVATE_TODO_FIELDS                                           \
++  void* pending_queue[2];
++#else
++#define UV_LOOP_PRIVATE_TODO_FIELDS
++#endif
++
++#define UV_LOOP_PRIVATE_FIELDS                                                \
++  void* watcher_queue[2];                                                     \
++  UV_LOOP_PRIVATE_WQ_FIELDS                                                   \
++  uv_handle_t* closing_handles;                                               \
++  UV_LOOP_PRIVATE_WATCHERS_FIELDS                                             \
++  UV_LOOP_PRIVATE_ASYNC_FIELDS                                                \
++  UV_LOOP_PRIVATE_TIMER_FIELDS                                                \
++  uv_time_t time;                                                              \
++  UV_LOOP_PRIVATE_SIGNAL_FIELDS                                               \
++  UV_LOOP_PRIVATE_PROCESS_FIELDS                                              \
++  UV_LOOP_PRIVATE_PERFS_FIELDS                                                \
+   UV_PLATFORM_LOOP_FIELDS                                                     \
+ 
+ #define UV_REQ_TYPE_PRIVATE /* empty */
+@@ -290,7 +380,7 @@ typedef struct {
+   void* write_queue[2];                                                       \
+   void* write_completed_queue[2];                                             \
+   uv_connection_cb connection_cb;                                             \
+-  int delayed_error;                                                          \
++  /*int delayed_error;*/                                                      \
+   int accepted_fd;                                                            \
+   void* queued_fds;                                                           \
+   UV_STREAM_PRIVATE_PLATFORM_FIELDS                                           \
+@@ -327,12 +417,20 @@ typedef struct {
+   void* queue[2];                                                             \
+   int pending;                                                                \
+ 
++#ifdef CONFIG_LIBUV_TIMER_NUTTX
++#define UV_TIMER_PRIVATE_FIELDS                                               \
++  uv_timer_cb timer_cb;                                                       \
++  struct uv_timer_s *next;                                                    \
++  int32_t timeout;                                                            \
++  int32_t repeat;
++#else
+ #define UV_TIMER_PRIVATE_FIELDS                                               \
+   uv_timer_cb timer_cb;                                                       \
+   void* heap_node[3];                                                         \
+   uint64_t timeout;                                                           \
+   uint64_t repeat;                                                            \
+   uint64_t start_id;
++#endif
+ 
+ #define UV_GETADDRINFO_PRIVATE_FIELDS                                         \
+   struct uv__work work_req;                                                   \
+diff --git a/src/inet.c b/src/inet.c
+index 698ab232e..63aa2b81b 100644
+--- a/src/inet.c
++++ b/src/inet.c
+@@ -1,3 +1,23 @@
++/****************************************************************************
++ * src/inet.c
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
+ /*
+  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+  * Copyright (c) 1996-1999 by Internet Software Consortium.
+@@ -30,26 +50,33 @@
+ #define UV__INET_ADDRSTRLEN         16
+ #define UV__INET6_ADDRSTRLEN        46
+ 
+-
++#ifdef CONFIG_NET_IPv4
+ static int inet_ntop4(const unsigned char *src, char *dst, size_t size);
+-static int inet_ntop6(const unsigned char *src, char *dst, size_t size);
+ static int inet_pton4(const char *src, unsigned char *dst);
+-static int inet_pton6(const char *src, unsigned char *dst);
++#endif
+ 
++#ifdef CONFIG_NET_IPv6
++static int inet_ntop6(const unsigned char *src, char *dst, size_t size);
++static int inet_pton6(const char *src, unsigned char *dst);
++#endif
+ 
+ int uv_inet_ntop(int af, const void* src, char* dst, size_t size) {
+   switch (af) {
++#ifdef CONFIG_NET_IPv4
+   case AF_INET:
+     return (inet_ntop4(src, dst, size));
++#endif
++#ifdef CONFIG_NET_IPv6
+   case AF_INET6:
+     return (inet_ntop6(src, dst, size));
++#endif
+   default:
+     return UV_EAFNOSUPPORT;
+   }
+   /* NOTREACHED */
+ }
+ 
+-
++#ifdef CONFIG_NET_IPv4
+ static int inet_ntop4(const unsigned char *src, char *dst, size_t size) {
+   static const char fmt[] = "%u.%u.%u.%u";
+   char tmp[UV__INET_ADDRSTRLEN];
+@@ -62,8 +89,9 @@ static int inet_ntop4(const unsigned char *src, char *dst, size_t size) {
+   uv__strscpy(dst, tmp, size);
+   return 0;
+ }
++#endif
+ 
+-
++#ifdef CONFIG_NET_IPv6
+ static int inet_ntop6(const unsigned char *src, char *dst, size_t size) {
+   /*
+    * Note that int32_t and int16_t need only be "at least" large enough
+@@ -145,15 +173,18 @@ static int inet_ntop6(const unsigned char *src, char *dst, size_t size) {
+     return UV_ENOSPC;
+   return 0;
+ }
+-
++#endif
+ 
+ int uv_inet_pton(int af, const char* src, void* dst) {
+   if (src == NULL || dst == NULL)
+     return UV_EINVAL;
+ 
+   switch (af) {
++#ifdef CONFIG_NET_IPv4
+   case AF_INET:
+     return (inet_pton4(src, dst));
++#endif
++#ifdef CONFIG_NET_IPv6
+   case AF_INET6: {
+     int len;
+     char tmp[UV__INET6_ADDRSTRLEN], *s, *p;
+@@ -169,13 +200,14 @@ int uv_inet_pton(int af, const char* src, void* dst) {
+     }
+     return inet_pton6(s, dst);
+   }
++#endif
+   default:
+     return UV_EAFNOSUPPORT;
+   }
+   /* NOTREACHED */
+ }
+ 
+-
++#ifdef CONFIG_NET_IPv4
+ static int inet_pton4(const char *src, unsigned char *dst) {
+   static const char digits[] = "0123456789";
+   int saw_digit, octets, ch;
+@@ -213,8 +245,9 @@ static int inet_pton4(const char *src, unsigned char *dst) {
+   memcpy(dst, tmp, sizeof(struct in_addr));
+   return 0;
+ }
++#endif
+ 
+-
++#ifdef CONFIG_NET_IPv6
+ static int inet_pton6(const char *src, unsigned char *dst) {
+   static const char xdigits_l[] = "0123456789abcdef",
+                     xdigits_u[] = "0123456789ABCDEF";
+@@ -300,3 +333,4 @@ static int inet_pton6(const char *src, unsigned char *dst) {
+   memcpy(dst, tmp, sizeof tmp);
+   return 0;
+ }
++#endif
+diff --git a/src/queue.h b/src/queue.h
+index ff3540a0a..1e3e92904 100644
+--- a/src/queue.h
++++ b/src/queue.h
+@@ -74,8 +74,8 @@ typedef void *QUEUE[2];
+     if (QUEUE_EMPTY(h))                                                       \
+       QUEUE_INIT(n);                                                          \
+     else {                                                                    \
+-      QUEUE* q = QUEUE_HEAD(h);                                               \
+-      QUEUE_SPLIT(h, q, n);                                                   \
++      QUEUE* _q = QUEUE_HEAD(h);                                               \
++      QUEUE_SPLIT(h, _q, n);                                                   \
+     }                                                                         \
+   }                                                                           \
+   while (0)
+diff --git a/src/random.c b/src/random.c
+index 491bf7033..6b2280f02 100644
+--- a/src/random.c
++++ b/src/random.c
+@@ -31,6 +31,9 @@
+ static int uv__random(void* buf, size_t buflen) {
+   int rc;
+ 
++#ifdef __NUTTX__
++  rc = uv__random_devurandom(buf, buflen);
++#else /* __NUTTX__ */
+ #if defined(__PASE__)
+   rc = uv__random_readpath("/dev/urandom", buf, buflen);
+ #elif defined(_AIX)
+@@ -65,6 +68,7 @@ static int uv__random(void* buf, size_t buflen) {
+ #else
+   rc = uv__random_devurandom(buf, buflen);
+ #endif
++#endif /* __NUTTX__ */
+ 
+   return rc;
+ }
+diff --git a/src/unix/async.c b/src/unix/async.c
+index 5f58fb88d..00b6a858c 100644
+--- a/src/unix/async.c
++++ b/src/unix/async.c
+@@ -1,3 +1,23 @@
++/****************************************************************************
++ * libuv/src/unix/async.c
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
+ /* 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
+@@ -34,7 +54,7 @@
+ #include <unistd.h>
+ #include <sched.h>  /* sched_yield() */
+ 
+-#ifdef __linux__
++#if defined (__linux__) || defined(__NUTTX__)
+ #include <sys/eventfd.h>
+ #endif
+ 
+@@ -72,14 +92,18 @@ int uv_async_send(uv_async_t* handle) {
+   /* Wake up the other thread's event loop. */
+   uv__async_send(handle->loop);
+ 
++#ifdef __NUTTX__
++  cmpxchgi(&handle->pending, 0, 1);
++#else
+   /* Tell the other thread we're done. */
+   if (cmpxchgi(&handle->pending, 1, 2) != 1)
+     abort();
++#endif
+ 
+   return 0;
+ }
+ 
+-
++#ifndef __NUTTX__
+ /* Only call this from the event loop thread. */
+ static int uv__async_spin(uv_async_t* handle) {
+   int i;
+@@ -110,17 +134,26 @@ static int uv__async_spin(uv_async_t* handle) {
+     sched_yield();
+   }
+ }
+-
++#endif
+ 
+ void uv__async_close(uv_async_t* handle) {
++#ifdef __NUTTX__
++  /* FIXME: potential race condition were as fd will not be valid for next uv_async_send.
++   */
++#else
+   uv__async_spin(handle);
++#endif
+   QUEUE_REMOVE(&handle->queue);
+   uv__handle_stop(handle);
+ }
+ 
+ 
+ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
++#ifdef __NUTTX__
++  char buf[sizeof(eventfd_t)];
++#else
+   char buf[1024];
++#endif
+   ssize_t r;
+   QUEUE queue;
+   QUEUE* q;
+@@ -154,7 +187,11 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
+     QUEUE_REMOVE(q);
+     QUEUE_INSERT_TAIL(&loop->async_handles, q);
+ 
++#ifdef __NUTTX__
++    if (0 == cmpxchgi(&h->pending, 1, 0))
++#else
+     if (0 == uv__async_spin(h))
++#endif
+       continue;  /* Not pending. */
+ 
+     if (h->async_cb == NULL)
+@@ -166,11 +203,23 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
+ 
+ 
+ static void uv__async_send(uv_loop_t* loop) {
++#ifndef __NUTTX__
+   const void* buf;
+   ssize_t len;
+   int fd;
++#endif
+   int r;
+ 
++#ifdef __NUTTX__
++  const eventfd_t val = 1;
++
++  do {
++    r = write(loop->async_io_watcher.fd, &val, sizeof(val));
++  } while (r == -1 && errno == EINTR);
++
++  if (r == sizeof(val))
++    return;
++#else
+   buf = "";
+   len = 1;
+   fd = loop->async_wfd;
+@@ -190,6 +239,7 @@ static void uv__async_send(uv_loop_t* loop) {
+ 
+   if (r == len)
+     return;
++#endif
+ 
+   if (r == -1)
+     if (errno == EAGAIN || errno == EWOULDBLOCK)
+@@ -200,12 +250,21 @@ static void uv__async_send(uv_loop_t* loop) {
+ 
+ 
+ static int uv__async_start(uv_loop_t* loop) {
++#ifndef __NUTTX__
+   int pipefd[2];
++#endif
+   int err;
+ 
+   if (loop->async_io_watcher.fd != -1)
+     return 0;
+ 
++#ifdef __NUTTX__
++  err = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
++  if (err < 0)
++    return UV__ERR(errno);
++  uv__io_init(&loop->async_io_watcher, uv__async_io, err);
++  uv__io_start(loop, &loop->async_io_watcher, POLLIN);
++#else
+ #ifdef __linux__
+   err = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
+   if (err < 0)
+@@ -222,11 +281,12 @@ static int uv__async_start(uv_loop_t* loop) {
+   uv__io_init(&loop->async_io_watcher, uv__async_io, pipefd[0]);
+   uv__io_start(loop, &loop->async_io_watcher, POLLIN);
+   loop->async_wfd = pipefd[1];
++#endif
+ 
+   return 0;
+ }
+ 
+-
++#ifndef __NUTTX__
+ int uv__async_fork(uv_loop_t* loop) {
+   if (loop->async_io_watcher.fd == -1) /* never started */
+     return 0;
+@@ -235,17 +295,20 @@ int uv__async_fork(uv_loop_t* loop) {
+ 
+   return uv__async_start(loop);
+ }
++#endif
+ 
+ 
+ void uv__async_stop(uv_loop_t* loop) {
+   if (loop->async_io_watcher.fd == -1)
+     return;
+ 
++#ifndef __NUTTX__
+   if (loop->async_wfd != -1) {
+     if (loop->async_wfd != loop->async_io_watcher.fd)
+       uv__close(loop->async_wfd);
+     loop->async_wfd = -1;
+   }
++#endif
+ 
+   uv__io_stop(loop, &loop->async_io_watcher, POLLIN);
+   uv__close(loop->async_io_watcher.fd);
+diff --git a/src/unix/core.c b/src/unix/core.c
+index 5b0b64dd4..2438614f0 100644
+--- a/src/unix/core.c
++++ b/src/unix/core.c
+@@ -1,3 +1,23 @@
++/****************************************************************************
++ * src/unix/core.c
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
+ /* 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
+@@ -58,11 +78,14 @@
+ # include <crt_externs.h>
+ # include <mach-o/dyld.h> /* _NSGetExecutablePath */
+ # define environ (*_NSGetEnviron())
++#elif defined(__NUTTX__)
++/* environ defined as function in stdlib in NuttX*/
+ #else /* defined(__APPLE__) && !TARGET_OS_IPHONE */
+ extern char** environ;
+ #endif /* !(defined(__APPLE__) && !TARGET_OS_IPHONE) */
+ 
+ 
++#if 0
+ #if defined(__DragonFly__)      || \
+     defined(__FreeBSD__)        || \
+     defined(__FreeBSD_kernel__) || \
+@@ -89,6 +112,7 @@ extern char** environ;
+ #endif
+ 
+ static int uv__run_pending(uv_loop_t* loop);
++#endif
+ 
+ /* Verify that uv_buf_t is ABI-compatible with struct iovec. */
+ STATIC_ASSERT(sizeof(uv_buf_t) == sizeof(struct iovec));
+@@ -112,6 +136,7 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
+   handle->close_cb = close_cb;
+ 
+   switch (handle->type) {
++#if 0
+   case UV_NAMED_PIPE:
+     uv__pipe_close((uv_pipe_t*)handle);
+     break;
+@@ -119,15 +144,21 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
+   case UV_TTY:
+     uv__stream_close((uv_stream_t*)handle);
+     break;
++#endif
+ 
++#ifdef CONFIG_LIBUV_TCP
+   case UV_TCP:
+     uv__tcp_close((uv_tcp_t*)handle);
+     break;
++#endif
+ 
++#ifdef CONFIG_LIBUV_UDP
+   case UV_UDP:
+     uv__udp_close((uv_udp_t*)handle);
+     break;
++#endif
+ 
++#ifdef CONFIG_LIBUV_LOOP_WATCHERS
+   case UV_PREPARE:
+     uv__prepare_close((uv_prepare_t*)handle);
+     break;
+@@ -139,15 +170,20 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
+   case UV_IDLE:
+     uv__idle_close((uv_idle_t*)handle);
+     break;
++#endif
+ 
++#ifdef CONFIG_LIBUV_ASYNC
+   case UV_ASYNC:
+     uv__async_close((uv_async_t*)handle);
+     break;
++#endif
+ 
++#ifdef CONFIG_LIBUV_TIMER
+   case UV_TIMER:
+     uv__timer_close((uv_timer_t*)handle);
+     break;
+-
++#endif
++#if 0
+   case UV_PROCESS:
+     uv__process_close((uv_process_t*)handle);
+     break;
+@@ -155,21 +191,24 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
+   case UV_FS_EVENT:
+     uv__fs_event_close((uv_fs_event_t*)handle);
+     break;
+-
++#endif
+   case UV_POLL:
+     uv__poll_close((uv_poll_t*)handle);
+     break;
+ 
++#ifdef CONFIG_LIBUV_FS_POLL
+   case UV_FS_POLL:
+     uv__fs_poll_close((uv_fs_poll_t*)handle);
+     /* Poll handles use file system requests, and one of them may still be
+      * running. The poll code will call uv__make_close_pending() for us. */
+     return;
++#endif
+ 
++#ifdef CONFIG_LIBUV_SIGNAL
+   case UV_SIGNAL:
+     uv__signal_close((uv_signal_t*) handle);
+     break;
+-
++#endif
+   default:
+     assert(0);
+   }
+@@ -177,6 +216,7 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
+   uv__make_close_pending(handle);
+ }
+ 
++#if 0
+ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
+   int r;
+   int fd;
+@@ -204,6 +244,7 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
+ 
+   return 0;
+ }
++#endif
+ 
+ void uv__make_close_pending(uv_handle_t* handle) {
+   assert(handle->flags & UV_HANDLE_CLOSING);
+@@ -241,7 +282,9 @@ int uv__getiovmax(void) {
+ 
+ 
+ static void uv__finish_close(uv_handle_t* handle) {
++#ifdef CONFIG_LIBUV_SIGNAL
+   uv_signal_t* sh;
++#endif
+ 
+   /* Note: while the handle is in the UV_HANDLE_CLOSING state now, it's still
+    * possible for it to be active in the sense that uv__is_active() returns
+@@ -256,17 +299,28 @@ static void uv__finish_close(uv_handle_t* handle) {
+   handle->flags |= UV_HANDLE_CLOSED;
+ 
+   switch (handle->type) {
++#ifdef CONFIG_LIBUV_LOOP_WATCHERS
+     case UV_PREPARE:
+     case UV_CHECK:
+     case UV_IDLE:
++#endif
++#ifdef CONFIG_LIBUV_ASYNC
+     case UV_ASYNC:
++#endif
++#ifdef CONFIG_LIBUV_TIMER
+     case UV_TIMER:
++#endif
++#if 0
+     case UV_PROCESS:
+     case UV_FS_EVENT:
++#endif
++
++#ifdef CONFIG_LIBUV_FS_POLL
+     case UV_FS_POLL:
++#endif
+     case UV_POLL:
+       break;
+-
++#ifdef CONFIG_LIBUV_SIGNAL
+     case UV_SIGNAL:
+       /* If there are any caught signals "trapped" in the signal pipe,
+        * we can't call the close callback yet. Reinserting the handle
+@@ -280,17 +334,21 @@ static void uv__finish_close(uv_handle_t* handle) {
+         return;
+       }
+       break;
+-
++#endif
++#if 0
+     case UV_NAMED_PIPE:
+-    case UV_TCP:
+     case UV_TTY:
++#endif
++#ifdef CONFIG_LIBUV_TCP
++    case UV_TCP:
+       uv__stream_destroy((uv_stream_t*)handle);
+       break;
+-
++#endif
++#ifdef CONFIG_LIBUV_UDP
+     case UV_UDP:
+       uv__udp_finish_close((uv_udp_t*)handle);
+       break;
+-
++#endif
+     default:
+       assert(0);
+       break;
+@@ -324,10 +382,11 @@ int uv_is_closing(const uv_handle_t* handle) {
+   return uv__is_closing(handle);
+ }
+ 
+-
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+ int uv_backend_fd(const uv_loop_t* loop) {
+   return loop->backend_fd;
+ }
++#endif
+ 
+ 
+ int uv_backend_timeout(const uv_loop_t* loop) {
+@@ -337,16 +396,24 @@ int uv_backend_timeout(const uv_loop_t* loop) {
+   if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop))
+     return 0;
+ 
++#ifdef CONFIG_LIBUV_LOOP_WATCHERS
+   if (!QUEUE_EMPTY(&loop->idle_handles))
+     return 0;
++#endif
+ 
++#if 0
+   if (!QUEUE_EMPTY(&loop->pending_queue))
+     return 0;
++#endif
+ 
+   if (loop->closing_handles)
+     return 0;
+ 
++#ifdef CONFIG_LIBUV_TIMER
+   return uv__next_timeout(loop);
++#else
++  return -1;
++#endif
+ }
+ 
+ 
+@@ -373,17 +440,30 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) {
+ 
+   while (r != 0 && loop->stop_flag == 0) {
+     uv__update_time(loop);
++
++#ifdef CONFIG_LIBUV_TIMER
+     uv__run_timers(loop);
++#endif
++
++#if 0
+     ran_pending = uv__run_pending(loop);
++#else
++    ran_pending = 0;
++#endif
++
++#ifdef CONFIG_LIBUV_LOOP_WATCHERS
+     uv__run_idle(loop);
+     uv__run_prepare(loop);
++#endif
+ 
+     timeout = 0;
+     if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
+       timeout = uv_backend_timeout(loop);
+ 
+     uv__io_poll(loop, timeout);
++#ifdef CONFIG_LIBUV_LOOP_WATCHERS
+     uv__run_check(loop);
++#endif
+     uv__run_closing_handles(loop);
+ 
+     if (mode == UV_RUN_ONCE) {
+@@ -396,7 +476,10 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) {
+        * the check.
+        */
+       uv__update_time(loop);
++
++#ifdef CONFIG_LIBUV_TIMER
+       uv__run_timers(loop);
++#endif
+     }
+ 
+     r = uv__loop_alive(loop);
+@@ -423,7 +506,7 @@ int uv_is_active(const uv_handle_t* handle) {
+   return uv__is_active(handle);
+ }
+ 
+-
++#ifdef CONFIG_LIBUV_NET
+ /* Open a socket in non-blocking close-on-exec mode, atomically if possible. */
+ int uv__socket(int domain, int type, int protocol) {
+   int sockfd;
+@@ -460,6 +543,7 @@ int uv__socket(int domain, int type, int protocol) {
+ 
+   return sockfd;
+ }
++#endif
+ 
+ /* get a file pointer to a file in read-only and close-on-exec mode */
+ FILE* uv__open_file(const char* path) {
+@@ -477,7 +561,7 @@ FILE* uv__open_file(const char* path) {
+    return fp;
+ }
+ 
+-
++#ifdef CONFIG_LIBUV_STREAM
+ int uv__accept(int sockfd) {
+   int peerfd;
+   int err;
+@@ -509,7 +593,7 @@ int uv__accept(int sockfd) {
+ 
+   return peerfd;
+ }
+-
++#endif
+ 
+ /* close() on macos has the "interesting" quirk that it fails with EINTR
+  * without closing the file descriptor when a thread is in the cancel state.
+@@ -531,6 +615,8 @@ int uv__close_nocancel(int fd) {
+   return close$NOCANCEL$UNIX2003(fd);
+ #endif
+ #pragma GCC diagnostic pop
++#elif defined(__NUTTX__)
++  return close(fd);
+ #elif defined(__linux__)
+   return syscall(SYS_close, fd);
+ #else
+@@ -559,11 +645,18 @@ int uv__close_nocheckstdio(int fd) {
+ 
+ 
+ int uv__close(int fd) {
++#ifdef __NUTTX__
++  if (close(fd) < 0) {
++      return UV__ERR(errno);
++  }
++  return 0;
++#else
+   assert(fd > STDERR_FILENO);  /* Catch stdio close bugs. */
+ #if defined(__MVS__)
+   SAVE_ERRNO(epoll_file_close(fd));
+ #endif
+   return uv__close_nocheckstdio(fd);
++#endif /* __NUTTX__ */
+ }
+ 
+ 
+@@ -581,7 +674,8 @@ int uv__nonblock_ioctl(int fd, int set) {
+ }
+ 
+ 
+-#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__HAIKU__)
++#if !defined(__CYGWIN__) && !defined(__MSYS__) && \
++    !defined(__HAIKU__)  && !defined(__NUTTX__)
+ int uv__cloexec_ioctl(int fd, int set) {
+   int r;
+ 
+@@ -658,7 +752,7 @@ int uv__cloexec_fcntl(int fd, int set) {
+   return 0;
+ }
+ 
+-
++#if 0
+ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
+   struct cmsghdr* cmsg;
+   ssize_t rc;
+@@ -695,7 +789,7 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
+         uv__cloexec(*pfd, 1);
+   return rc;
+ }
+-
++#endif
+ 
+ int uv_cwd(char* buffer, size_t* size) {
+   char scratch[1 + UV__PATH_MAX];
+@@ -743,7 +837,7 @@ int uv_chdir(const char* dir) {
+   return 0;
+ }
+ 
+-
++#if 0
+ void uv_disable_stdio_inheritance(void) {
+   int fd;
+ 
+@@ -754,7 +848,7 @@ void uv_disable_stdio_inheritance(void) {
+     if (uv__cloexec(fd, 1) && fd > 15)
+       break;
+ }
+-
++#endif
+ 
+ int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) {
+   int fd_out;
+@@ -785,7 +879,7 @@ int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) {
+   return 0;
+ }
+ 
+-
++#if 0
+ static int uv__run_pending(uv_loop_t* loop) {
+   QUEUE* q;
+   QUEUE pq;
+@@ -806,8 +900,9 @@ static int uv__run_pending(uv_loop_t* loop) {
+ 
+   return 1;
+ }
++#endif
+ 
+-
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+ static unsigned int next_power_of_two(unsigned int val) {
+   val -= 1;
+   val |= val >> 1;
+@@ -852,12 +947,14 @@ static void maybe_resize(uv_loop_t* loop, unsigned int len) {
+   loop->watchers = watchers;
+   loop->nwatchers = nwatchers;
+ }
+-
++#endif
+ 
+ void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd) {
+   assert(cb != NULL);
+   assert(fd >= -1);
++#if 0
+   QUEUE_INIT(&w->pending_queue);
++#endif
+   QUEUE_INIT(&w->watcher_queue);
+   w->cb = cb;
+   w->fd = fd;
+@@ -878,7 +975,9 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
+   assert(w->fd < INT_MAX);
+ 
+   w->pevents |= events;
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+   maybe_resize(loop, w->fd + 1);
++#endif
+ 
+ #if !defined(__sun)
+   /* The event ports backend needs to rearm all file descriptors on each and
+@@ -892,10 +991,12 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
+   if (QUEUE_EMPTY(&w->watcher_queue))
+     QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
+ 
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+   if (loop->watchers[w->fd] == NULL) {
+     loop->watchers[w->fd] = w;
+     loop->nfds++;
+   }
++#endif
+ }
+ 
+ 
+@@ -909,8 +1010,10 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
+   assert(w->fd >= 0);
+ 
+   /* Happens when uv__io_stop() is called on a handle that was never started. */
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+   if ((unsigned) w->fd >= loop->nwatchers)
+     return;
++#endif
+ 
+   w->pevents &= ~events;
+ 
+@@ -918,6 +1021,7 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
+     QUEUE_REMOVE(&w->watcher_queue);
+     QUEUE_INIT(&w->watcher_queue);
+ 
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+     if (loop->watchers[w->fd] != NULL) {
+       assert(loop->watchers[w->fd] == w);
+       assert(loop->nfds > 0);
+@@ -925,6 +1029,9 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
+       loop->nfds--;
+       w->events = 0;
+     }
++#else
++    w->events = 0;
++#endif
+   }
+   else if (QUEUE_EMPTY(&w->watcher_queue))
+     QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
+@@ -933,7 +1040,7 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
+ 
+ void uv__io_close(uv_loop_t* loop, uv__io_t* w) {
+   uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
+-  QUEUE_REMOVE(&w->pending_queue);
++  // QUEUE_REMOVE(&w->pending_queue);
+ 
+   /* Remove stale events for this file descriptor */
+   if (w->fd != -1)
+@@ -941,10 +1048,12 @@ void uv__io_close(uv_loop_t* loop, uv__io_t* w) {
+ }
+ 
+ 
++#if 0
+ void uv__io_feed(uv_loop_t* loop, uv__io_t* w) {
+   if (QUEUE_EMPTY(&w->pending_queue))
+     QUEUE_INSERT_TAIL(&loop->pending_queue, &w->pending_queue);
+ }
++#endif
+ 
+ 
+ int uv__io_active(const uv__io_t* w, unsigned int events) {
+@@ -955,10 +1064,22 @@ int uv__io_active(const uv__io_t* w, unsigned int events) {
+ 
+ 
+ int uv__fd_exists(uv_loop_t* loop, int fd) {
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+   return (unsigned) fd < loop->nwatchers && loop->watchers[fd] != NULL;
++#else
++  QUEUE* q;
++  uv__io_t* w;
++  QUEUE_FOREACH(q, &loop->watcher_queue) {
++    w = QUEUE_DATA(q, uv__io_t, watcher_queue);
++    if (w->fd == fd) {
++      return 1;
++    }
++  }
++  return 0;
++#endif
+ }
+ 
+-
++#if 0
+ int uv_getrusage(uv_rusage_t* rusage) {
+   struct rusage usage;
+ 
+@@ -990,7 +1111,7 @@ int uv_getrusage(uv_rusage_t* rusage) {
+ 
+   return 0;
+ }
+-
++#endif
+ 
+ int uv__open_cloexec(const char* path, int flags) {
+ #if defined(O_CLOEXEC)
+@@ -1019,7 +1140,7 @@ int uv__open_cloexec(const char* path, int flags) {
+ #endif  /* O_CLOEXEC */
+ }
+ 
+-
++#if 0
+ int uv__dup2_cloexec(int oldfd, int newfd) {
+ #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__linux__)
+   int r;
+@@ -1046,7 +1167,7 @@ int uv__dup2_cloexec(int oldfd, int newfd) {
+   return r;
+ #endif
+ }
+-
++#endif
+ 
+ int uv_os_homedir(char* buffer, size_t* size) {
+   uv_passwd_t pwd;
+@@ -1390,12 +1511,13 @@ uv_pid_t uv_os_getpid(void) {
+   return getpid();
+ }
+ 
+-
++#if 0
+ uv_pid_t uv_os_getppid(void) {
+   return getppid();
+ }
++#endif
+ 
+-
++#if 0
+ int uv_os_getpriority(uv_pid_t pid, int* priority) {
+   int r;
+ 
+@@ -1422,7 +1544,7 @@ int uv_os_setpriority(uv_pid_t pid, int priority) {
+ 
+   return 0;
+ }
+-
++#endif
+ 
+ int uv_os_uname(uv_utsname_t* buffer) {
+   struct utsname buf;
+diff --git a/src/unix/fs.c b/src/unix/fs.c
+index dd08ea541..4e32d0783 100644
+--- a/src/unix/fs.c
++++ b/src/unix/fs.c
+@@ -56,6 +56,12 @@
+ # define HAVE_PREADV 0
+ #endif
+ 
++#ifdef __NUTTX__
++# include <sys/sendfile.h>
++# include <sys/statfs.h>
++
++#else /* __NUTTX__ */
++
+ #if defined(__linux__) || defined(__sun)
+ # include <sys/sendfile.h>
+ #endif
+@@ -84,6 +90,7 @@
+ #else
+ # include <sys/statfs.h>
+ #endif
++#endif /* __NUTTX__ */
+ 
+ #if defined(_AIX) && _XOPEN_SOURCE <= 600
+ extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */
+@@ -219,6 +226,7 @@ UV_UNUSED(static struct timeval uv__fs_to_timeval(double time)) {
+   return tv;
+ }
+ 
++#ifndef __NUTTX__
+ static ssize_t uv__fs_futime(uv_fs_t* req) {
+ #if defined(__linux__)                                                        \
+     || defined(_AIX71)                                                        \
+@@ -349,7 +357,7 @@ static int uv__fs_mkstemp(uv_fs_t* req) {
+ 
+   return r;
+ }
+-
++#endif /* __NUTTX__ */
+ 
+ static ssize_t uv__fs_open(uv_fs_t* req) {
+ #ifdef O_CLOEXEC
+@@ -431,7 +439,7 @@ static ssize_t uv__fs_preadv(uv_file fd,
+ 
+ 
+ static ssize_t uv__fs_read(uv_fs_t* req) {
+-#if defined(__linux__)
++#if !defined(__NUTTX__) && defined(__linux__)
+   static int no_preadv;
+ #endif
+   unsigned int iovmax;
+@@ -455,13 +463,13 @@ static ssize_t uv__fs_read(uv_fs_t* req) {
+ #if HAVE_PREADV
+     result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
+ #else
+-# if defined(__linux__)
++# if !defined(__NUTTX__) && defined(__linux__)
+     if (uv__load_relaxed(&no_preadv)) retry:
+ # endif
+     {
+       result = uv__fs_preadv(req->file, req->bufs, req->nbufs, req->off);
+     }
+-# if defined(__linux__)
++# if !defined(__NUTTX__) && defined(__linux__)
+     else {
+       result = uv__preadv(req->file,
+                           (struct iovec*)req->bufs,
+@@ -668,6 +676,7 @@ static ssize_t uv__fs_pathmax_size(const char* path) {
+   return pathmax;
+ }
+ 
++#ifdef CONFIG_PSEUDOFS_SOFTLINKS
+ static ssize_t uv__fs_readlink(uv_fs_t* req) {
+   ssize_t maxlen;
+   ssize_t len;
+@@ -726,6 +735,7 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) {
+ 
+   return 0;
+ }
++#endif
+ 
+ static ssize_t uv__fs_realpath(uv_fs_t* req) {
+   char* buf;
+@@ -756,6 +766,7 @@ static ssize_t uv__fs_realpath(uv_fs_t* req) {
+   return 0;
+ }
+ 
++#ifndef __NUTTX__
+ static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) {
+   struct pollfd pfd;
+   int use_pread;
+@@ -868,7 +879,7 @@ out:
+ 
+   return nsent;
+ }
+-
++#endif
+ 
+ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
+   int in_fd;
+@@ -877,7 +888,7 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
+   in_fd = req->flags;
+   out_fd = req->file;
+ 
+-#if defined(__linux__) || defined(__sun)
++#if defined(__NUTTX__) || defined(__linux__) || defined(__sun)
+   {
+     off_t off;
+     ssize_t r;
+@@ -895,6 +906,7 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
+       return r;
+     }
+ 
++#ifndef __NUTTX__
+     if (errno == EINVAL ||
+         errno == EIO ||
+         errno == ENOTSOCK ||
+@@ -902,7 +914,7 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
+       errno = 0;
+       return uv__fs_sendfile_emul(req);
+     }
+-
++#endif
+     return -1;
+   }
+ #elif defined(__APPLE__)           || \
+@@ -970,7 +982,12 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
+ 
+ 
+ static ssize_t uv__fs_utime(uv_fs_t* req) {
+-#if defined(__linux__)                                                         \
++#if defined(__NUTTX__)
++  struct timeval tv[2];
++  tv[0] = uv__fs_to_timeval(req->atime);
++  tv[1] = uv__fs_to_timeval(req->mtime);
++  return utimes(req->path, tv);
++#elif defined(__linux__)                                                         \
+     || defined(_AIX71)                                                         \
+     || defined(__sun)                                                          \
+     || defined(__HAIKU__)
+@@ -1011,7 +1028,7 @@ static ssize_t uv__fs_utime(uv_fs_t* req) {
+ #endif
+ }
+ 
+-
++#ifndef __NUTTX__
+ static ssize_t uv__fs_lutime(uv_fs_t* req) {
+ #if defined(__linux__)            ||                                           \
+     defined(_AIX71)               ||                                           \
+@@ -1035,10 +1052,10 @@ static ssize_t uv__fs_lutime(uv_fs_t* req) {
+   return -1;
+ #endif
+ }
+-
++#endif
+ 
+ static ssize_t uv__fs_write(uv_fs_t* req) {
+-#if defined(__linux__)
++#if !defined(__NUTTX__) && defined(__linux__)
+   static int no_pwritev;
+ #endif
+   ssize_t r;
+@@ -1067,13 +1084,13 @@ static ssize_t uv__fs_write(uv_fs_t* req) {
+ #if HAVE_PREADV
+     r = pwritev(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
+ #else
+-# if defined(__linux__)
++# if !defined(__NUTTX__) && defined(__linux__)
+     if (no_pwritev) retry:
+ # endif
+     {
+       r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
+     }
+-# if defined(__linux__)
++# if !defined(__NUTTX__) && defined(__linux__)
+     else {
+       r = uv__pwritev(req->file,
+                       (struct iovec*) req->bufs,
+@@ -1102,7 +1119,9 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
+   uv_file srcfd;
+   uv_file dstfd;
+   struct stat src_statsbuf;
++#ifndef __NUTTX__
+   struct stat dst_statsbuf;
++#endif
+   int dst_flags;
+   int result;
+   int err;
+@@ -1146,6 +1165,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
+     goto out;
+   }
+ 
++#ifndef __NUTTX__
+   /* Get the destination file's mode. */
+   if (fstat(dstfd, &dst_statsbuf)) {
+     err = UV__ERR(errno);
+@@ -1157,9 +1177,12 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
+       src_statsbuf.st_ino == dst_statsbuf.st_ino) {
+     goto out;
+   }
++#endif
+ 
++#ifndef __NUTTX__
+   if (fchmod(dstfd, src_statsbuf.st_mode) == -1) {
+     err = UV__ERR(errno);
++    goto out;
+ #ifdef __linux__
+     if (err != UV_EPERM)
+       goto out;
+@@ -1183,6 +1206,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
+     goto out;
+ #endif  /* !__linux__ */
+   }
++#endif /* !__NUTTX__ */
+ 
+ #ifdef FICLONE
+   if (req->flags & UV_FS_COPYFILE_FICLONE ||
+@@ -1343,7 +1367,7 @@ static int uv__fs_statx(int fd,
+                         int is_lstat,
+                         uv_stat_t* buf) {
+   STATIC_ASSERT(UV_ENOSYS != -1);
+-#ifdef __linux__
++#if !defined(__NUTTX__) && defined(__linux__)
+   static int no_statx;
+   struct uv__statx statxbuf;
+   int dirfd;
+@@ -1543,30 +1567,40 @@ static void uv__fs_work(struct uv__work* w) {
+     switch (req->fs_type) {
+     X(ACCESS, access(req->path, req->flags));
+     X(CHMOD, chmod(req->path, req->mode));
++#ifndef __NUTTX__
+     X(CHOWN, chown(req->path, req->uid, req->gid));
++#endif
+     X(CLOSE, uv__fs_close(req->file));
+     X(COPYFILE, uv__fs_copyfile(req));
+     X(FCHMOD, fchmod(req->file, req->mode));
++#ifndef __NUTTX__
+     X(FCHOWN, fchown(req->file, req->uid, req->gid));
+     X(LCHOWN, lchown(req->path, req->uid, req->gid));
++#endif
+     X(FDATASYNC, uv__fs_fdatasync(req));
+     X(FSTAT, uv__fs_fstat(req->file, &req->statbuf));
+     X(FSYNC, uv__fs_fsync(req));
+     X(FTRUNCATE, ftruncate(req->file, req->off));
++#ifndef __NUTTX__
+     X(FUTIME, uv__fs_futime(req));
+     X(LUTIME, uv__fs_lutime(req));
++#endif
+     X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));
+     X(LINK, link(req->path, req->new_path));
+     X(MKDIR, mkdir(req->path, req->mode));
++#ifndef __NUTTX__
+     X(MKDTEMP, uv__fs_mkdtemp(req));
+     X(MKSTEMP, uv__fs_mkstemp(req));
++#endif
+     X(OPEN, uv__fs_open(req));
+     X(READ, uv__fs_read(req));
+     X(SCANDIR, uv__fs_scandir(req));
+     X(OPENDIR, uv__fs_opendir(req));
+     X(READDIR, uv__fs_readdir(req));
+     X(CLOSEDIR, uv__fs_closedir(req));
++#ifdef CONFIG_PSEUDOFS_SOFTLINKS
+     X(READLINK, uv__fs_readlink(req));
++#endif
+     X(REALPATH, uv__fs_realpath(req));
+     X(RENAME, rename(req->path, req->new_path));
+     X(RMDIR, rmdir(req->path));
+diff --git a/src/unix/internal.h b/src/unix/internal.h
+index 402ee877d..9f828a223 100644
+--- a/src/unix/internal.h
++++ b/src/unix/internal.h
+@@ -1,3 +1,23 @@
++/****************************************************************************
++ * src/unix/internal.h
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+@@ -157,14 +177,15 @@ struct uv__stream_queued_fds_s {
+ };
+ 
+ 
+-#if defined(_AIX) || \
++#if !defined(__NUTTX__) && ( \
++    defined(_AIX) || \
+     defined(__APPLE__) || \
+     defined(__DragonFly__) || \
+     defined(__FreeBSD__) || \
+     defined(__FreeBSD_kernel__) || \
+     defined(__linux__) || \
+     defined(__OpenBSD__) || \
+-    defined(__NetBSD__)
++    defined(__NetBSD__))
+ #define uv__cloexec uv__cloexec_ioctl
+ #define uv__nonblock uv__nonblock_ioctl
+ #else
+@@ -247,6 +268,7 @@ int uv__signal_loop_fork(uv_loop_t* loop);
+ 
+ /* platform specific */
+ uint64_t uv__hrtime(uv_clocktype_t type);
++uint32_t uv__hrtime_ms(uv_clocktype_t type);
+ int uv__kqueue_init(uv_loop_t* loop);
+ int uv__platform_loop_init(uv_loop_t* loop);
+ void uv__platform_loop_delete(uv_loop_t* loop);
+@@ -302,7 +324,11 @@ void uv__fsevents_loop_delete(uv_loop_t* loop);
+ UV_UNUSED(static void uv__update_time(uv_loop_t* loop)) {
+   /* Use a fast time source if available.  We only need millisecond precision.
+    */
++#ifdef CONFIG_LIBUV_TIMER_NUTTX
++  loop->time = uv__hrtime_ms(UV_CLOCK_FAST);
++#else
+   loop->time = uv__hrtime(UV_CLOCK_FAST) / 1000000;
++#endif
+ }
+ 
+ UV_UNUSED(static char* uv__basename_r(const char* path)) {
+diff --git a/src/unix/loop.c b/src/unix/loop.c
+index e5b288956..de5d5aa80 100644
+--- a/src/unix/loop.c
++++ b/src/unix/loop.c
+@@ -1,3 +1,23 @@
++/****************************************************************************
++ * src/unix/loop.c
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+@@ -27,48 +47,87 @@
+ #include <string.h>
+ #include <unistd.h>
+ 
++#ifdef CONFIG_LIBUV_CONTEXT
++int uv_loop_init(uv_loop_t* loop, uv_context_t *ctx) {
++#else
+ int uv_loop_init(uv_loop_t* loop) {
++#endif
+   void* saved_data;
+   int err;
+ 
+-
+   saved_data = loop->data;
+   memset(loop, 0, sizeof(*loop));
+   loop->data = saved_data;
+ 
++#ifdef CONFIG_LIBUV_CONTEXT
++  loop->context = ctx;
++#endif
++
++#ifdef CONFIG_LIBUV_TIMER_NUTTX
++  loop->timer_head = NULL;
++#elif defined(CONFIG_LIBUV_TIMER)
+   heap_init((struct heap*) &loop->timer_heap);
++#endif
++#ifdef CONFIG_LIBUV_WQ
+   QUEUE_INIT(&loop->wq);
++#endif
++#ifdef CONFIG_LIBUV_LOOP_WATCHERS
+   QUEUE_INIT(&loop->idle_handles);
++#endif
++#ifdef CONFIG_LIBUV_ASYNC
+   QUEUE_INIT(&loop->async_handles);
++#endif
++#ifdef CONFIG_LIBUV_LOOP_WATCHERS
+   QUEUE_INIT(&loop->check_handles);
+   QUEUE_INIT(&loop->prepare_handles);
++#endif
+   QUEUE_INIT(&loop->handle_queue);
+ 
+   loop->active_handles = 0;
+   loop->active_reqs.count = 0;
++
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+   loop->nfds = 0;
+   loop->watchers = NULL;
+   loop->nwatchers = 0;
++#endif
++#if 0
+   QUEUE_INIT(&loop->pending_queue);
++#endif
+   QUEUE_INIT(&loop->watcher_queue);
+ 
+   loop->closing_handles = NULL;
+   uv__update_time(loop);
++#ifdef CONFIG_LIBUV_ASYNC
+   loop->async_io_watcher.fd = -1;
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+   loop->async_wfd = -1;
++#endif
++#endif
++
++#ifdef CONFIG_LIBUV_SIGNAL
+   loop->signal_pipefd[0] = -1;
+   loop->signal_pipefd[1] = -1;
++#endif
++
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+   loop->backend_fd = -1;
+   loop->emfile_fd = -1;
++#endif
+ 
++#if defined(CONFIG_LIBUV_TIMER) && !defined(CONFIG_LIBUV_TIMER_NUTTX)
+   loop->timer_counter = 0;
++#endif
+   loop->stop_flag = 0;
+ 
+   err = uv__platform_loop_init(loop);
+   if (err)
+     return err;
+ 
++#ifdef CONFIG_LIBUV_SIGNAL
+   uv__signal_global_once_init();
++
++#ifdef CONFIG_LIBUV_PROCESS
+   err = uv_signal_init(loop, &loop->child_watcher);
+   if (err)
+     goto fail_signal_init;
+@@ -76,11 +135,16 @@ int uv_loop_init(uv_loop_t* loop) {
+   uv__handle_unref(&loop->child_watcher);
+   loop->child_watcher.flags |= UV_HANDLE_INTERNAL;
+   QUEUE_INIT(&loop->process_handles);
++#endif
++#endif
+ 
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+   err = uv_rwlock_init(&loop->cloexec_lock);
+   if (err)
+     goto fail_rwlock_init;
++#endif
+ 
++#ifdef CONFIG_LIBUV_WQ
+   err = uv_mutex_init(&loop->wq_mutex);
+   if (err)
+     goto fail_mutex_init;
+@@ -91,27 +155,38 @@ int uv_loop_init(uv_loop_t* loop) {
+ 
+   uv__handle_unref(&loop->wq_async);
+   loop->wq_async.flags |= UV_HANDLE_INTERNAL;
++#endif
+ 
+   return 0;
+ 
++#ifdef CONFIG_LIBUV_WQ
+ fail_async_init:
+   uv_mutex_destroy(&loop->wq_mutex);
+ 
+ fail_mutex_init:
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+   uv_rwlock_destroy(&loop->cloexec_lock);
++#endif
++#endif
+ 
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+ fail_rwlock_init:
++#endif
++#ifdef CONFIG_LIBUV_PROCESS
+   uv__signal_loop_cleanup(loop);
+ 
+ fail_signal_init:
++#endif
+   uv__platform_loop_delete(loop);
+ 
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+   uv__free(loop->watchers);
+   loop->nwatchers = 0;
++#endif
+   return err;
+ }
+ 
+-
++#if 0
+ int uv_loop_fork(uv_loop_t* loop) {
+   int err;
+   unsigned int i;
+@@ -143,13 +218,19 @@ int uv_loop_fork(uv_loop_t* loop) {
+ 
+   return 0;
+ }
+-
++#endif
+ 
+ void uv__loop_close(uv_loop_t* loop) {
++#ifdef CONFIG_LIBUV_SIGNAL
+   uv__signal_loop_cleanup(loop);
++#endif
+   uv__platform_loop_delete(loop);
++
++#ifdef CONFIG_LIBUV_ASYNC
+   uv__async_stop(loop);
++#endif
+ 
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+   if (loop->emfile_fd != -1) {
+     uv__close(loop->emfile_fd);
+     loop->emfile_fd = -1;
+@@ -159,18 +240,25 @@ void uv__loop_close(uv_loop_t* loop) {
+     uv__close(loop->backend_fd);
+     loop->backend_fd = -1;
+   }
++#endif
+ 
++#ifdef CONFIG_LIBUV_WQ
+   uv_mutex_lock(&loop->wq_mutex);
+   assert(QUEUE_EMPTY(&loop->wq) && "thread pool work queue not empty!");
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+   assert(!uv__has_active_reqs(loop));
++#endif
+   uv_mutex_unlock(&loop->wq_mutex);
+   uv_mutex_destroy(&loop->wq_mutex);
++#endif
+ 
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+   /*
+    * Note that all thread pool stuff is finished at this point and
+    * it is safe to just destroy rw lock
+    */
+   uv_rwlock_destroy(&loop->cloexec_lock);
++#endif
+ 
+ #if 0
+   assert(QUEUE_EMPTY(&loop->pending_queue));
+@@ -178,13 +266,16 @@ void uv__loop_close(uv_loop_t* loop) {
+   assert(loop->nfds == 0);
+ #endif
+ 
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
+   uv__free(loop->watchers);
+   loop->watchers = NULL;
+   loop->nwatchers = 0;
++#endif
+ }
+ 
+ 
+ int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) {
++#ifndef __NUTTX__
+   if (option != UV_LOOP_BLOCK_SIGNAL)
+     return UV_ENOSYS;
+ 
+@@ -192,5 +283,6 @@ int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) {
+     return UV_EINVAL;
+ 
+   loop->flags |= UV_LOOP_BLOCK_SIGPROF;
++#endif
+   return 0;
+ }
+diff --git a/src/unix/no-proctitle.c b/src/unix/no-proctitle.c
+index 32aa0af1f..64a785351 100644
+--- a/src/unix/no-proctitle.c
++++ b/src/unix/no-proctitle.c
+@@ -1,3 +1,23 @@
++/****************************************************************************
++ * src/unix/no-proctitle.c
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
+ /* Copyright libuv project contributors. All rights reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+@@ -29,8 +49,16 @@ char** uv_setup_args(int argc, char** argv) {
+   return argv;
+ }
+ 
++#ifdef CONFIG_LIBUV_CONTEXT
++void uv__process_title_setup(uv_context_t *ctx) {
++}
++
++void uv__process_title_cleanup(uv_context_t *ctx) {
++}
++#else
+ void uv__process_title_cleanup(void) {
+ }
++#endif
+ 
+ int uv_set_process_title(const char* title) {
+   return 0;
+diff --git a/src/unix/nuttx.c b/src/unix/nuttx.c
+new file mode 100644
+index 000000000..4549e48eb
+--- /dev/null
++++ b/src/unix/nuttx.c
+@@ -0,0 +1,238 @@
++/****************************************************************************
++ * libuv/src/unix/nuttx.c
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
++/* Copyright libuv project 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 "unix/internal.h"
++
++#include <stdint.h>
++#include <time.h>
++#include <assert.h>
++
++#undef NANOSEC
++#define NANOSEC ((uint64_t) 1e9)
++
++int uv__platform_loop_init(uv_loop_t* loop) {
++  return 0;
++}
++
++void uv__platform_loop_delete(uv_loop_t* loop) {
++}
++
++/* From libuv/src/unix/posix-hrtime.c */
++
++uint64_t uv__hrtime(uv_clocktype_t type) {
++  struct timespec ts;
++  clock_gettime(CLOCK_MONOTONIC, &ts);
++  return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec);
++}
++
++uint32_t uv__hrtime_ms(uv_clocktype_t type) {
++  struct timespec ts;
++  clock_gettime(CLOCK_MONOTONIC, &ts);
++  return (uint32_t)(((uint64_t) ts.tv_sec) * 1000 + (ts.tv_nsec/1000/1000));
++}
++
++/* From libuv/src/unix/posix-poll.c */
++
++void uv__io_poll(uv_loop_t* loop, int timeout) {
++  uv_time_t time_base;
++  uv_time_t time_diff;
++  QUEUE* q;
++  uv__io_t* w;
++  size_t i;
++  unsigned int nevents;
++  int nfds;
++#ifdef CONFIG_LIBUV_SIGNAL
++  int have_signals;
++#endif
++  struct pollfd* pe;
++  int fd;
++
++  assert(timeout >= -1);
++  time_base = loop->time;
++
++  if (QUEUE_EMPTY(&loop->watcher_queue)) {
++    if (timeout > 0) {
++      usleep(1000*timeout);
++    }
++    return;
++  }
++
++  /* Build pollfd array */
++
++  loop->poll_fds_used = 0;
++  QUEUE_FOREACH(q, &loop->watcher_queue) {
++    w = QUEUE_DATA(q, uv__io_t, watcher_queue);
++
++    /* Allocate new entry */
++    i = loop->poll_fds_used ++;
++    if (loop->poll_fds_used >= CONFIG_LIBUV_NPOLLWAITERS) {
++      /* Error no available pollfd for loop */
++      abort();
++    }
++
++    loop->poll_fds[i].fd = w->fd;
++    loop->poll_fds[i].events = w->pevents;
++  }
++
++  /* Loop calls to poll() and processing of results.  If we get some
++   * results from poll() but they turn out not to be interesting to
++   * our caller then we need to loop around and poll() again.
++   */
++  for (;;) {
++    nfds = poll(loop->poll_fds, (nfds_t)loop->poll_fds_used, 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;
++    }
++
++    if (nfds == -1) {
++      if (errno != EINTR)
++        abort();
++
++      if (timeout == -1)
++        continue;
++
++      if (timeout == 0)
++        return;
++
++      /* Interrupted by a signal. Update timeout and poll again. */
++      goto update_timeout;
++    }
++
++    /* Initialize a count of events that we care about.  */
++    nevents = 0;
++#ifdef CONFIG_LIBUV_SIGNAL
++    have_signals = 0;
++#endif
++
++    /* Loop over the entire poll fds array looking for returned events.  */
++    for (i = 0; i < loop->poll_fds_used; i++) {
++      pe = loop->poll_fds + i;
++      fd = pe->fd;
++
++      if (fd < 0 || !pe->revents) {
++        continue;
++      }
++
++      QUEUE_FOREACH(q, &loop->watcher_queue) {
++        w = QUEUE_DATA(q, uv__io_t, watcher_queue);
++        if (w->fd == fd) {
++          goto process_event;
++        }
++      }
++
++      /* File descriptor that we've stopped watching, ignore.  */
++      continue;
++
++process_event:
++      /* Filter out events that user has not requested us to watch
++       * (e.g. POLLNVAL).
++       */
++      pe->revents &= w->pevents | POLLERR | POLLHUP;
++
++      if (pe->revents != 0) {
++#ifdef CONFIG_LIBUV_SIGNAL
++        /* Run signal watchers last.  */
++        if (w == &loop->signal_io_watcher) {
++          have_signals = 1;
++        } else
++#endif
++        {
++          w->cb(loop, w, pe->revents);
++        }
++
++        nevents++;
++      }
++    }
++
++#ifdef CONFIG_LIBUV_SIGNAL
++    if (have_signals != 0) {
++      loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
++      return;  /* Event loop should cycle now so don't poll again. */
++    }
++#endif
++
++    if (nevents != 0)
++      return;
++
++    if (timeout == 0)
++      return;
++
++    if (timeout == -1)
++      continue;
++
++update_timeout:
++    assert(timeout > 0);
++
++    time_diff = (uv_time_t)(loop->time - time_base);
++    if (time_diff >= (uv_time_t) timeout)
++      return;
++
++    timeout -= time_diff;
++  }
++}
++
++/* Check whether the given fd is supported by poll().  */
++int uv__io_check_fd(uv_loop_t* loop, int fd) {
++  return 0;
++}
++
++void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
++  int i;
++
++  /* uv__io_stop() removes uv__io_t from watcher_queue so
++   * no need to do it here */
++
++  for (i = 0; i < loop->poll_fds_used; i++) {
++    if (loop->poll_fds[i].fd == fd) {
++      loop->poll_fds[i].fd = -1;
++      break;
++    }
++  }
++}
+diff --git a/src/unix/nuttx_stream.c b/src/unix/nuttx_stream.c
+new file mode 100644
+index 000000000..891a872dd
+--- /dev/null
++++ b/src/unix/nuttx_stream.c
+@@ -0,0 +1,1077 @@
++/****************************************************************************
++ * libuv/src/unix/nuttx_stream.c
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
++/* 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 <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <assert.h>
++#include <errno.h>
++
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <sys/uio.h>
++#include <sys/un.h>
++#include <unistd.h>
++#include <limits.h> /* IOV_MAX */
++
++static void uv__stream_connect(uv_stream_t*);
++static void uv__write(uv_stream_t* stream);
++static void uv__read(uv_stream_t* stream);
++static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events);
++static void uv__write_callbacks(uv_stream_t* stream);
++static size_t uv__write_req_size(uv_write_t* req);
++
++
++void uv__stream_init(uv_loop_t* loop,
++                     uv_stream_t* stream,
++                     uv_handle_type type) {
++  uv__handle_init(loop, (uv_handle_t*)stream, type);
++  stream->read_cb = NULL;
++  stream->alloc_cb = NULL;
++  stream->close_cb = NULL;
++  stream->connection_cb = NULL;
++  stream->connect_req = NULL;
++  stream->shutdown_req = NULL;
++  stream->accepted_fd = -1;
++  stream->queued_fds = NULL;
++  QUEUE_INIT(&stream->write_queue);
++  QUEUE_INIT(&stream->write_completed_queue);
++  stream->write_queue_size = 0;
++
++  uv__io_init(&stream->io_watcher, uv__stream_io, -1);
++}
++
++
++int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
++  if (!(stream->io_watcher.fd == -1 || stream->io_watcher.fd == fd))
++    return UV_EBUSY;
++
++  assert(fd >= 0);
++  stream->flags |= flags;
++
++#ifdef CONFIG_LIBUV_TCP
++  if (stream->type == UV_TCP) {
++#ifdef CONFIG_NET_TCP_KEEPALIVE
++    /* TODO Use delay the user passed in. */
++    if ((stream->flags & UV_HANDLE_TCP_KEEPALIVE) &&
++        uv__tcp_keepalive(fd, 1, 60)) {
++      return UV__ERR(errno);
++    }
++#endif
++  }
++#endif
++
++  stream->io_watcher.fd = fd;
++
++  return 0;
++}
++
++
++void uv__stream_flush_write_queue(uv_stream_t* stream, int error) {
++  uv_write_t* req;
++  QUEUE* q;
++  while (!QUEUE_EMPTY(&stream->write_queue)) {
++    q = QUEUE_HEAD(&stream->write_queue);
++    QUEUE_REMOVE(q);
++
++    req = QUEUE_DATA(q, uv_write_t, queue);
++    req->error = error;
++
++    QUEUE_INSERT_TAIL(&stream->write_completed_queue, &req->queue);
++  }
++}
++
++
++void uv__stream_destroy(uv_stream_t* stream) {
++  assert(!uv__io_active(&stream->io_watcher, POLLIN | POLLOUT));
++  assert(stream->flags & UV_HANDLE_CLOSED);
++
++  if (stream->connect_req) {
++    uv__req_unregister(stream->loop, stream->connect_req);
++    stream->connect_req->cb(stream->connect_req, UV_ECANCELED);
++    stream->connect_req = NULL;
++  }
++
++  uv__stream_flush_write_queue(stream, UV_ECANCELED);
++  uv__write_callbacks(stream);
++
++  if (stream->shutdown_req) {
++    /* The ECANCELED error code is a lie, the shutdown(2) syscall is a
++     * fait accompli at this point. Maybe we should revisit this in v0.11.
++     * A possible reason for leaving it unchanged is that it informs the
++     * callee that the handle has been destroyed.
++     */
++    uv__req_unregister(stream->loop, stream->shutdown_req);
++    stream->shutdown_req->cb(stream->shutdown_req, UV_ECANCELED);
++    stream->shutdown_req = NULL;
++  }
++
++  assert(stream->write_queue_size == 0);
++}
++
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
++/* Implements a best effort approach to mitigating accept() EMFILE errors.
++ * We have a spare file descriptor stashed away that we close to get below
++ * the EMFILE limit. Next, we accept all pending connections and close them
++ * immediately to signal the clients that we're overloaded - and we are, but
++ * we still keep on trucking.
++ *
++ * There is one caveat: it's not reliable in a multi-threaded environment.
++ * The file descriptor limit is per process. Our party trick fails if another
++ * thread opens a file or creates a socket in the time window between us
++ * calling close() and accept().
++ */
++static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) {
++  int err;
++  int emfile_fd;
++
++  if (loop->emfile_fd == -1)
++    return UV_EMFILE;
++
++  uv__close(loop->emfile_fd);
++  loop->emfile_fd = -1;
++
++  do {
++    err = uv__accept(accept_fd);
++    if (err >= 0)
++      uv__close(err);
++  } while (err >= 0 || err == UV_EINTR);
++
++  emfile_fd = uv__open_cloexec("/", O_RDONLY);
++  if (emfile_fd >= 0)
++    loop->emfile_fd = emfile_fd;
++
++  return err;
++}
++#endif
++
++#if defined(UV_HAVE_KQUEUE)
++# define UV_DEC_BACKLOG(w) w->rcount--;
++#else
++# define UV_DEC_BACKLOG(w) /* no-op */
++#endif /* defined(UV_HAVE_KQUEUE) */
++
++
++void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
++  uv_stream_t* stream;
++  int err;
++
++  stream = container_of(w, uv_stream_t, io_watcher);
++  assert(events & POLLIN);
++  assert(stream->accepted_fd == -1);
++  assert(!(stream->flags & UV_HANDLE_CLOSING));
++
++  uv__io_start(stream->loop, &stream->io_watcher, POLLIN);
++
++  /* connection_cb can close the server socket while we're
++   * in the loop so check it on each iteration.
++   */
++  while (uv__stream_fd(stream) != -1) {
++    assert(stream->accepted_fd == -1);
++
++    err = uv__accept(uv__stream_fd(stream));
++    if (err < 0) {
++      if (err == UV_EAGAIN || err == UV__ERR(EWOULDBLOCK))
++        return;  /* Not an error. */
++
++      if (err == UV_ECONNABORTED)
++        continue;  /* Ignore. Nothing we can do about that. */
++
++#ifndef CONFIG_LIBUV_LOW_FOOTPRINT
++      if (err == UV_EMFILE || err == UV_ENFILE) {
++        err = uv__emfile_trick(loop, uv__stream_fd(stream));
++        if (err == UV_EAGAIN || err == UV__ERR(EWOULDBLOCK))
++          break;
++      }
++#endif
++
++      stream->connection_cb(stream, err);
++      continue;
++    }
++
++    UV_DEC_BACKLOG(w)
++    stream->accepted_fd = err;
++    stream->connection_cb(stream, 0);
++
++    if (stream->accepted_fd != -1) {
++      /* The user hasn't yet accepted called uv_accept() */
++      uv__io_stop(loop, &stream->io_watcher, POLLIN);
++      return;
++    }
++
++#if 0
++    if (stream->type == UV_TCP &&
++        (stream->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) {
++      /* Give other processes a chance to accept connections. */
++      struct timespec timeout = { 0, 1 };
++      nanosleep(&timeout, NULL);
++    }
++#endif
++  }
++}
++
++
++#undef UV_DEC_BACKLOG
++
++
++int uv_accept(uv_stream_t* server, uv_stream_t* client) {
++  int err;
++
++  assert(server->loop == client->loop);
++
++  if (server->accepted_fd == -1)
++    return UV_EAGAIN;
++
++  switch (client->type) {
++#if 0
++    case UV_NAMED_PIPE:
++#endif
++#ifdef CONFIG_LIBUV_TCP
++    case UV_TCP:
++      err = uv__stream_open(client,
++                            server->accepted_fd,
++                            UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
++      if (err) {
++        /* TODO handle error */
++        uv__close(server->accepted_fd);
++        goto done;
++      }
++      break;
++#endif
++#ifdef CONFIG_LIBUV_UDP
++    case UV_UDP:
++      err = uv_udp_open((uv_udp_t*) client, server->accepted_fd);
++      if (err) {
++        uv__close(server->accepted_fd);
++        goto done;
++      }
++      break;
++#endif
++
++    default:
++      return UV_EINVAL;
++  }
++
++  client->flags |= UV_HANDLE_BOUND;
++
++done:
++  /* Process queued fds */
++  if (server->queued_fds != NULL) {
++    uv__stream_queued_fds_t* queued_fds;
++
++    queued_fds = server->queued_fds;
++
++    /* Read first */
++    server->accepted_fd = queued_fds->fds[0];
++
++    /* All read, free */
++    assert(queued_fds->offset > 0);
++    if (--queued_fds->offset == 0) {
++      uv__free(queued_fds);
++      server->queued_fds = NULL;
++    } else {
++      /* Shift rest */
++      memmove(queued_fds->fds,
++              queued_fds->fds + 1,
++              queued_fds->offset * sizeof(*queued_fds->fds));
++    }
++  } else {
++    server->accepted_fd = -1;
++
++    if (err == 0)
++      uv__io_start(server->loop, &server->io_watcher, POLLIN);
++  }
++  return err;
++}
++
++
++int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {
++  int err;
++
++  switch (stream->type) {
++#ifdef CONFIG_LIBUV_TCP
++  case UV_TCP:
++    err = uv_tcp_listen((uv_tcp_t*)stream, backlog, cb);
++    break;
++#endif
++#if 0
++  case UV_NAMED_PIPE:
++    err = uv_pipe_listen((uv_pipe_t*)stream, backlog, cb);
++    break;
++#endif
++
++  default:
++    err = UV_EINVAL;
++  }
++
++  if (err == 0)
++    uv__handle_start(stream);
++
++  return err;
++}
++
++
++static void uv__drain(uv_stream_t* stream) {
++  uv_shutdown_t* req;
++  int err;
++
++  assert(QUEUE_EMPTY(&stream->write_queue));
++  uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
++
++  /* Shutdown? */
++  if ((stream->flags & UV_HANDLE_SHUTTING) &&
++      !(stream->flags & UV_HANDLE_CLOSING) &&
++      !(stream->flags & UV_HANDLE_SHUT)) {
++    assert(stream->shutdown_req);
++
++    req = stream->shutdown_req;
++    stream->shutdown_req = NULL;
++    stream->flags &= ~UV_HANDLE_SHUTTING;
++    uv__req_unregister(stream->loop, req);
++
++    err = 0;
++    if (shutdown(uv__stream_fd(stream), SHUT_WR))
++      err = UV__ERR(errno);
++
++    if (err == 0)
++      stream->flags |= UV_HANDLE_SHUT;
++
++    if (req->cb != NULL)
++      req->cb(req, err);
++  }
++}
++
++
++static ssize_t uv__writev(int fd, struct iovec* vec, size_t n) {
++  if (n == 1)
++    return write(fd, vec->iov_base, vec->iov_len);
++  else
++    return writev(fd, vec, n);
++}
++
++
++static size_t uv__write_req_size(uv_write_t* req) {
++  size_t size;
++
++  assert(req->bufs != NULL);
++  size = uv__count_bufs(req->bufs + req->write_index,
++                        req->nbufs - req->write_index);
++  assert(req->handle->write_queue_size >= size);
++
++  return size;
++}
++
++
++/* Returns 1 if all write request data has been written, or 0 if there is still
++ * more data to write.
++ *
++ * Note: the return value only says something about the *current* request.
++ * There may still be other write requests sitting in the queue.
++ */
++static int uv__write_req_update(uv_stream_t* stream,
++                                uv_write_t* req,
++                                size_t n) {
++  uv_buf_t* buf;
++  size_t len;
++
++  assert(n <= stream->write_queue_size);
++  stream->write_queue_size -= n;
++
++  buf = req->bufs + req->write_index;
++
++  do {
++    len = n < buf->len ? n : buf->len;
++    buf->base += len;
++    buf->len -= len;
++    buf += (buf->len == 0);  /* Advance to next buffer if this one is empty. */
++    n -= len;
++  } while (n > 0);
++
++  req->write_index = buf - req->bufs;
++
++  return req->write_index == req->nbufs;
++}
++
++
++static void uv__write_req_finish(uv_write_t* req) {
++  uv_stream_t* stream = req->handle;
++
++  /* Pop the req off tcp->write_queue. */
++  QUEUE_REMOVE(&req->queue);
++
++  /* Only free when there was no error. On error, we touch up write_queue_size
++   * right before making the callback. The reason we don't do that right away
++   * is that a write_queue_size > 0 is our only way to signal to the user that
++   * they should stop writing - which they should if we got an error. Something
++   * to revisit in future revisions of the libuv API.
++   */
++  if (req->error == 0) {
++    if (req->bufs != req->bufsml)
++      uv__free(req->bufs);
++    req->bufs = NULL;
++  }
++
++#if 0
++  /* Add it to the write_completed_queue where it will have its
++   * callback called in the near future.
++   */
++  QUEUE_INSERT_TAIL(&stream->write_completed_queue, &req->queue);
++  uv__io_feed(stream->loop, &stream->io_watcher);
++#else
++  QUEUE_INSERT_TAIL(&stream->write_completed_queue, &req->queue);
++  stream->io_watcher.cb(stream->loop, &stream->io_watcher, POLLOUT);
++#endif
++}
++
++#if 0
++static int uv__handle_fd(uv_handle_t* handle) {
++  switch (handle->type) {
++    case UV_NAMED_PIPE:
++    case UV_TCP:
++      return ((uv_stream_t*) handle)->io_watcher.fd;
++
++    case UV_UDP:
++      return ((uv_udp_t*) handle)->io_watcher.fd;
++
++    default:
++      return -1;
++  }
++}
++#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;
++  int err;
++
++start:
++
++  assert(uv__stream_fd(stream) >= 0);
++
++  if (QUEUE_EMPTY(&stream->write_queue))
++    return;
++
++  q = QUEUE_HEAD(&stream->write_queue);
++  req = QUEUE_DATA(q, uv_write_t, queue);
++  assert(req->handle == stream);
++
++  /*
++   * Cast to iovec. We had to have our own uv_buf_t instead of iovec
++   * because Windows's WSABUF is not an iovec.
++   */
++  assert(sizeof(uv_buf_t) == sizeof(struct iovec));
++  iov = (struct iovec*) &(req->bufs[req->write_index]);
++  iovcnt = req->nbufs - req->write_index;
++
++  iovmax = uv__getiovmax();
++
++  /* Limit iov count to avoid EINVALs from writev() */
++  if (iovcnt > iovmax)
++    iovcnt = iovmax;
++
++  /*
++   * Now do the actual writev. Note that we've been updating the pointers
++   * inside the iov each time we write. So there is no need to offset it.
++   */
++
++  do {
++    n = uv__writev(uv__stream_fd(stream), iov, iovcnt);
++  } while (n == -1 && errno == EINTR);
++
++  if (n == -1 &&
++    errno != EAGAIN &&
++    errno != EWOULDBLOCK &&
++    errno != ENOBUFS) {
++    err = UV__ERR(errno);
++    goto error;
++  }
++
++  if (n >= 0 && uv__write_req_update(stream, req, n)) {
++    uv__write_req_finish(req);
++    return;  /* TODO(bnoordhuis) Start trying to write the next request. */
++  }
++
++  /* If this is a blocking stream, try again. */
++  if (stream->flags & UV_HANDLE_BLOCKING_WRITES)
++    goto start;
++
++  /* We're not done. */
++  uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
++
++  return;
++
++error:
++  req->error = err;
++  uv__write_req_finish(req);
++  uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
++  if (!uv__io_active(&stream->io_watcher, POLLIN))
++    uv__handle_stop(stream);
++}
++
++
++static void uv__write_callbacks(uv_stream_t* stream) {
++  uv_write_t* req;
++  QUEUE* q;
++  QUEUE pq;
++
++  if (QUEUE_EMPTY(&stream->write_completed_queue))
++    return;
++
++  QUEUE_MOVE(&stream->write_completed_queue, &pq);
++
++  while (!QUEUE_EMPTY(&pq)) {
++    /* Pop a req off write_completed_queue. */
++    q = QUEUE_HEAD(&pq);
++    req = QUEUE_DATA(q, uv_write_t, queue);
++    QUEUE_REMOVE(q);
++    uv__req_unregister(stream->loop, req);
++
++    if (req->bufs != NULL) {
++      stream->write_queue_size -= uv__write_req_size(req);
++      if (req->bufs != req->bufsml)
++        uv__free(req->bufs);
++      req->bufs = NULL;
++    }
++
++    /* NOTE: call callback AFTER freeing the request data. */
++    if (req->cb)
++      req->cb(req, req->error);
++  }
++}
++
++
++uv_handle_type uv__handle_type(int fd) {
++  struct sockaddr_storage ss;
++  socklen_t sslen;
++  socklen_t len;
++  int type;
++
++  memset(&ss, 0, sizeof(ss));
++  sslen = sizeof(ss);
++
++  if (getsockname(fd, (struct sockaddr*)&ss, &sslen))
++    return UV_UNKNOWN_HANDLE;
++
++  len = sizeof type;
++
++  if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len))
++    return UV_UNKNOWN_HANDLE;
++
++  if (type == SOCK_STREAM) {
++#if defined(_AIX) || defined(__DragonFly__)
++    /* on AIX/DragonFly the getsockname call returns an empty sa structure
++     * for sockets of type AF_UNIX.  For all other types it will
++     * return a properly filled in structure.
++     */
++    if (sslen == 0)
++      return UV_NAMED_PIPE;
++#endif
++    switch (ss.ss_family) {
++      case AF_UNIX:
++        return UV_NAMED_PIPE;
++      case AF_INET:
++      case AF_INET6:
++        return UV_TCP;
++      }
++  }
++
++  if (type == SOCK_DGRAM &&
++      (ss.ss_family == AF_INET || ss.ss_family == AF_INET6))
++    return UV_UDP;
++
++  return UV_UNKNOWN_HANDLE;
++}
++
++
++static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) {
++  stream->flags |= UV_HANDLE_READ_EOF;
++  stream->flags &= ~UV_HANDLE_READING;
++  uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
++  if (!uv__io_active(&stream->io_watcher, POLLOUT))
++    uv__handle_stop(stream);
++  stream->read_cb(stream, UV_EOF, buf);
++}
++
++
++static void uv__read(uv_stream_t* stream) {
++  uv_buf_t buf;
++  ssize_t nread;
++  int count;
++
++  stream->flags &= ~UV_HANDLE_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.
++   */
++  count = 32;
++
++  /* XXX: Maybe instead of having UV_HANDLE_READING we just test if
++   * tcp->read_cb is NULL or not?
++   */
++  while (stream->read_cb
++      && (stream->flags & UV_HANDLE_READING)
++      && (count-- > 0)) {
++    assert(stream->alloc_cb != NULL);
++
++    buf = uv_buf_init(NULL, 0);
++    stream->alloc_cb((uv_handle_t*)stream, CONFIG_LIBUV_STREAM_READ_SIZE, &buf);
++    if (buf.base == NULL || buf.len == 0) {
++      /* User indicates it can't or won't handle the read. */
++      stream->read_cb(stream, UV_ENOBUFS, &buf);
++      return;
++    }
++
++    assert(buf.base != NULL);
++    assert(uv__stream_fd(stream) >= 0);
++
++    do {
++      nread = read(uv__stream_fd(stream), buf.base, buf.len);
++    }
++    while (nread < 0 && errno == EINTR);
++
++    if (nread < 0) {
++      /* Error */
++      if (errno == EAGAIN || errno == EWOULDBLOCK) {
++        /* Wait for the next one. */
++        if (stream->flags & UV_HANDLE_READING) {
++          uv__io_start(stream->loop, &stream->io_watcher, POLLIN);
++        }
++        stream->read_cb(stream, 0, &buf);
++      } else {
++        /* Error. User should call uv_close(). */
++        stream->read_cb(stream, UV__ERR(errno), &buf);
++        if (stream->flags & UV_HANDLE_READING) {
++          stream->flags &= ~UV_HANDLE_READING;
++          uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
++          if (!uv__io_active(&stream->io_watcher, POLLOUT))
++            uv__handle_stop(stream);
++        }
++      }
++      return;
++    } else if (nread == 0) {
++      uv__stream_eof(stream, &buf);
++      return;
++    } else {
++      /* Successful read */
++      ssize_t buflen = buf.len;
++
++      stream->read_cb(stream, nread, &buf);
++
++      /* Return if we didn't fill the buffer, there is no more data to read. */
++      if (nread < buflen) {
++        stream->flags |= UV_HANDLE_READ_PARTIAL;
++        return;
++      }
++    }
++  }
++}
++
++
++int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
++  assert(stream->type == UV_TCP ||
++         stream->type == UV_TTY ||
++         stream->type == UV_NAMED_PIPE);
++
++  if (!(stream->flags & UV_HANDLE_WRITABLE) ||
++      stream->flags & UV_HANDLE_SHUT ||
++      stream->flags & UV_HANDLE_SHUTTING ||
++      uv__is_closing(stream)) {
++    return UV_ENOTCONN;
++  }
++
++  assert(uv__stream_fd(stream) >= 0);
++
++  /* Initialize request */
++  uv__req_init(stream->loop, req, UV_SHUTDOWN);
++  req->handle = stream;
++  req->cb = cb;
++  stream->shutdown_req = req;
++  stream->flags |= UV_HANDLE_SHUTTING;
++
++  uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
++
++  return 0;
++}
++
++
++static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
++  uv_stream_t* stream;
++
++  stream = container_of(w, uv_stream_t, io_watcher);
++
++  assert(stream->type == UV_TCP ||
++         stream->type == UV_NAMED_PIPE ||
++         stream->type == UV_TTY);
++  assert(!(stream->flags & UV_HANDLE_CLOSING));
++
++  if (stream->connect_req) {
++    uv__stream_connect(stream);
++    return;
++  }
++
++  assert(uv__stream_fd(stream) >= 0);
++
++  /* Ignore POLLHUP here. Even if it's set, there may still be data to read. */
++  if (events & (POLLIN | POLLERR | POLLHUP))
++    uv__read(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 & POLLHUP) &&
++      (stream->flags & UV_HANDLE_READING) &&
++      (stream->flags & UV_HANDLE_READ_PARTIAL) &&
++      !(stream->flags & UV_HANDLE_READ_EOF)) {
++    uv_buf_t buf = { NULL, 0 };
++    uv__stream_eof(stream, &buf);
++  }
++
++  if (uv__stream_fd(stream) == -1)
++    return;  /* read_cb closed stream. */
++
++  if (events & (POLLOUT | POLLERR | POLLHUP)) {
++    uv__write(stream);
++    uv__write_callbacks(stream);
++
++    /* Write queue drained. */
++    if (QUEUE_EMPTY(&stream->write_queue))
++      uv__drain(stream);
++  }
++}
++
++
++/**
++ * We get called here from directly following a call to connect(2).
++ * In order to determine if we've errored out or succeeded must call
++ * getsockopt.
++ */
++static void uv__stream_connect(uv_stream_t* stream) {
++  int error;
++  uv_connect_t* req = stream->connect_req;
++  socklen_t errorsize = sizeof(int);
++
++  assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE);
++  assert(req);
++
++  /* Normal situation: we need to get the socket error from the kernel. */
++  assert(uv__stream_fd(stream) >= 0);
++  getsockopt(uv__stream_fd(stream),
++             SOL_SOCKET,
++             SO_ERROR,
++             &error,
++             &errorsize);
++  error = UV__ERR(error);
++
++  if (error == UV__ERR(EINPROGRESS))
++    return;
++
++  stream->connect_req = NULL;
++  uv__req_unregister(stream->loop, req);
++
++  if (error < 0 || QUEUE_EMPTY(&stream->write_queue)) {
++    uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
++  }
++
++  if (req->cb)
++    req->cb(req, error);
++
++  if (uv__stream_fd(stream) == -1)
++    return;
++
++  if (error < 0) {
++    uv__stream_flush_write_queue(stream, UV_ECANCELED);
++    uv__write_callbacks(stream);
++  }
++}
++
++
++int uv_write2(uv_write_t* req,
++              uv_stream_t* stream,
++              const uv_buf_t bufs[],
++              unsigned int nbufs,
++              uv_stream_t* send_handle,
++              uv_write_cb cb) {
++  int empty_queue;
++
++  assert(nbufs > 0);
++  assert((stream->type == UV_TCP ||
++          stream->type == UV_NAMED_PIPE ||
++          stream->type == UV_TTY) &&
++         "uv_write (unix) does not yet support other types of streams");
++
++  if (uv__stream_fd(stream) < 0)
++    return UV_EBADF;
++
++  if (!(stream->flags & UV_HANDLE_WRITABLE))
++    return UV_EPIPE;
++
++  /* It's legal for write_queue_size > 0 even when the write_queue is empty;
++   * it means there are error-state requests in the write_completed_queue that
++   * will touch up write_queue_size later, see also uv__write_req_finish().
++   * We could check that write_queue is empty instead but that implies making
++   * a write() syscall when we know that the handle is in error mode.
++   */
++  empty_queue = (stream->write_queue_size == 0);
++
++  /* Initialize the req */
++  uv__req_init(stream->loop, req, UV_WRITE);
++  req->cb = cb;
++  req->handle = stream;
++  req->error = 0;
++  // req->send_handle = send_handle;
++  QUEUE_INIT(&req->queue);
++
++  req->bufs = req->bufsml;
++  if (nbufs > ARRAY_SIZE(req->bufsml))
++    req->bufs = uv__malloc(nbufs * sizeof(bufs[0]));
++
++  if (req->bufs == NULL)
++    return UV_ENOMEM;
++
++  memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0]));
++  req->nbufs = nbufs;
++  req->write_index = 0;
++  stream->write_queue_size += uv__count_bufs(bufs, nbufs);
++
++  /* Append the request to write_queue. */
++  QUEUE_INSERT_TAIL(&stream->write_queue, &req->queue);
++
++  /* If the queue was empty when this function began, we should attempt to
++   * do the write immediately. Otherwise start the write_watcher and wait
++   * for the fd to become writable.
++   */
++  if (stream->connect_req) {
++    /* Still connecting, do nothing. */
++  }
++  else if (empty_queue) {
++    uv__write(stream);
++  }
++  else {
++    /*
++     * blocking streams should never have anything in the queue.
++     * if this assert fires then somehow the blocking stream isn't being
++     * sufficiently flushed in uv__write.
++     */
++    assert(!(stream->flags & UV_HANDLE_BLOCKING_WRITES));
++    uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
++  }
++
++  return 0;
++}
++
++
++/* The buffers to be written must remain valid until the callback is called.
++ * This is not required for the uv_buf_t array.
++ */
++int uv_write(uv_write_t* req,
++             uv_stream_t* handle,
++             const uv_buf_t bufs[],
++             unsigned int nbufs,
++             uv_write_cb cb) {
++  return uv_write2(req, handle, bufs, nbufs, NULL, cb);
++}
++
++
++void uv_try_write_cb(uv_write_t* req, int status) {
++  /* Should not be called */
++  abort();
++}
++
++
++int uv_try_write(uv_stream_t* stream,
++                 const uv_buf_t bufs[],
++                 unsigned int nbufs) {
++  int r;
++  int has_pollout;
++  size_t written;
++  size_t req_size;
++  uv_write_t req;
++
++  /* Connecting or already writing some data */
++  if (stream->connect_req != NULL || stream->write_queue_size != 0)
++    return UV_EAGAIN;
++
++  has_pollout = uv__io_active(&stream->io_watcher, POLLOUT);
++
++  r = uv_write(&req, stream, bufs, nbufs, uv_try_write_cb);
++  if (r != 0)
++    return r;
++
++  /* Remove not written bytes from write queue size */
++  written = uv__count_bufs(bufs, nbufs);
++  if (req.bufs != NULL)
++    req_size = uv__write_req_size(&req);
++  else
++    req_size = 0;
++  written -= req_size;
++  stream->write_queue_size -= req_size;
++
++  /* Unqueue request, regardless of immediateness */
++  QUEUE_REMOVE(&req.queue);
++  uv__req_unregister(stream->loop, &req);
++  if (req.bufs != req.bufsml)
++    uv__free(req.bufs);
++  req.bufs = NULL;
++
++  /* Do not poll for writable, if we wasn't before calling this */
++  if (!has_pollout) {
++    uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
++  }
++
++  if (written == 0 && req_size != 0)
++    return req.error < 0 ? req.error : UV_EAGAIN;
++  else
++    return written;
++}
++
++
++int uv_read_start(uv_stream_t* stream,
++                  uv_alloc_cb alloc_cb,
++                  uv_read_cb read_cb) {
++  assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE ||
++      stream->type == UV_TTY);
++
++  if (stream->flags & UV_HANDLE_CLOSING)
++    return UV_EINVAL;
++
++  if (!(stream->flags & UV_HANDLE_READABLE))
++    return UV_ENOTCONN;
++
++  /* The UV_HANDLE_READING flag is irrelevant of the state of the tcp - it just
++   * expresses the desired state of the user.
++   */
++  stream->flags |= UV_HANDLE_READING;
++
++  /* TODO: try to do the read inline? */
++  /* TODO: keep track of tcp state. If we've gotten a EOF then we should
++   * not start the IO watcher.
++   */
++  assert(uv__stream_fd(stream) >= 0);
++  assert(alloc_cb);
++
++  stream->read_cb = read_cb;
++  stream->alloc_cb = alloc_cb;
++
++  uv__io_start(stream->loop, &stream->io_watcher, POLLIN);
++  uv__handle_start(stream);
++
++  return 0;
++}
++
++
++int uv_read_stop(uv_stream_t* stream) {
++  if (!(stream->flags & UV_HANDLE_READING))
++    return 0;
++
++  stream->flags &= ~UV_HANDLE_READING;
++  uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
++  if (!uv__io_active(&stream->io_watcher, POLLOUT))
++    uv__handle_stop(stream);
++
++  stream->read_cb = NULL;
++  stream->alloc_cb = NULL;
++  return 0;
++}
++
++
++int uv_is_readable(const uv_stream_t* stream) {
++  return !!(stream->flags & UV_HANDLE_READABLE);
++}
++
++
++int uv_is_writable(const uv_stream_t* stream) {
++  return !!(stream->flags & UV_HANDLE_WRITABLE);
++}
++
++
++void uv__stream_close(uv_stream_t* handle) {
++  unsigned int i;
++  uv__stream_queued_fds_t* queued_fds;
++
++  uv__io_close(handle->loop, &handle->io_watcher);
++  uv_read_stop(handle);
++  uv__handle_stop(handle);
++  handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
++
++  if (handle->io_watcher.fd != -1) {
++    /* Don't close stdio file descriptors.  Nothing good comes from it. */
++    if (handle->io_watcher.fd > STDERR_FILENO)
++      uv__close(handle->io_watcher.fd);
++    handle->io_watcher.fd = -1;
++  }
++
++  if (handle->accepted_fd != -1) {
++    uv__close(handle->accepted_fd);
++    handle->accepted_fd = -1;
++  }
++
++  /* Close all queued fds */
++  if (handle->queued_fds != NULL) {
++    queued_fds = handle->queued_fds;
++    for (i = 0; i < queued_fds->offset; i++)
++      uv__close(queued_fds->fds[i]);
++    uv__free(handle->queued_fds);
++    handle->queued_fds = NULL;
++  }
++
++  assert(!uv__io_active(&handle->io_watcher, POLLIN | POLLOUT));
++}
++
++
++int uv_stream_set_blocking(uv_stream_t* handle, int blocking) {
++  /* Don't need to check the file descriptor, uv__nonblock()
++   * will fail with EBADF if it's not valid.
++   */
++  return uv__nonblock(uv__stream_fd(handle), !blocking);
++}
+diff --git a/src/unix/nuttx_tcp.c b/src/unix/nuttx_tcp.c
+new file mode 100644
+index 000000000..ddf4216f7
+--- /dev/null
++++ b/src/unix/nuttx_tcp.c
+@@ -0,0 +1,311 @@
++/****************************************************************************
++ * libuv/src/unix/nuttx_tcp.c
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
++/* 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 <stdlib.h>
++#include <unistd.h>
++#include <assert.h>
++#include <errno.h>
++
++static int new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
++  int sockfd;
++  int err;
++
++  err = uv__socket(domain, SOCK_STREAM, 0);
++  if (err < 0)
++    return err;
++  sockfd = err;
++
++  err = uv__stream_open((uv_stream_t*) handle, sockfd, flags);
++  if (err) {
++    uv__close(sockfd);
++    return err;
++  }
++
++  return 0;
++}
++
++int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) {
++  uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP);
++  return 0;
++}
++
++
++static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
++  if (uv__stream_fd(handle) != -1) {
++    handle->flags |= flags;
++    return 0;
++  }
++
++  return new_socket(handle, domain, flags);
++}
++
++int uv__tcp_bind(uv_tcp_t* tcp,
++                 const struct sockaddr* addr,
++                 unsigned int addrlen,
++                 unsigned int flags) {
++  int err;
++
++  err = maybe_new_socket(tcp, addr->sa_family, 0);
++  if (err)
++    return err;
++
++  errno = 0;
++  if (bind(tcp->io_watcher.fd, addr, addrlen)) {
++    return UV__ERR(errno);
++  }
++
++  tcp->flags |= UV_HANDLE_BOUND;
++
++#ifdef CONFIG_NET_IPv6
++  if (addr->sa_family == AF_INET6)
++    tcp->flags |= UV_HANDLE_IPV6;
++#endif
++
++  return 0;
++}
++
++
++int uv__tcp_connect(uv_connect_t* req,
++                    uv_tcp_t* handle,
++                    const struct sockaddr* addr,
++                    unsigned int addrlen,
++                    uv_connect_cb cb) {
++  int err;
++  int r;
++
++  assert(handle->type == UV_TCP);
++
++  if (handle->connect_req != NULL)
++    return UV_EBUSY;
++
++  err = maybe_new_socket(handle,
++                         addr->sa_family,
++                         UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
++  if (err)
++    return err;
++
++  do {
++    errno = 0;
++    r = connect(uv__stream_fd(handle), addr, addrlen);
++  } while (r < 0 && errno == EINTR);
++
++  if (r < 0) {
++    /* FIXME NuttX does not support NONBLOCKING connect,
++     * no need to check for EINPROGRESS.
++     *
++     * if (errno == EINPROGRESS) {
++     *   // This is not an error
++     * }
++     */
++    return UV__ERR(errno);
++  }
++
++  uv__req_init(handle->loop, req, UV_CONNECT);
++  req->cb = cb;
++  req->handle = (uv_stream_t*) handle;
++  QUEUE_INIT(&req->queue);
++  handle->connect_req = req;
++
++  uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
++
++  return 0;
++}
++
++#if 0
++int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
++  int err;
++
++  if (uv__fd_exists(handle->loop, sock))
++    return UV_EEXIST;
++
++  err = uv__nonblock(sock, 1);
++  if (err)
++    return err;
++
++  return uv__stream_open((uv_stream_t*)handle,
++                         sock,
++                         UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
++}
++#endif
++
++int uv_tcp_getsockname(const uv_tcp_t* handle,
++                       struct sockaddr* name,
++                       int* namelen) {
++  return uv__getsockpeername((const uv_handle_t*) handle,
++                             getsockname,
++                             name,
++                             namelen);
++}
++
++
++int uv_tcp_getpeername(const uv_tcp_t* handle,
++                       struct sockaddr* name,
++                       int* namelen) {
++  return uv__getsockpeername((const uv_handle_t*) handle,
++                             getpeername,
++                             name,
++                             namelen);
++}
++
++#if 0
++int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) {
++  int fd;
++  struct linger l = { 1, 0 };
++
++  /* Disallow setting SO_LINGER to zero due to some platform inconsistencies */
++  if (handle->flags & UV_HANDLE_SHUTTING)
++    return UV_EINVAL;
++
++  fd = uv__stream_fd(handle);
++  if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)))
++    return UV__ERR(errno);
++
++  uv_close((uv_handle_t*) handle, close_cb);
++  return 0;
++}
++#endif
++
++int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
++  unsigned long flags;
++  int err;
++
++  flags = 0;
++
++  err = maybe_new_socket(tcp, AF_INET, flags);
++  if (err)
++    return err;
++
++  if (listen(tcp->io_watcher.fd, backlog))
++    return UV__ERR(errno);
++
++  tcp->connection_cb = cb;
++  tcp->flags |= UV_HANDLE_BOUND;
++
++  /* Start listening for connections. */
++  tcp->io_watcher.cb = uv__server_io;
++  uv__io_start(tcp->loop, &tcp->io_watcher, POLLIN);
++
++  return 0;
++}
++
++#if 0
++int uv__tcp_nodelay(int fd, int on) {
++  if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)))
++    return UV__ERR(errno);
++  return 0;
++}
++
++int uv_tcp_nodelay(uv_tcp_t* handle, int on) {
++  int err;
++
++  if (uv__stream_fd(handle) != -1) {
++    err = uv__tcp_nodelay(uv__stream_fd(handle), on);
++    if (err)
++      return err;
++  }
++
++  if (on)
++    handle->flags |= UV_HANDLE_TCP_NODELAY;
++  else
++    handle->flags &= ~UV_HANDLE_TCP_NODELAY;
++
++  return 0;
++}
++#endif
++
++#ifdef CONFIG_NET_TCP_KEEPALIVE
++int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
++  if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
++    return UV__ERR(errno);
++
++#ifdef TCP_KEEPIDLE
++  if (on) {
++    int intvl = 1;  /*  1 second; same as default on Win32 */
++    int cnt = 10;  /* 10 retries; same as hardcoded on Win32 */
++    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
++      return UV__ERR(errno);
++    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
++      return UV__ERR(errno);
++    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)))
++      return UV__ERR(errno);
++  }
++#endif
++
++  /* Solaris/SmartOS, if you don't support keep-alive,
++   * then don't advertise it in your system headers...
++   */
++  /* FIXME(bnoordhuis) That's possibly because sizeof(delay) should be 1. */
++#if defined(TCP_KEEPALIVE) && !defined(__sun)
++  if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
++    return UV__ERR(errno);
++#endif
++
++  return 0;
++}
++
++int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {
++  int err;
++
++  if (uv__stream_fd(handle) != -1) {
++    err =uv__tcp_keepalive(uv__stream_fd(handle), on, delay);
++    if (err)
++      return err;
++  }
++
++  if (on)
++    handle->flags |= UV_HANDLE_TCP_KEEPALIVE;
++  else
++    handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;
++
++  /* TODO Store delay if uv__stream_fd(handle) == -1 but don't want to enlarge
++   *      uv_tcp_t with an int that's almost never used...
++   */
++
++  return 0;
++}
++#endif /* CONFIG_NET_TCP_KEEPALIVE */
++
++void uv__tcp_close(uv_tcp_t* handle) {
++  uv__stream_close((uv_stream_t*)handle);
++}
+diff --git a/src/unix/nuttx_threadpool.c b/src/unix/nuttx_threadpool.c
+new file mode 100644
+index 000000000..ae509db11
+--- /dev/null
++++ b/src/unix/nuttx_threadpool.c
+@@ -0,0 +1,361 @@
++/****************************************************************************
++ * libuv/src/unix/nuttx_threadpool.c
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
++/* 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-common.h"
++# include "unix/internal.h"
++
++#include <stdlib.h>
++
++#ifdef CONFIG_LIBUV_CONTEXT
++typedef struct worker_priv_s {
++  uv_sem_t sem;
++  uv_wq_context_t *ctx;
++} worker_priv_t;
++#else
++static uv_wq_context_t wq_ctx = {
++  .once = UV_ONCE_INIT;
++};
++#endif
++
++static void uv__cancelled(struct uv__work* w) {
++  abort();
++}
++
++
++/* To avoid deadlock with uv_cancel() it's crucial that the worker
++ * never holds the global mutex and the loop-local mutex at the same time.
++ */
++static void worker(void* arg) {
++  struct uv__work* w;
++  QUEUE* q;
++
++#ifdef CONFIG_LIBUV_CONTEXT
++  uv_wq_context_t *ctx = ((volatile worker_priv_t*)arg)->ctx;
++  uv_sem_post(&((worker_priv_t*) arg)->sem);
++#else
++  uv_wq_context_t *ctx = &wq_ctx;
++  uv_sem_post((uv_sem_t*) arg);
++#endif
++
++  arg = NULL;
++
++  uv_mutex_lock(&ctx->mutex);
++  for (;;) {
++    /* `mutex` should always be locked at this point. */
++
++    /* Keep waiting while either no work is present or only slow I/O
++       and we're at the threshold for that. */
++    while (QUEUE_EMPTY(&ctx->wq)) {
++      ctx->idle_threads += 1;
++      uv_cond_wait(&ctx->cond, &ctx->mutex);
++      ctx->idle_threads -= 1;
++    }
++
++    q = QUEUE_HEAD(&ctx->wq);
++    if (q == &ctx->exit_message) {
++      uv_cond_signal(&ctx->cond);
++      uv_mutex_unlock(&ctx->mutex);
++      break;
++    }
++
++    QUEUE_REMOVE(q);
++    QUEUE_INIT(q);  /* Signal uv_cancel() that the work req is executing. */
++
++    uv_mutex_unlock(&ctx->mutex);
++
++    w = QUEUE_DATA(q, struct uv__work, wq);
++    w->work(w);
++
++    uv_mutex_lock(&w->loop->wq_mutex);
++    w->work = NULL;  /* Signal uv_cancel() that the work req is done
++                        executing. */
++    QUEUE_INSERT_TAIL(&w->loop->wq, &w->wq);
++    uv_async_send(&w->loop->wq_async);
++    uv_mutex_unlock(&w->loop->wq_mutex);
++
++    /* Lock `mutex` since that is expected at the start of the next
++     * iteration. */
++    uv_mutex_lock(&ctx->mutex);
++  }
++}
++
++#ifdef CONFIG_LIBUV_CONTEXT
++static void post(QUEUE* q, enum uv__work_kind kind,
++  uv_wq_context_t *ctx) {
++#else
++static void post(QUEUE* q, enum uv__work_kind kind) {
++  uv_wq_context_t *ctx = &wq_ctx;
++#endif
++  uv_mutex_lock(&ctx->mutex);
++  QUEUE_INSERT_TAIL(&ctx->wq, q);
++  if (ctx->idle_threads > 0)
++    uv_cond_signal(&ctx->cond);
++  uv_mutex_unlock(&ctx->mutex);
++}
++
++
++#ifdef CONFIG_LIBUV_CONTEXT
++static void init_threads(uv_wq_context_t *ctx) {
++  worker_priv_t worker_priv;
++  uv_sem_t *psem = &worker_priv.sem;
++#else
++static void init_threads(void) {
++  uv_wq_context_t *ctx = &wq_ctx;
++  uv_sem_t sem;
++  uv_sem_t *psem = &sem;
++#endif
++  unsigned int i;
++
++  if (uv_cond_init(&ctx->cond))
++    abort();
++
++  if (uv_mutex_init(&ctx->mutex))
++    abort();
++
++  QUEUE_INIT(&ctx->wq);
++
++#ifdef CONFIG_LIBUV_CONTEXT
++  worker_priv.ctx = ctx;
++#endif
++
++  if (uv_sem_init(psem, 0))
++    abort();
++
++  for (i = 0; i < ARRAY_SIZE(ctx->default_threads); i++)
++#ifdef CONFIG_LIBUV_CONTEXT
++    if (uv_thread_create(ctx->default_threads + i, worker, &worker_priv))
++#else
++    if (uv_thread_create(ctx->default_threads + i, worker, &sem))
++#endif
++      abort();
++
++  for (i = 0; i < ARRAY_SIZE(ctx->default_threads); i++)
++    uv_sem_wait(psem);
++
++  uv_sem_destroy(psem);
++}
++
++#ifndef CONFIG_LIBUV_CONTEXT
++static void init_once(void) {
++  init_threads();
++}
++#endif
++
++
++#ifdef CONFIG_LIBUV_CONTEXT
++void uv__threadpool_setup(uv_context_t *context) {
++  init_threads(&context->wq);
++}
++
++void uv__threadpool_cleanup(uv_context_t *context) {
++  unsigned int i;
++  uv_wq_context_t *ctx = &context->wq;
++#else
++void uv__threadpool_cleanup(void) {
++  uv_wq_context_t *ctx = &wq_ctx;
++  unsigned int i;
++
++  if (!ctx->once) {
++    /* Threads not initialized */
++    return;
++  }
++#endif
++
++  post(&ctx->exit_message, UV__WORK_CPU
++#ifdef CONFIG_LIBUV_CONTEXT
++    , ctx
++#endif
++    );
++
++  for (i = 0; i < ARRAY_SIZE(ctx->default_threads); i++)
++    if (uv_thread_join(ctx->default_threads + i))
++      abort();
++
++  uv_mutex_destroy(&ctx->mutex);
++  uv_cond_destroy(&ctx->cond);
++}
++
++
++void uv__work_submit(uv_loop_t* loop,
++                     struct uv__work* w,
++                     enum uv__work_kind kind,
++                     void (*work)(struct uv__work* w),
++                     void (*done)(struct uv__work* w, int status)) {
++#ifndef CONFIG_LIBUV_CONTEXT
++  uv_once(&once, init_once);
++#endif
++  w->loop = loop;
++  w->work = work;
++  w->done = done;
++  post(&w->wq, kind
++#ifdef CONFIG_LIBUV_CONTEXT
++    , &loop->context->wq
++#endif
++    );
++}
++
++
++static int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) {
++  int cancelled;
++
++#ifdef CONFIG_LIBUV_CONTEXT
++  uv_wq_context_t *ctx = &loop->context->wq;
++#else
++  uv_wq_context_t *ctx = &wq_ctx;
++#endif
++
++  uv_mutex_lock(&ctx->mutex);
++  uv_mutex_lock(&w->loop->wq_mutex);
++
++  cancelled = !QUEUE_EMPTY(&w->wq) && w->work != NULL;
++  if (cancelled)
++    QUEUE_REMOVE(&w->wq);
++
++  uv_mutex_unlock(&w->loop->wq_mutex);
++  uv_mutex_unlock(&ctx->mutex);
++
++  if (!cancelled)
++    return UV_EBUSY;
++
++  w->work = uv__cancelled;
++  uv_mutex_lock(&loop->wq_mutex);
++  QUEUE_INSERT_TAIL(&loop->wq, &w->wq);
++  uv_async_send(&loop->wq_async);
++  uv_mutex_unlock(&loop->wq_mutex);
++
++  return 0;
++}
++
++
++void uv__work_done(uv_async_t* handle) {
++  struct uv__work* w;
++  uv_loop_t* loop;
++  QUEUE* q;
++  QUEUE wql;
++  int err;
++
++  loop = container_of(handle, uv_loop_t, wq_async);
++  uv_mutex_lock(&loop->wq_mutex);
++  QUEUE_MOVE(&loop->wq, &wql);
++  uv_mutex_unlock(&loop->wq_mutex);
++
++  while (!QUEUE_EMPTY(&wql)) {
++    q = QUEUE_HEAD(&wql);
++    QUEUE_REMOVE(q);
++
++    w = container_of(q, struct uv__work, wq);
++    err = (w->work == uv__cancelled) ? UV_ECANCELED : 0;
++    w->done(w, err);
++  }
++}
++
++
++static void uv__queue_work(struct uv__work* w) {
++  uv_work_t* req = container_of(w, uv_work_t, work_req);
++
++  req->work_cb(req);
++}
++
++
++static void uv__queue_done(struct uv__work* w, int err) {
++  uv_work_t* req;
++
++  req = container_of(w, uv_work_t, work_req);
++  uv__req_unregister(req->loop, req);
++
++  if (req->after_work_cb == NULL)
++    return;
++
++  req->after_work_cb(req, err);
++}
++
++
++int uv_queue_work(uv_loop_t* loop,
++                  uv_work_t* req,
++                  uv_work_cb work_cb,
++                  uv_after_work_cb after_work_cb) {
++  if (work_cb == NULL)
++    return UV_EINVAL;
++
++  uv__req_init(loop, req, UV_WORK);
++  req->loop = loop;
++  req->work_cb = work_cb;
++  req->after_work_cb = after_work_cb;
++  uv__work_submit(loop,
++                  &req->work_req,
++                  UV__WORK_CPU,
++                  uv__queue_work,
++                  uv__queue_done);
++  return 0;
++}
++
++
++int uv_cancel(uv_req_t* req) {
++  struct uv__work* wreq;
++  uv_loop_t* loop;
++
++  switch (req->type) {
++  case UV_FS:
++    loop =  ((uv_fs_t*) req)->loop;
++    wreq = &((uv_fs_t*) req)->work_req;
++    break;
++  case UV_GETADDRINFO:
++    loop =  ((uv_getaddrinfo_t*) req)->loop;
++    wreq = &((uv_getaddrinfo_t*) req)->work_req;
++    break;
++  case UV_GETNAMEINFO:
++    loop = ((uv_getnameinfo_t*) req)->loop;
++    wreq = &((uv_getnameinfo_t*) req)->work_req;
++    break;
++  case UV_RANDOM:
++    loop = ((uv_random_t*) req)->loop;
++    wreq = &((uv_random_t*) req)->work_req;
++    break;
++  case UV_WORK:
++    loop =  ((uv_work_t*) req)->loop;
++    wreq = &((uv_work_t*) req)->work_req;
++    break;
++  default:
++    return UV_EINVAL;
++  }
++
++  return uv__work_cancel(loop, req, wreq);
++}
+diff --git a/src/unix/nuttx_timer.c b/src/unix/nuttx_timer.c
+new file mode 100644
+index 000000000..d56fdc287
+--- /dev/null
++++ b/src/unix/nuttx_timer.c
+@@ -0,0 +1,199 @@
++/****************************************************************************
++ * libuv/src/unix/nuttx_timer.c
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
++#include "uv.h"
++#include "uv-common.h"
++
++#include <assert.h>
++#include <stdlib.h>
++
++int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {
++  uv__handle_init(loop, (uv_handle_t*)handle, UV_TIMER);
++  handle->timer_cb = NULL;
++  handle->repeat = 0;
++  return 0;
++}
++
++
++int uv_timer_start(uv_timer_t* handle,
++                   uv_timer_cb cb,
++                   int32_t timeout,
++                   int32_t repeat) {
++  if (uv__is_closing(handle) || cb == NULL)
++    return UV_EINVAL;
++
++  if (timeout < 0 || repeat < 0) {
++    return UV_EINVAL;
++  }
++
++  if (uv__is_active(handle))
++    uv_timer_stop(handle);
++
++  handle->timer_cb = cb;
++  handle->timeout = (uint32_t)handle->loop->time + (uint32_t)timeout;
++  handle->repeat = repeat;
++
++  uv_timer_t *cur_timer = handle->loop->timer_head;
++
++  /* If a timer has the same timeout, insert after to preserve timer order */
++
++  if (cur_timer == NULL ||
++    timeout < (int32_t)(cur_timer->timeout-(uint32_t)handle->loop->time)) {
++    handle->next = cur_timer;
++    handle->loop->timer_head = handle;
++    goto exit_start_handle;
++  }
++
++  /* Insert anywhere in timer list */
++  for (;; cur_timer = cur_timer->next) {
++    if (cur_timer->next == NULL) {
++      handle->next = NULL;
++      cur_timer->next = handle;
++      goto exit_start_handle;
++    }
++
++    int32_t expiration =
++      (int32_t)(cur_timer->next->timeout-(uint32_t)handle->loop->time);
++
++    if (timeout < expiration) {
++      handle->next = cur_timer->next;
++      cur_timer->next = handle;
++      goto exit_start_handle;
++    }
++  }
++
++exit_start_handle:
++  uv__handle_start(handle);
++
++  return 0;
++}
++
++
++int uv_timer_stop(uv_timer_t* handle) {
++  if (!uv__is_active(handle))
++    return 0;
++
++  uv_timer_t *cur_timer = handle->loop->timer_head;
++
++  /* Remove if handle is in timer list head */
++  if (cur_timer == handle) {
++    handle->loop->timer_head = cur_timer->next;
++    goto exit_stop_handle;
++  }
++
++  /* Remove anywhere in timer list */
++  for (;; cur_timer = cur_timer->next) {
++    if (cur_timer->next == NULL) {
++      abort();
++    }
++
++    if (cur_timer->next == handle) {
++      cur_timer->next = handle->next;
++      goto exit_stop_handle;
++    }
++  }
++
++exit_stop_handle:
++  uv__handle_stop(handle);
++
++  return 0;
++}
++
++
++int uv_timer_again(uv_timer_t* handle) {
++  if (handle->timer_cb == NULL)
++    return UV_EINVAL;
++
++  if (handle->repeat) {
++    uv_timer_stop(handle);
++    uv_timer_start(handle, handle->timer_cb, handle->repeat, handle->repeat);
++  }
++
++  return 0;
++}
++
++
++void uv_timer_set_repeat(uv_timer_t* handle, int32_t repeat) {
++  handle->repeat = repeat;
++}
++
++
++int32_t uv_timer_get_repeat(const uv_timer_t* handle) {
++  return handle->repeat;
++}
++
++
++int uv__next_timeout(const uv_loop_t* loop) {
++  if (loop->timer_head == NULL) {
++    return -1; /* block indefinitely */
++  }
++
++  int32_t expiration =
++    (int32_t)(loop->timer_head->timeout-(uint32_t)loop->time);
++
++  if (expiration <= 0) {
++    return 0;
++  }
++
++  return expiration;
++}
++
++
++void uv__run_timers(uv_loop_t* loop) {
++  uv_timer_t* handle;
++
++  for (;;) {
++    handle = loop->timer_head;
++
++    if (handle == NULL) {
++      break;
++    }
++
++    int32_t expiration =
++      (int32_t)(handle->timeout-(uint32_t)loop->time);
++
++    if (expiration > 0) {
++      break;
++    }
++
++    uv_timer_stop(handle);
++
++    if (handle->repeat) {
++      uv_interval_t new_timeout;
++      if (handle->repeat+expiration <= 0) {
++        new_timeout = 0;
++      }
++      else {
++        new_timeout = handle->repeat+expiration;
++      }
++      uv_timer_start(handle,
++        handle->timer_cb,
++        new_timeout,
++        handle->repeat);
++    }
++
++    handle->timer_cb(handle);
++  }
++}
++
++
++void uv__timer_close(uv_timer_t* handle) {
++  uv_timer_stop(handle);
++}
+diff --git a/src/unix/poll.c b/src/unix/poll.c
+index 3d5022b22..d2f442132 100644
+--- a/src/unix/poll.c
++++ b/src/unix/poll.c
+@@ -1,3 +1,23 @@
++/****************************************************************************
++ * src/unix/poll.c
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+@@ -75,6 +95,11 @@ int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
+   if (err)
+     return err;
+ 
++#ifdef __NUTTX__
++  err = uv__nonblock(fd, 1);
++  if (err)
++    return err;
++#else
+   /* If ioctl(FIONBIO) reports ENOTTY, try fcntl(F_GETFL) + fcntl(F_SETFL).
+    * Workaround for e.g. kqueue fds not supporting ioctls.
+    */
+@@ -85,6 +110,7 @@ int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
+ 
+   if (err)
+     return err;
++#endif
+ 
+   uv__handle_init(loop, (uv_handle_t*) handle, UV_POLL);
+   uv__io_init(&handle->io_watcher, uv__poll_io, fd);
+diff --git a/src/unix/process.c b/src/unix/process.c
+index b021aaeba..7abed9f0f 100644
+--- a/src/unix/process.c
++++ b/src/unix/process.c
+@@ -1,3 +1,23 @@
++/****************************************************************************
++ * src/unix/process.c
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+@@ -111,7 +131,7 @@ static void uv__chld(uv_signal_t* handle, int signum) {
+   assert(QUEUE_EMPTY(&pending));
+ }
+ 
+-
++#if 0
+ static int uv__make_socketpair(int fds[2]) {
+ #if defined(__FreeBSD__) || defined(__linux__)
+   if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds))
+@@ -137,7 +157,7 @@ static int uv__make_socketpair(int fds[2]) {
+   return 0;
+ #endif
+ }
+-
++#endif
+ 
+ int uv__make_pipe(int fds[2], int flags) {
+ #if defined(__FreeBSD__) || defined(__linux__)
+@@ -172,7 +192,7 @@ fail:
+ #endif
+ }
+ 
+-
++#if 0
+ /*
+  * Used for initializing stdio streams like options.stdin_stream. Returns
+  * zero on success. See also the cleanup section in uv_spawn().
+@@ -243,7 +263,7 @@ static void uv__process_close_stream(uv_stdio_container_t* container) {
+   if (!(container->flags & UV_CREATE_PIPE)) return;
+   uv__stream_close(container->data.stream);
+ }
+-
++#endif
+ 
+ static void uv__write_int(int fd, int val) {
+   ssize_t n;
+@@ -259,7 +279,8 @@ static void uv__write_int(int fd, int val) {
+ }
+ 
+ 
+-#if !(defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH))
++#if !(defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)) \
++ && !defined(__NUTTX__)
+ /* execvp is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED, so must be
+  * avoided. Since this isn't called on those targets, the function
+  * doesn't even need to be defined for them.
+@@ -404,7 +425,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
+ }
+ #endif
+ 
+-
++#if 0
+ int uv_spawn(uv_loop_t* loop,
+              uv_process_t* process,
+              const uv_process_options_t* options) {
+@@ -572,7 +593,7 @@ error:
+   return err;
+ #endif
+ }
+-
++#endif
+ 
+ int uv_process_kill(uv_process_t* process, int signum) {
+   return uv_kill(process->pid, signum);
+diff --git a/src/unix/random-devurandom.c b/src/unix/random-devurandom.c
+index 05e52a56a..dd6f5c438 100644
+--- a/src/unix/random-devurandom.c
++++ b/src/unix/random-devurandom.c
+@@ -25,16 +25,23 @@
+ #include <sys/stat.h>
+ #include <unistd.h>
+ 
++#ifndef __NUTTX__
+ static uv_once_t once = UV_ONCE_INIT;
+ static int status;
+-
++#endif
+ 
+ int uv__random_readpath(const char* path, void* buf, size_t buflen) {
+-  struct stat s;
+   size_t pos;
+   ssize_t n;
+   int fd;
+ 
++#ifdef __NUTTX__
++  fd = open(path, O_RDONLY);
++  if (fd < 0)
++    return fd;
++#else
++  struct stat s;
++
+   fd = uv__open_cloexec(path, O_RDONLY);
+ 
+   if (fd < 0)
+@@ -49,6 +56,7 @@ int uv__random_readpath(const char* path, void* buf, size_t buflen) {
+     uv__close(fd);
+     return UV_EIO;
+   }
++#endif
+ 
+   for (pos = 0; pos != buflen; pos += n) {
+     do
+@@ -70,7 +78,7 @@ int uv__random_readpath(const char* path, void* buf, size_t buflen) {
+   return 0;
+ }
+ 
+-
++#ifndef __NUTTX__
+ static void uv__random_devurandom_init(void) {
+   char c;
+ 
+@@ -81,13 +89,14 @@ static void uv__random_devurandom_init(void) {
+    */
+   status = uv__random_readpath("/dev/random", &c, 1);
+ }
+-
++#endif
+ 
+ int uv__random_devurandom(void* buf, size_t buflen) {
++#ifndef __NUTTX__
+   uv_once(&once, uv__random_devurandom_init);
+ 
+   if (status != 0)
+     return status;
+-
++#endif
+   return uv__random_readpath("/dev/urandom", buf, buflen);
+ }
+diff --git a/src/unix/thread.c b/src/unix/thread.c
+index 1a85d1d4f..479a20b90 100644
+--- a/src/unix/thread.c
++++ b/src/unix/thread.c
+@@ -1,3 +1,23 @@
++/****************************************************************************
++ * src/unix/thread.c
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+@@ -161,7 +181,7 @@ void uv_barrier_destroy(uv_barrier_t* barrier) {
+ 
+ #endif
+ 
+-
++#if 0
+ /* On MacOS, threads other than the main thread are created with a reduced
+  * stack size by default.  Adjust to RLIMIT_STACK aligned to the page size.
+  *
+@@ -205,14 +225,19 @@ static size_t thread_stack_size(void) {
+   return 2 << 20;  /* glibc default. */
+ #endif
+ }
+-
++#endif
+ 
+ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
++#ifdef __NUTTX__
++  return pthread_create(tid, NULL, (pthread_startroutine_t)entry, arg);
++#else
+   uv_thread_options_t params;
+   params.flags = UV_THREAD_NO_FLAGS;
+   return uv_thread_create_ex(tid, &params, entry, arg);
++#endif
+ }
+ 
++#if 0
+ int uv_thread_create_ex(uv_thread_t* tid,
+                         const uv_thread_options_t* params,
+                         void (*entry)(void *arg),
+@@ -263,7 +288,7 @@ int uv_thread_create_ex(uv_thread_t* tid,
+ 
+   return UV__ERR(err);
+ }
+-
++#endif
+ 
+ uv_thread_t uv_thread_self(void) {
+   return pthread_self();
+@@ -280,7 +305,7 @@ int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) {
+ 
+ 
+ int uv_mutex_init(uv_mutex_t* mutex) {
+-#if defined(NDEBUG) || !defined(PTHREAD_MUTEX_ERRORCHECK)
++#if defined(NDEBUG) || !defined(PTHREAD_MUTEX_ERRORCHECK) || defined(__NUTTX__)
+   return UV__ERR(pthread_mutex_init(mutex, NULL));
+ #else
+   pthread_mutexattr_t attr;
+@@ -709,9 +734,11 @@ int uv_cond_init(uv_cond_t* cond) {
+   if (err)
+     return UV__ERR(err);
+ 
++#ifndef __NUTTX__
+   err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
+   if (err)
+     goto error2;
++#endif
+ 
+   err = pthread_cond_init(cond, &attr);
+   if (err)
+diff --git a/src/uv-common.c b/src/uv-common.c
+index 0cfb921e6..6eaee4902 100644
+--- a/src/uv-common.c
++++ b/src/uv-common.c
+@@ -1,3 +1,23 @@
++/****************************************************************************
++ * src/uv-common.c
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+@@ -217,7 +237,8 @@ const char* uv_strerror(int err) {
+ }
+ #undef UV_STRERROR_GEN
+ 
+-
++#ifdef CONFIG_LIBUV_TCP
++#ifdef CONFIG_NET_IPv4
+ int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr) {
+   memset(addr, 0, sizeof(*addr));
+   addr->sin_family = AF_INET;
+@@ -228,7 +249,12 @@ int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr) {
+   return uv_inet_pton(AF_INET, ip, &(addr->sin_addr.s_addr));
+ }
+ 
++int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size) {
++  return uv_inet_ntop(AF_INET, &src->sin_addr, dst, size);
++}
++#endif
+ 
++#ifdef CONFIG_NET_IPv6
+ int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) {
+   char address_part[40];
+   size_t address_part_size;
+@@ -263,16 +289,10 @@ int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) {
+   return uv_inet_pton(AF_INET6, ip, &addr->sin6_addr);
+ }
+ 
+-
+-int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size) {
+-  return uv_inet_ntop(AF_INET, &src->sin_addr, dst, size);
+-}
+-
+-
+ int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size) {
+   return uv_inet_ntop(AF_INET6, &src->sin6_addr, dst, size);
+ }
+-
++#endif
+ 
+ int uv_tcp_bind(uv_tcp_t* handle,
+                 const struct sockaddr* addr,
+@@ -282,17 +302,48 @@ int uv_tcp_bind(uv_tcp_t* handle,
+   if (handle->type != UV_TCP)
+     return UV_EINVAL;
+ 
++#ifdef CONFIG_NET_IPv4
+   if (addr->sa_family == AF_INET)
+     addrlen = sizeof(struct sockaddr_in);
+-  else if (addr->sa_family == AF_INET6)
++  else
++#endif
++#ifdef CONFIG_NET_IPv6
++  if (addr->sa_family == AF_INET6)
+     addrlen = sizeof(struct sockaddr_in6);
+   else
++#endif
+     return UV_EINVAL;
+ 
+   return uv__tcp_bind(handle, addr, addrlen, flags);
+ }
+ 
+ 
++int uv_tcp_connect(uv_connect_t* req,
++                   uv_tcp_t* handle,
++                   const struct sockaddr* addr,
++                   uv_connect_cb cb) {
++  unsigned int addrlen;
++
++  if (handle->type != UV_TCP)
++    return UV_EINVAL;
++
++#ifdef CONFIG_NET_IPv4
++  if (addr->sa_family == AF_INET)
++    addrlen = sizeof(struct sockaddr_in);
++  else
++#endif
++#ifdef CONFIG_NET_IPv6
++  if (addr->sa_family == AF_INET6)
++    addrlen = sizeof(struct sockaddr_in6);
++  else
++#endif
++    return UV_EINVAL;
++
++  return uv__tcp_connect(req, handle, addr, addrlen, cb);
++}
++#endif /* CONFIG_LIBUV_TCP */
++
++#ifdef CONFIG_LIBUV_UDP
+ int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned flags) {
+   unsigned extra_flags;
+   int domain;
+@@ -342,26 +393,6 @@ int uv_udp_bind(uv_udp_t* handle,
+ }
+ 
+ 
+-int uv_tcp_connect(uv_connect_t* req,
+-                   uv_tcp_t* handle,
+-                   const struct sockaddr* addr,
+-                   uv_connect_cb cb) {
+-  unsigned int addrlen;
+-
+-  if (handle->type != UV_TCP)
+-    return UV_EINVAL;
+-
+-  if (addr->sa_family == AF_INET)
+-    addrlen = sizeof(struct sockaddr_in);
+-  else if (addr->sa_family == AF_INET6)
+-    addrlen = sizeof(struct sockaddr_in6);
+-  else
+-    return UV_EINVAL;
+-
+-  return uv__tcp_connect(req, handle, addr, addrlen, cb);
+-}
+-
+-
+ int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr) {
+   unsigned int addrlen;
+ 
+@@ -481,7 +512,7 @@ int uv_udp_recv_stop(uv_udp_t* handle) {
+   else
+     return uv__udp_recv_stop(handle);
+ }
+-
++#endif
+ 
+ void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) {
+   QUEUE queue;
+@@ -507,8 +538,12 @@ static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) {
+   QUEUE* q;
+   uv_handle_t* h;
+ 
++#ifdef CONFIG_LIBUV_CONTEXT
++  assert(loop != NULL);
++#else
+   if (loop == NULL)
+     loop = uv_default_loop();
++#endif
+ 
+   QUEUE_FOREACH(q, &loop->handle_queue) {
+     h = QUEUE_DATA(q, uv_handle_t, handle_queue);
+@@ -564,7 +599,7 @@ void uv_stop(uv_loop_t* loop) {
+ }
+ 
+ 
+-uint64_t uv_now(const uv_loop_t* loop) {
++uv_time_t uv_now(const uv_loop_t* loop) {
+   return loop->time;
+ }
+ 
+@@ -581,6 +616,7 @@ size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs) {
+   return bytes;
+ }
+ 
++#if 0
+ int uv_recv_buffer_size(uv_handle_t* handle, int* value) {
+   return uv__socket_sockopt(handle, SO_RCVBUF, value);
+ }
+@@ -588,6 +624,7 @@ int uv_recv_buffer_size(uv_handle_t* handle, int* value) {
+ int uv_send_buffer_size(uv_handle_t* handle, int *value) {
+   return uv__socket_sockopt(handle, SO_SNDBUF, value);
+ }
++#endif
+ 
+ int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) {
+   size_t required_len;
+@@ -742,7 +779,7 @@ void uv__fs_readdir_cleanup(uv_fs_t* req) {
+   }
+ }
+ 
+-
++#if 0
+ int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) {
+   va_list ap;
+   int err;
+@@ -754,7 +791,22 @@ int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) {
+ 
+   return err;
+ }
++#endif
++
++#ifdef CONFIG_LIBUV_CONTEXT
++
++uv_loop_t* uv_default_loop(uv_context_t *ctx) {
++  if (ctx->default_loop_ptr != NULL)
++    return ctx->default_loop_ptr;
+ 
++  if (uv_loop_init(&ctx->default_loop, ctx))
++    return NULL;
++
++  ctx->default_loop_ptr = &ctx->default_loop;
++  return ctx->default_loop_ptr;
++}
++
++#else /* CONFIG_LIBUV_CONTEXT */
+ 
+ static uv_loop_t default_loop_struct;
+ static uv_loop_t* default_loop_ptr;
+@@ -770,16 +822,24 @@ uv_loop_t* uv_default_loop(void) {
+   default_loop_ptr = &default_loop_struct;
+   return default_loop_ptr;
+ }
++#endif /* CONFIG_LIBUV_CONTEXT */
+ 
+-
++#ifdef CONFIG_LIBUV_CONTEXT
++uv_loop_t* uv_loop_new(uv_context_t *ctx) {
++#else
+ uv_loop_t* uv_loop_new(void) {
++#endif
+   uv_loop_t* loop;
+ 
+   loop = uv__malloc(sizeof(*loop));
+   if (loop == NULL)
+     return NULL;
+ 
++#ifdef CONFIG_LIBUV_CONTEXT
++  if (uv_loop_init(loop, ctx)) {
++#else
+   if (uv_loop_init(loop)) {
++#endif
+     uv__free(loop);
+     return NULL;
+   }
+@@ -806,13 +866,19 @@ int uv_loop_close(uv_loop_t* loop) {
+ 
+   uv__loop_close(loop);
+ 
++#ifdef CONFIG_LIBUV_CONTEXT
++  if (loop == loop->context->default_loop_ptr)
++    loop->context->default_loop_ptr = NULL;
++#else
++  if (loop == default_loop_ptr)
++    default_loop_ptr = NULL;
++#endif
++
+ #ifndef NDEBUG
+   saved_data = loop->data;
+   memset(loop, -1, sizeof(*loop));
+   loop->data = saved_data;
+ #endif
+-  if (loop == default_loop_ptr)
+-    default_loop_ptr = NULL;
+ 
+   return 0;
+ }
+@@ -822,7 +888,11 @@ void uv_loop_delete(uv_loop_t* loop) {
+   uv_loop_t* default_loop;
+   int err;
+ 
++#ifdef CONFIG_LIBUV_CONTEXT
++  default_loop = loop->context->default_loop_ptr;
++#else
+   default_loop = default_loop_ptr;
++#endif
+ 
+   err = uv_loop_close(loop);
+   (void) err;    /* Squelch compiler warnings. */
+@@ -852,18 +922,51 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
+   uv__free(cpu_infos);
+ }
+ 
++#ifdef CONFIG_LIBUV_CONTEXT
++void uv_library_init(uv_context_t *ctx) {
++  memset(ctx, 0, sizeof(*ctx));
++  uv__process_title_setup(ctx);
++
++#ifdef CONFIG_LIBUV_SIGNAL
++  uv__signal_setup(ctx);
++#endif
++
++#ifdef CONFIG_LIBUV_WQ
++  uv__threadpool_setup(ctx);
++#endif
++}
++
++void uv_library_shutdown(uv_context_t *ctx) {
++  uv__process_title_cleanup(ctx);
++
++#ifdef CONFIG_LIBUV_SIGNAL
++  uv__signal_cleanup(ctx);
++#endif
++
++#ifdef CONFIG_LIBUV_WQ
++  uv__threadpool_cleanup(ctx);
++#endif
++}
++
++#else /* CONFIG_LIBUV_CONTEXT */
+ 
+ #ifdef __GNUC__  /* Also covers __clang__ and __INTEL_COMPILER. */
+ __attribute__((destructor))
+ #endif
+ void uv_library_shutdown(void) {
+   static int was_shutdown;
+-
+   if (uv__load_relaxed(&was_shutdown))
+     return;
+ 
+   uv__process_title_cleanup();
++#ifdef CONFIG_LIBUV_SIGNAL
+   uv__signal_cleanup();
++#endif
++
++#ifdef CONFIG_LIBUV_WQ
+   uv__threadpool_cleanup();
++#endif
++
+   uv__store_relaxed(&was_shutdown, 1);
+ }
++#endif /* CONFIG_LIBUV_CONTEXT */
+\ No newline at end of file
+diff --git a/src/uv-common.h b/src/uv-common.h
+index 063588eac..9a436c0fd 100644
+--- a/src/uv-common.h
++++ b/src/uv-common.h
+@@ -1,3 +1,23 @@
++/****************************************************************************
++ * src/uv-common.h
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+@@ -214,9 +234,20 @@ int uv__next_timeout(const uv_loop_t* loop);
+ void uv__run_timers(uv_loop_t* loop);
+ void uv__timer_close(uv_timer_t* handle);
+ 
++#ifdef CONFIG_LIBUV_CONTEXT
++void uv__process_title_setup(uv_context_t *ctx);
++void uv__signal_setup(uv_context_t *ctx);
++void uv__threadpool_setup(uv_context_t *ctx);
++
++void uv__process_title_cleanup(uv_context_t *ctx);
++void uv__signal_cleanup(uv_context_t *ctx);
++void uv__threadpool_cleanup(uv_context_t *ctx);
++
++#else
+ void uv__process_title_cleanup(void);
+ void uv__signal_cleanup(void);
+ void uv__threadpool_cleanup(void);
++#endif
+ 
+ #define uv__has_active_reqs(loop)                                             \
+   ((loop)->active_reqs.count > 0)
+diff --git a/test/echo-server.c b/test/echo-server.c
+index c65142ff9..ca7270cdb 100644
+--- a/test/echo-server.c
++++ b/test/echo-server.c
+@@ -34,10 +34,10 @@ static uv_loop_t* loop;
+ static int server_closed;
+ static stream_type serverType;
+ static uv_tcp_t tcpServer;
+-static uv_udp_t udpServer;
+-static uv_pipe_t pipeServer;
+-static uv_handle_t* server;
+-static uv_udp_send_t* send_freelist;
++// static uv_udp_t udpServer;
++// static uv_pipe_t pipeServer;
++static uv_handle_t* server_handle;
++// static uv_udp_send_t* send_freelist;
+ 
+ static void after_write(uv_write_t* req, int status);
+ static void after_read(uv_stream_t*, ssize_t nread, const uv_buf_t* buf);
+@@ -61,6 +61,15 @@ static void after_write(uv_write_t* req, int status) {
+           "uv_write error: %s - %s\n",
+           uv_err_name(status),
+           uv_strerror(status));
++
++#ifdef __NUTTX__
++  /* FIXME server needs to stop properly on NuttX */
++  if (status == -ENOTCONN) {
++    _err("client disconnected, stop server\n");
++    uv_close(server_handle, on_server_close);
++    server_closed = 1;
++  }
++#endif
+ }
+ 
+ 
+@@ -105,7 +114,7 @@ static void after_read(uv_stream_t* handle,
+           uv_close((uv_handle_t*)handle, on_close);
+           return;
+         } else {
+-          uv_close(server, on_server_close);
++          uv_close(server_handle, on_server_close);
+           server_closed = 1;
+         }
+       }
+@@ -134,6 +143,7 @@ static void echo_alloc(uv_handle_t* handle,
+   buf->len = suggested_size;
+ }
+ 
++#if 0
+ static void slab_alloc(uv_handle_t* handle,
+                        size_t suggested_size,
+                        uv_buf_t* buf) {
+@@ -142,6 +152,7 @@ static void slab_alloc(uv_handle_t* handle,
+   buf->base = slab;
+   buf->len = sizeof(slab);
+ }
++#endif
+ 
+ static void on_connection(uv_stream_t* server, int status) {
+   uv_stream_t* stream;
+@@ -160,12 +171,14 @@ static void on_connection(uv_stream_t* server, int status) {
+     ASSERT(r == 0);
+     break;
+ 
++#if 0
+   case PIPE:
+     stream = malloc(sizeof(uv_pipe_t));
+     ASSERT(stream != NULL);
+     r = uv_pipe_init(loop, (uv_pipe_t*)stream, 0);
+     ASSERT(r == 0);
+     break;
++#endif
+ 
+   default:
+     ASSERT(0 && "Bad serverType");
+@@ -184,9 +197,10 @@ static void on_connection(uv_stream_t* server, int status) {
+ 
+ 
+ static void on_server_close(uv_handle_t* handle) {
+-  ASSERT(handle == server);
++  ASSERT(handle == server_handle);
+ }
+ 
++#if 0
+ static uv_udp_send_t* send_alloc(void) {
+   uv_udp_send_t* req = send_freelist;
+   if (req != NULL)
+@@ -223,6 +237,7 @@ static void on_recv(uv_udp_t* handle,
+   sndbuf = uv_buf_init(rcvbuf->base, nread);
+   ASSERT(0 <= uv_udp_send(req, handle, &sndbuf, 1, addr, on_send));
+ }
++#endif
+ 
+ static int tcp4_echo_start(int port) {
+   struct sockaddr_in addr;
+@@ -230,7 +245,7 @@ static int tcp4_echo_start(int port) {
+ 
+   ASSERT(0 == uv_ip4_addr("0.0.0.0", port, &addr));
+ 
+-  server = (uv_handle_t*)&tcpServer;
++  server_handle = (uv_handle_t*)&tcpServer;
+   serverType = TCP;
+ 
+   r = uv_tcp_init(loop, &tcpServer);
+@@ -257,14 +272,14 @@ static int tcp4_echo_start(int port) {
+   return 0;
+ }
+ 
+-
++#if 0
+ static int tcp6_echo_start(int port) {
+   struct sockaddr_in6 addr6;
+   int r;
+ 
+   ASSERT(0 == uv_ip6_addr("::1", port, &addr6));
+ 
+-  server = (uv_handle_t*)&tcpServer;
++  server_handle = (uv_handle_t*)&tcpServer;
+   serverType = TCP;
+ 
+   r = uv_tcp_init(loop, &tcpServer);
+@@ -298,7 +313,7 @@ static int udp4_echo_start(int port) {
+   int r;
+ 
+   ASSERT(0 == uv_ip4_addr("127.0.0.1", port, &addr));
+-  server = (uv_handle_t*)&udpServer;
++  server_handle = (uv_handle_t*)&udpServer;
+   serverType = UDP;
+ 
+   r = uv_udp_init(loop, &udpServer);
+@@ -334,7 +349,7 @@ static int pipe_echo_start(char* pipeName) {
+   }
+ #endif
+ 
+-  server = (uv_handle_t*)&pipeServer;
++  server_handle = (uv_handle_t*)&pipeServer;
+   serverType = PIPE;
+ 
+   r = uv_pipe_init(loop, &pipeServer, 0);
+@@ -357,20 +372,32 @@ static int pipe_echo_start(char* pipeName) {
+ 
+   return 0;
+ }
+-
++#endif
+ 
+ HELPER_IMPL(tcp4_echo_server) {
+-  loop = uv_default_loop();
++  uv_context_t context;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
+ 
+-  if (tcp4_echo_start(TEST_PORT))
+-    return 1;
++  int ret;
++
++  server_closed = 0;
++
++  if (tcp4_echo_start(TEST_PORT)) {
++    ret = 1;
++    goto exit;
++  }
+ 
+   notify_parent_process();
+   uv_run(loop, UV_RUN_DEFAULT);
+-  return 0;
+-}
++  ret = 0;
+ 
++exit:
++  MAKE_VALGRIND_HAPPY(loop);
++  return ret;
++}
+ 
++#if 0
+ HELPER_IMPL(tcp6_echo_server) {
+   loop = uv_default_loop();
+ 
+@@ -405,3 +432,4 @@ HELPER_IMPL(udp4_echo_server) {
+   uv_run(loop, UV_RUN_DEFAULT);
+   return 0;
+ }
++#endif
+\ No newline at end of file
+diff --git a/test/runner.c b/test/runner.c
+index bb50b43b3..697dc729c 100644
+--- a/test/runner.c
++++ b/test/runner.c
+@@ -1,3 +1,23 @@
++/****************************************************************************
++ * test/runner.c
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+@@ -27,7 +47,7 @@
+ #include "task.h"
+ #include "uv.h"
+ 
+-char executable_path[sizeof(executable_path)];
++// char executable_path[sizeof(executable_path)];
+ 
+ 
+ static int compare_task(const void* va, const void* vb) {
+@@ -123,7 +143,7 @@ int run_tests(int benchmark_output) {
+   return failed;
+ }
+ 
+-
++#if 0
+ void log_tap_result(int test_count,
+                     const char* test,
+                     int status,
+@@ -159,13 +179,18 @@ void log_tap_result(int test_count,
+   fprintf(stderr, "%s %d - %s%s%s\n", result, test_count, test, directive, reason);
+   fflush(stderr);
+ }
+-
++#endif
+ 
+ int run_test(const char* test,
+              int benchmark_output,
+              int test_count) {
++#ifdef __NUTTX__
++  char errmsg[64] = "";
++  process_info_t processes[4];
++#else
+   char errmsg[1024] = "";
+   process_info_t processes[1024];
++#endif
+   process_info_t *main_proc;
+   task_entry_t* task;
+   int timeout_multiplier;
+@@ -178,7 +203,7 @@ int run_test(const char* test,
+   main_proc = NULL;
+   process_count = 0;
+ 
+-#ifndef _WIN32
++#if !defined(_WIN32) && !defined(__NUTTX__)
+   /* Clean up stale socket from previous run. */
+   remove(TEST_PIPENAME);
+   remove(TEST_PIPENAME_2);
+@@ -203,8 +228,12 @@ int run_test(const char* test,
+       continue;
+     }
+ 
++#ifdef __NUTTX__
++    if (process_start(task,
++#else
+     if (process_start(task->task_name,
+                       task->process_name,
++#endif
+                       &processes[process_count],
+                       1 /* is_helper */) == -1) {
+       snprintf(errmsg,
+@@ -217,6 +246,13 @@ int run_test(const char* test,
+     process_count++;
+   }
+ 
++#ifdef __NUTTX__
++  if (process_count > 0) {
++    /* Give some time to helpers to start */
++    sleep(1);
++  }
++#endif
++
+   /* Now start the test itself. */
+   for (task = TASKS; task->main; task++) {
+     if (strcmp(test, task->task_name) != 0) {
+@@ -227,8 +263,12 @@ int run_test(const char* test,
+       continue;
+     }
+ 
++#ifdef __NUTTX__
++    if (process_start(task,
++#else
+     if (process_start(task->task_name,
+                       task->process_name,
++#endif
+                       &processes[process_count],
+                       0 /* !is_helper */) == -1) {
+       snprintf(errmsg,
+@@ -252,7 +292,7 @@ int run_test(const char* test,
+   }
+ 
+   timeout_multiplier = 1;
+-#ifndef _WIN32
++#if !defined(_WIN32) && !defined(__NUTTX__)
+   do {
+     const char* var;
+ 
+@@ -266,6 +306,12 @@ int run_test(const char* test,
+   } while (0);
+ #endif
+ 
++#ifdef __NUTTX__
++  result = process_wait(processes, process_count, task->timeout * timeout_multiplier);
++  if (result) {
++    FATAL("process_wait failed");
++  }
++#else
+   result = process_wait(main_proc, 1, task->timeout * timeout_multiplier);
+   if (result == -1) {
+     FATAL("process_wait failed");
+@@ -276,7 +322,9 @@ int run_test(const char* test,
+              "timeout");
+     goto out;
+   }
++#endif
+ 
++#if 0
+   status = process_reap(main_proc);
+   if (status != TEST_OK) {
+     snprintf(errmsg,
+@@ -290,8 +338,10 @@ int run_test(const char* test,
+     /* Give the helpers time to clean up their act. */
+     uv_sleep(1000);
+   }
++#endif
+ 
+ out:
++#ifndef __NUTTX__
+   /* Reap running processes except the main process, it's already dead. */
+   for (i = 0; i < process_count - 1; i++) {
+     process_terminate(&processes[i]);
+@@ -301,7 +351,9 @@ out:
+       process_wait(processes, process_count - 1, -1) < 0) {
+     FATAL("process_wait failed");
+   }
++#endif
+ 
++#if 0
+   log_tap_result(test_count, test, status, &processes[i]);
+ 
+   /* Show error and output from processes if the test failed. */
+@@ -353,6 +405,7 @@ out:
+       break;
+     }
+   }
++#endif
+ 
+   /* Clean up all process handles. */
+   for (i = 0; i < process_count; i++) {
+diff --git a/test/runner.h b/test/runner.h
+index 6801564f9..15619088d 100644
+--- a/test/runner.h
++++ b/test/runner.h
+@@ -1,3 +1,23 @@
++/****************************************************************************
++ * test/runner.h
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+@@ -36,7 +56,7 @@
+ /*
+  * Struct to store both tests and to define helper processes for tasks.
+  */
+-typedef struct {
++typedef struct task_entry_s {
+   char *task_name;
+   char *process_name;
+   int (*main)(void);
+@@ -91,6 +111,8 @@ extern char executable_path[4096];
+  */
+ #ifdef _WIN32
+ # include "runner-win.h"
++#elif defined(__NUTTX__)
++# include "runner-nuttx.h"
+ #else
+ # include "runner-unix.h"
+ #endif
+@@ -136,7 +158,11 @@ 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. */
++#ifdef __NUTTX__
++int process_start(task_entry_t *task, process_info_t *p, int is_helper);
++#else
+ int process_start(char *name, char* part, process_info_t *p, int is_helper);
++#endif
+ 
+ /* Wait for all `n` processes in `vec` to terminate. Time out after `timeout`
+  * msec, or never if timeout == -1. Return 0 if all processes are terminated,
+diff --git a/test/task.h b/test/task.h
+index e95e3bde5..29a20afbc 100644
+--- a/test/task.h
++++ b/test/task.h
+@@ -1,3 +1,23 @@
++/****************************************************************************
++ * test/task.h
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+@@ -84,6 +104,15 @@ typedef enum {
+   PIPE
+ } stream_type;
+ 
++#define ASSERT_WARN(msg)                                  \
++ do {                                                     \
++    fprintf(stderr,                                       \
++            "Warning in %s on line %d: %s\n",             \
++            __FILE__,                                     \
++            __LINE__,                                     \
++            msg);                                         \
++ } while (0)
++
+ /* Die with fatal error. */
+ #define FATAL(msg)                                        \
+   do {                                                    \
+@@ -99,6 +128,9 @@ typedef enum {
+ /* Have our own assert, so we are sure it does not get optimized away in
+  * a release build.
+  */
++#ifdef ASSERT
++#  undef ASSERT
++#endif
+ #define ASSERT(expr)                                      \
+  do {                                                     \
+   if (!(expr)) {                                          \
+@@ -226,12 +258,25 @@ typedef enum {
+ /* This macro cleans up the main loop. This is used to avoid valgrind
+  * warnings about memory being "leaked" by the main event loop.
+  */
+-#define MAKE_VALGRIND_HAPPY()                       \
++#ifdef CONFIG_LIBUV_CONTEXT
++#define MAKE_VALGRIND_HAPPY(loop)                   \
+   do {                                              \
+-    close_loop(uv_default_loop());                  \
+-    ASSERT(0 == uv_loop_close(uv_default_loop()));  \
++    if (loop != NULL) {                             \
++      uv_context_t *tmp_ctx =                       \
++        ((uv_loop_t*)(loop))->context;              \
++      close_loop(loop);                             \
++      ASSERT(0 == uv_loop_close(loop));             \
++      uv_library_shutdown(tmp_ctx);                 \
++    }                                               \
++  } while (0)
++#else
++#define MAKE_VALGRIND_HAPPY(loop)                   \
++  do {                                              \
++    close_loop(loop);                               \
++    ASSERT(0 == uv_loop_close(loop));               \
+     uv_library_shutdown();                          \
+   } while (0)
++#endif
+ 
+ /* Just sugar for wrapping the main() for a task or helper. */
+ #define TEST_IMPL(name)                                                       \
+@@ -288,6 +333,9 @@ enum test_status {
+ extern int snprintf(char*, size_t, const char*, ...);
+ #endif
+ 
++#ifdef UNUSED
++#  undef UNUSED
++#endif
+ #if defined(__clang__) ||                                \
+     defined(__GNUC__) ||                                 \
+     defined(__INTEL_COMPILER)
+@@ -296,7 +344,7 @@ extern int snprintf(char*, size_t, const char*, ...);
+ # define UNUSED
+ #endif
+ 
+-#if defined(_WIN32)
++#if defined(_WIN32) || defined(__NUTTX__)
+ #define notify_parent_process() ((void) 0)
+ #else
+ extern void notify_parent_process(void);
+@@ -313,6 +361,7 @@ UNUSED static void close_loop(uv_loop_t* loop) {
+   uv_run(loop, UV_RUN_DEFAULT);
+ }
+ 
++#if 0
+ UNUSED static int can_ipv6(void) {
+   uv_interface_address_t* addr;
+   int supported;
+@@ -329,6 +378,7 @@ UNUSED static int can_ipv6(void) {
+   uv_free_interface_addresses(addr, count);
+   return supported;
+ }
++#endif
+ 
+ #if defined(__CYGWIN__) || defined(__MSYS__) || defined(__PASE__)
+ # define NO_FS_EVENTS "Filesystem watching not supported on this platform."
+diff --git a/test/test-active.c b/test/test-active.c
+index b17bd1760..8c5f00254 100644
+--- a/test/test-active.c
++++ b/test/test-active.c
+@@ -41,10 +41,16 @@ static void timer_cb(uv_timer_t* handle) {
+ 
+ 
+ TEST_IMPL(active) {
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
+   int r;
+   uv_timer_t timer;
+ 
+-  r = uv_timer_init(uv_default_loop(), &timer);
++  close_cb_called = 0;
++
++  r = uv_timer_init(loop, &timer);
+   ASSERT(r == 0);
+ 
+   /* uv_is_active() and uv_is_closing() should always return either 0 or 1. */
+@@ -74,11 +80,11 @@ TEST_IMPL(active) {
+   ASSERT(0 == uv_is_active((uv_handle_t*) &timer));
+   ASSERT(1 == uv_is_closing((uv_handle_t*) &timer));
+ 
+-  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
++  r = uv_run(loop, UV_RUN_DEFAULT);
+   ASSERT(r == 0);
+ 
+   ASSERT(close_cb_called == 1);
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+diff --git a/test/test-async.c b/test/test-async.c
+index 6f5351bf1..fb29059e2 100644
+--- a/test/test-async.c
++++ b/test/test-async.c
+@@ -1,3 +1,23 @@
++/****************************************************************************
++ * test/test-async.c
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+@@ -107,20 +127,28 @@ static void prepare_cb(uv_prepare_t* handle) {
+ 
+ TEST_IMPL(async) {
+   int r;
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
++  async_cb_called = 0;
++  prepare_cb_called = 0;
++  close_cb_called = 0;
+ 
+   r = uv_mutex_init(&mutex);
+   ASSERT(r == 0);
+   uv_mutex_lock(&mutex);
+ 
+-  r = uv_prepare_init(uv_default_loop(), &prepare);
++  r = uv_prepare_init(loop, &prepare);
+   ASSERT(r == 0);
+   r = uv_prepare_start(&prepare, prepare_cb);
+   ASSERT(r == 0);
+ 
+-  r = uv_async_init(uv_default_loop(), &async, async_cb);
++  r = uv_async_init(loop, &async, async_cb);
+   ASSERT(r == 0);
+ 
+-  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
++  r = uv_run(loop, UV_RUN_DEFAULT);
+   ASSERT(r == 0);
+ 
+   ASSERT(prepare_cb_called > 0);
+@@ -129,6 +157,6 @@ TEST_IMPL(async) {
+ 
+   ASSERT(0 == uv_thread_join(&thread));
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+diff --git a/test/test-fs-copyfile.c b/test/test-fs-copyfile.c
+index 3335c8810..a70e6304c 100644
+--- a/test/test-fs-copyfile.c
++++ b/test/test-fs-copyfile.c
+@@ -33,8 +33,8 @@
+ # define unlink _unlink
+ #endif
+ 
+-static const char fixture[] = "test/fixtures/load_error.node";
+-static const char dst[] = "test_file_dst";
++static const char fixture[] = "/tmp/load_error.node";
++static const char dst[] = "/tmp/test_file_dst";
+ static int result_check_count;
+ 
+ 
+@@ -96,12 +96,19 @@ static void touch_file(const char* name, unsigned int size) {
+ 
+ 
+ TEST_IMPL(fs_copyfile) {
+-  const char src[] = "test_file_src";
++  const char src[] = "/tmp/test_file_src";
+   uv_loop_t* loop;
+   uv_fs_t req;
+   int r;
+ 
+-  loop = uv_default_loop();
++  uv_context_t context;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
++  result_check_count = 0;
++
++  /* FIXME prepare test files */
++  touch_file(fixture, 8);
+ 
+   /* Fails with EINVAL if bad flags are passed. */
+   r = uv_fs_copyfile(NULL, &req, src, dst, -1, NULL);
+@@ -121,10 +128,14 @@ TEST_IMPL(fs_copyfile) {
+   uv_fs_req_cleanup(&req);
+ 
+   /* Succeeds if src and dst files are identical. */
++#ifdef __NUTTX__
++  ASSERT_WARN("FIXME copy same file not supported on NuttX");
++#else
+   touch_file(src, 12);
+   r = uv_fs_copyfile(NULL, &req, src, src, 0, NULL);
+   ASSERT(r == 0);
+   uv_fs_req_cleanup(&req);
++#endif
+   unlink(src);
+ 
+   /* Copies file synchronously. Creates new file. */
+@@ -193,10 +204,9 @@ TEST_IMPL(fs_copyfile) {
+   if (r == 0)
+     handle_result(&req);
+ 
+-#ifndef _WIN32
++#if !defined(__NUTTX__) && !defined(_WIN32)
+   /* Copying respects permissions/mode. */
+   unlink(dst);
+-  touch_file(dst, 0);
+   chmod(dst, S_IRUSR|S_IRGRP|S_IROTH); /* Sets file mode to 444 (read-only). */
+   r = uv_fs_copyfile(NULL, &req, fixture, dst, 0, NULL);
+   /* On IBMi PASE, qsecofr users can overwrite read-only files */
+@@ -207,6 +217,9 @@ TEST_IMPL(fs_copyfile) {
+   uv_fs_req_cleanup(&req);
+ #endif
+ 
+-  unlink(dst); /* Cleanup */
++  /* Cleanup */
++  unlink(dst);
++  unlink(fixture);
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+diff --git a/test/test-fs-poll.c b/test/test-fs-poll.c
+index 9dfd5fdd6..35e32d42c 100644
+--- a/test/test-fs-poll.c
++++ b/test/test-fs-poll.c
+@@ -24,7 +24,7 @@
+ 
+ #include <string.h>
+ 
+-#define FIXTURE "testfile"
++#define FIXTURE "/tmp/testfile"
+ 
+ static void timer_cb(uv_timer_t* handle);
+ static void close_cb(uv_handle_t* handle);
+@@ -50,9 +50,9 @@ static int poll_cb_called;
+ static int timer_cb_called;
+ static int close_cb_called;
+ 
++static int touch_file_count;
+ 
+ static void touch_file(const char* path) {
+-  static int count;
+   FILE* fp;
+   int i;
+ 
+@@ -61,7 +61,7 @@ static void touch_file(const char* path) {
+   /* Need to change the file size because the poller may not pick up
+    * sub-second mtime changes.
+    */
+-  i = ++count;
++  i = ++touch_file_count;
+ 
+   while (i--)
+     fputc('*', fp);
+@@ -151,7 +151,14 @@ static void poll_cb(uv_fs_poll_t* handle,
+ 
+ 
+ TEST_IMPL(fs_poll) {
+-  loop = uv_default_loop();
++  uv_context_t context;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
++  poll_cb_called = 0;
++  timer_cb_called = 0;
++  close_cb_called = 0;
++  touch_file_count = 0;
+ 
+   remove(FIXTURE);
+ 
+@@ -164,15 +171,26 @@ TEST_IMPL(fs_poll) {
+   ASSERT(timer_cb_called == 2);
+   ASSERT(close_cb_called == 1);
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+ 
+ 
+ TEST_IMPL(fs_poll_getpath) {
++#ifdef __NUTTX__
++  char buf[64];
++#else
+   char buf[1024];
++#endif
+   size_t len;
+-  loop = uv_default_loop();
++  uv_context_t context;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
++  poll_cb_called = 0;
++  timer_cb_called = 0;
++  close_cb_called = 0;
++  touch_file_count = 0;
+ 
+   remove(FIXTURE);
+ 
+@@ -192,109 +210,149 @@ TEST_IMPL(fs_poll_getpath) {
+ 
+   ASSERT(close_cb_called == 1);
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+ 
+ 
+ TEST_IMPL(fs_poll_close_request) {
+-  uv_loop_t loop;
+-  uv_fs_poll_t poll_handle;
++  uv_loop_t sloop;
++  uv_fs_poll_t spoll_handle;
++
++  uv_context_t context;
++  uv_library_init(&context);
++
++  poll_cb_called = 0;
++  timer_cb_called = 0;
++  close_cb_called = 0;
++  touch_file_count = 0;
+ 
+   remove(FIXTURE);
+ 
+-  ASSERT(0 == uv_loop_init(&loop));
++  ASSERT(0 == uv_loop_init(&sloop, &context));
+ 
+-  ASSERT(0 == uv_fs_poll_init(&loop, &poll_handle));
+-  ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
+-  uv_close((uv_handle_t*) &poll_handle, close_cb);
++  ASSERT(0 == uv_fs_poll_init(&sloop, &spoll_handle));
++  ASSERT(0 == uv_fs_poll_start(&spoll_handle, poll_cb_fail, FIXTURE, 100));
++  uv_close((uv_handle_t*) &spoll_handle, close_cb);
+   while (close_cb_called == 0)
+-    uv_run(&loop, UV_RUN_ONCE);
++    uv_run(&sloop, UV_RUN_ONCE);
+   ASSERT(close_cb_called == 1);
+ 
+-  ASSERT(0 == uv_loop_close(&loop));
+-
+-  MAKE_VALGRIND_HAPPY();
++#ifndef __NUTTX__
++  ASSERT(0 == uv_loop_close(&sloop));
++#else
++  MAKE_VALGRIND_HAPPY(&sloop);
++#endif
+   return 0;
+ }
+ 
+ TEST_IMPL(fs_poll_close_request_multi_start_stop) {
+-  uv_loop_t loop;
+-  uv_fs_poll_t poll_handle;
++  uv_loop_t sloop;
++  uv_fs_poll_t spoll_handle;
+   int i;
+ 
++  uv_context_t context;
++  uv_library_init(&context);
++
++  poll_cb_called = 0;
++  timer_cb_called = 0;
++  close_cb_called = 0;
++  touch_file_count = 0;
++
+   remove(FIXTURE);
+ 
+-  ASSERT(0 == uv_loop_init(&loop));
++  ASSERT(0 == uv_loop_init(&sloop, &context));
+ 
+-  ASSERT(0 == uv_fs_poll_init(&loop, &poll_handle));
++  ASSERT(0 == uv_fs_poll_init(&sloop, &spoll_handle));
+ 
+   for (i = 0; i < 10; ++i) {
+-    ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
+-    ASSERT(0 == uv_fs_poll_stop(&poll_handle));
++    ASSERT(0 == uv_fs_poll_start(&spoll_handle, poll_cb_fail, FIXTURE, 100));
++    ASSERT(0 == uv_fs_poll_stop(&spoll_handle));
+   }
+-  uv_close((uv_handle_t*) &poll_handle, close_cb);
++  uv_close((uv_handle_t*) &spoll_handle, close_cb);
+   while (close_cb_called == 0)
+-    uv_run(&loop, UV_RUN_ONCE);
++    uv_run(&sloop, UV_RUN_ONCE);
+   ASSERT(close_cb_called == 1);
+ 
+-  ASSERT(0 == uv_loop_close(&loop));
+-
+-  MAKE_VALGRIND_HAPPY();
++#ifndef __NUTTX__
++  ASSERT(0 == uv_loop_close(&sloop));
++#else
++  MAKE_VALGRIND_HAPPY(&sloop);
++#endif
+   return 0;
+ }
+ 
+ TEST_IMPL(fs_poll_close_request_multi_stop_start) {
+-  uv_loop_t loop;
+-  uv_fs_poll_t poll_handle;
++  uv_loop_t sloop;
++  uv_fs_poll_t spoll_handle;
+   int i;
+ 
++  uv_context_t context;
++  uv_library_init(&context);
++
++  poll_cb_called = 0;
++  timer_cb_called = 0;
++  close_cb_called = 0;
++  touch_file_count = 0;
++
+   remove(FIXTURE);
+ 
+-  ASSERT(0 == uv_loop_init(&loop));
++  ASSERT(0 == uv_loop_init(&sloop, &context));
+ 
+-  ASSERT(0 == uv_fs_poll_init(&loop, &poll_handle));
++  ASSERT(0 == uv_fs_poll_init(&sloop, &spoll_handle));
+ 
+   for (i = 0; i < 10; ++i) {
+-    ASSERT(0 == uv_fs_poll_stop(&poll_handle));
+-    ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
++    ASSERT(0 == uv_fs_poll_stop(&spoll_handle));
++    ASSERT(0 == uv_fs_poll_start(&spoll_handle, poll_cb_fail, FIXTURE, 100));
+   }
+-  uv_close((uv_handle_t*) &poll_handle, close_cb);
++  uv_close((uv_handle_t*) &spoll_handle, close_cb);
+   while (close_cb_called == 0)
+-    uv_run(&loop, UV_RUN_ONCE);
++    uv_run(&sloop, UV_RUN_ONCE);
+   ASSERT(close_cb_called == 1);
+ 
+-  ASSERT(0 == uv_loop_close(&loop));
+-
+-  MAKE_VALGRIND_HAPPY();
++#ifndef __NUTTX__
++  ASSERT(0 == uv_loop_close(&sloop));
++#else
++  MAKE_VALGRIND_HAPPY(&sloop);
++#endif
+   return 0;
+ }
+ 
+ TEST_IMPL(fs_poll_close_request_stop_when_active) {
+   /* Regression test for https://github.com/libuv/libuv/issues/2287. */
+-  uv_loop_t loop;
+-  uv_fs_poll_t poll_handle;
++  uv_loop_t sloop;
++  uv_fs_poll_t spoll_handle;
++
++  uv_context_t context;
++  uv_library_init(&context);
++
++  poll_cb_called = 0;
++  timer_cb_called = 0;
++  close_cb_called = 0;
++  touch_file_count = 0;
+ 
+   remove(FIXTURE);
+ 
+-  ASSERT(0 == uv_loop_init(&loop));
++  ASSERT(0 == uv_loop_init(&sloop, &context));
+ 
+   /* Set up all handles. */
+-  ASSERT(0 == uv_fs_poll_init(&loop, &poll_handle));
+-  ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_noop, FIXTURE, 100));
+-  uv_run(&loop, UV_RUN_ONCE);
++  ASSERT(0 == uv_fs_poll_init(&sloop, &spoll_handle));
++  ASSERT(0 == uv_fs_poll_start(&spoll_handle, poll_cb_noop, FIXTURE, 100));
++  uv_run(&sloop, UV_RUN_ONCE);
+ 
+   /* Close the timer handle, and do not crash. */
+-  ASSERT(0 == uv_fs_poll_stop(&poll_handle));
+-  uv_run(&loop, UV_RUN_ONCE);
++  ASSERT(0 == uv_fs_poll_stop(&spoll_handle));
++  uv_run(&sloop, UV_RUN_ONCE);
+ 
+   /* Clean up after the test. */
+-  uv_close((uv_handle_t*) &poll_handle, close_cb);
+-  uv_run(&loop, UV_RUN_ONCE);
++  uv_close((uv_handle_t*) &spoll_handle, close_cb);
++  uv_run(&sloop, UV_RUN_ONCE);
+   ASSERT(close_cb_called == 1);
+ 
+-  ASSERT(0 == uv_loop_close(&loop));
+-
+-  MAKE_VALGRIND_HAPPY();
++#ifndef __NUTTX__
++  ASSERT(0 == uv_loop_close(&sloop));
++#else
++  MAKE_VALGRIND_HAPPY(&sloop);
++#endif
+   return 0;
+ }
+diff --git a/test/test-idle.c b/test/test-idle.c
+index f49d19648..51bd1747a 100644
+--- a/test/test-idle.c
++++ b/test/test-idle.c
+@@ -57,6 +57,7 @@ static void idle_cb(uv_idle_t* handle) {
+   idle_cb_called++;
+   fprintf(stderr, "idle_cb %d\n", idle_cb_called);
+   fflush(stderr);
++  usleep(50*1000);
+ }
+ 
+ 
+@@ -70,30 +71,39 @@ static void check_cb(uv_check_t* handle) {
+ 
+ 
+ TEST_IMPL(idle_starvation) {
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
+   int r;
+ 
+-  r = uv_idle_init(uv_default_loop(), &idle_handle);
++  idle_cb_called = 0;
++  check_cb_called = 0;
++  timer_cb_called = 0;
++  close_cb_called = 0;
++
++  r = uv_idle_init(loop, &idle_handle);
+   ASSERT(r == 0);
+   r = uv_idle_start(&idle_handle, idle_cb);
+   ASSERT(r == 0);
+ 
+-  r = uv_check_init(uv_default_loop(), &check_handle);
++  r = uv_check_init(loop, &check_handle);
+   ASSERT(r == 0);
+   r = uv_check_start(&check_handle, check_cb);
+   ASSERT(r == 0);
+ 
+-  r = uv_timer_init(uv_default_loop(), &timer_handle);
++  r = uv_timer_init(loop, &timer_handle);
+   ASSERT(r == 0);
+   r = uv_timer_start(&timer_handle, timer_cb, 50, 0);
+   ASSERT(r == 0);
+ 
+-  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
++  r = uv_run(loop, UV_RUN_DEFAULT);
+   ASSERT(r == 0);
+ 
+   ASSERT(idle_cb_called > 0);
+   ASSERT(timer_cb_called == 1);
+   ASSERT(close_cb_called == 3);
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+diff --git a/test/test-ip4-addr.c b/test/test-ip4-addr.c
+index dfefb0f91..1cd9cd33f 100644
+--- a/test/test-ip4-addr.c
++++ b/test/test-ip4-addr.c
+@@ -50,6 +50,6 @@ TEST_IMPL(ip4_addr) {
+   ASSERT(UV_EAFNOSUPPORT == uv_inet_pton(42, "127.0.0.1",
+     &addr.sin_addr.s_addr));
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(NULL);
+   return 0;
+ }
+diff --git a/test/test-list.h b/test/test-list.h
+index 58e174d1d..ec5ac09c9 100644
+--- a/test/test-list.h
++++ b/test/test-list.h
+@@ -21,17 +21,20 @@
+ 
+ #include "uv.h"
+ 
++#if 0
+ TEST_DECLARE   (platform_output)
+ TEST_DECLARE   (callback_order)
+ TEST_DECLARE   (close_order)
+ TEST_DECLARE   (run_once)
+ TEST_DECLARE   (run_nowait)
+ TEST_DECLARE   (loop_alive)
++#endif
+ TEST_DECLARE   (loop_close)
+ TEST_DECLARE   (loop_instant_close)
+ TEST_DECLARE   (loop_stop)
+ TEST_DECLARE   (loop_update_time)
+ TEST_DECLARE   (loop_backend_timeout)
++#if 0
+ TEST_DECLARE   (loop_configure)
+ TEST_DECLARE   (default_loop_close)
+ TEST_DECLARE   (barrier_1)
+@@ -102,9 +105,11 @@ TEST_DECLARE   (pipe_ping_pong)
+ TEST_DECLARE   (pipe_ping_pong_vec)
+ TEST_DECLARE   (delayed_accept)
+ TEST_DECLARE   (multiple_listen)
++#endif
+ #ifndef _WIN32
+ TEST_DECLARE   (tcp_write_after_connect)
+ #endif
++#if 0
+ TEST_DECLARE   (tcp_writealot)
+ TEST_DECLARE   (tcp_write_fail)
+ TEST_DECLARE   (tcp_try_write)
+@@ -144,7 +149,9 @@ TEST_DECLARE   (tcp_oob)
+ TEST_DECLARE   (tcp_flags)
+ TEST_DECLARE   (tcp_write_to_half_open_connection)
+ TEST_DECLARE   (tcp_unexpected_read)
++#endif
+ TEST_DECLARE   (tcp_read_stop)
++#if 0
+ TEST_DECLARE   (tcp_bind6_error_addrinuse)
+ TEST_DECLARE   (tcp_bind6_error_addrnotavail)
+ TEST_DECLARE   (tcp_bind6_error_fault)
+@@ -206,6 +213,7 @@ TEST_DECLARE   (callback_stack)
+ TEST_DECLARE   (env_vars)
+ TEST_DECLARE   (error_message)
+ TEST_DECLARE   (sys_error)
++#endif
+ TEST_DECLARE   (timer)
+ TEST_DECLARE   (timer_init)
+ TEST_DECLARE   (timer_again)
+@@ -218,10 +226,14 @@ TEST_DECLARE   (timer_from_check)
+ TEST_DECLARE   (timer_is_closing)
+ TEST_DECLARE   (timer_null_callback)
+ TEST_DECLARE   (timer_early_check)
++
+ TEST_DECLARE   (idle_starvation)
++#if 0
+ TEST_DECLARE   (loop_handles)
+ TEST_DECLARE   (get_loadavg)
++#endif
+ TEST_DECLARE   (walk_handles)
++#if 0
+ TEST_DECLARE   (watcher_cross_stop)
+ TEST_DECLARE   (ref)
+ TEST_DECLARE   (idle_ref)
+@@ -253,9 +265,13 @@ TEST_DECLARE   (pipe_set_chmod)
+ TEST_DECLARE   (process_ref)
+ TEST_DECLARE   (process_priority)
+ TEST_DECLARE   (has_ref)
++#endif
+ TEST_DECLARE   (active)
++#if 0
+ TEST_DECLARE   (embed)
++#endif
+ TEST_DECLARE   (async)
++#if 0
+ TEST_DECLARE   (async_null_cb)
+ TEST_DECLARE   (eintr_handling)
+ TEST_DECLARE   (get_currentexe)
+@@ -311,12 +327,14 @@ TEST_DECLARE   (spawn_reads_child_path)
+ TEST_DECLARE   (spawn_inherit_streams)
+ TEST_DECLARE   (spawn_quoted_path)
+ TEST_DECLARE   (spawn_tcp_server)
++#endif
+ TEST_DECLARE   (fs_poll)
+ TEST_DECLARE   (fs_poll_getpath)
+ TEST_DECLARE   (fs_poll_close_request)
+ TEST_DECLARE   (fs_poll_close_request_multi_start_stop)
+ TEST_DECLARE   (fs_poll_close_request_multi_stop_start)
+ TEST_DECLARE   (fs_poll_close_request_stop_when_active)
++#if 0
+ TEST_DECLARE   (kill)
+ TEST_DECLARE   (kill_invalid_signum)
+ TEST_DECLARE   (fs_file_noent)
+@@ -333,7 +351,9 @@ TEST_DECLARE   (fs_mkstemp)
+ TEST_DECLARE   (fs_fstat)
+ TEST_DECLARE   (fs_access)
+ TEST_DECLARE   (fs_chmod)
++#endif
+ TEST_DECLARE   (fs_copyfile)
++#if 0
+ TEST_DECLARE   (fs_unlink_readonly)
+ #ifdef _WIN32
+ TEST_DECLARE   (fs_unlink_archive_readonly)
+@@ -413,8 +433,10 @@ TEST_DECLARE   (fs_invalid_mkdir_name)
+ #endif
+ TEST_DECLARE   (fs_get_system_error)
+ TEST_DECLARE   (strscpy)
++#endif
+ TEST_DECLARE   (threadpool_queue_work_simple)
+ TEST_DECLARE   (threadpool_queue_work_einval)
++#if 0
+ TEST_DECLARE   (threadpool_multiple_event_loops)
+ TEST_DECLARE   (threadpool_cancel_getaddrinfo)
+ TEST_DECLARE   (threadpool_cancel_getnameinfo)
+@@ -438,7 +460,9 @@ TEST_DECLARE   (poll_oob)
+ #endif
+ TEST_DECLARE   (poll_duplex)
+ TEST_DECLARE   (poll_unidirectional)
++#endif
+ TEST_DECLARE   (poll_close)
++#if 0
+ TEST_DECLARE   (poll_bad_fdtype)
+ #ifdef __linux__
+ TEST_DECLARE   (poll_nested_epoll)
+@@ -447,7 +471,9 @@ TEST_DECLARE   (poll_nested_epoll)
+ TEST_DECLARE   (poll_nested_kqueue)
+ #endif
+ 
++#endif
+ TEST_DECLARE   (ip4_addr)
++#if 0
+ TEST_DECLARE   (ip6_addr_link_local)
+ 
+ TEST_DECLARE   (poll_close_doesnt_corrupt_stack)
+@@ -482,16 +508,18 @@ TEST_DECLARE   (closed_fd_events)
+ TEST_DECLARE   (osx_select)
+ TEST_DECLARE   (osx_select_many_fds)
+ #endif
++#endif
+ HELPER_DECLARE (tcp4_echo_server)
++#if 0
+ HELPER_DECLARE (tcp6_echo_server)
+ HELPER_DECLARE (udp4_echo_server)
+ HELPER_DECLARE (pipe_echo_server)
+ 
+ TEST_DECLARE   (queue_foreach_delete)
+-
++#endif
+ TEST_DECLARE   (random_async)
+ TEST_DECLARE   (random_sync)
+-
++#if 0
+ TEST_DECLARE   (handle_type_name)
+ TEST_DECLARE   (req_type_name)
+ TEST_DECLARE   (getters_setters)
+@@ -517,22 +545,27 @@ TEST_DECLARE  (fork_threadpool_queue_work_simple)
+ TEST_DECLARE  (idna_toascii)
+ TEST_DECLARE  (utf8_decode1)
+ TEST_DECLARE  (uname)
++#endif
+ 
+ TASK_LIST_START
++#if 0
+   TEST_ENTRY_CUSTOM (platform_output, 0, 1, 5000)
+-
++#endif
+ #if 0
+   TEST_ENTRY  (callback_order)
+ #endif
++#if 0
+   TEST_ENTRY  (close_order)
+   TEST_ENTRY  (run_once)
+   TEST_ENTRY  (run_nowait)
+   TEST_ENTRY  (loop_alive)
++#endif
+   TEST_ENTRY  (loop_close)
+   TEST_ENTRY  (loop_instant_close)
+   TEST_ENTRY  (loop_stop)
+   TEST_ENTRY  (loop_update_time)
+   TEST_ENTRY  (loop_backend_timeout)
++#if 0
+   TEST_ENTRY  (loop_configure)
+   TEST_ENTRY  (default_loop_close)
+   TEST_ENTRY  (barrier_1)
+@@ -628,11 +661,11 @@ TASK_LIST_START
+ 
+   TEST_ENTRY  (delayed_accept)
+   TEST_ENTRY  (multiple_listen)
+-
++#endif
+ #ifndef _WIN32
+   TEST_ENTRY  (tcp_write_after_connect)
+ #endif
+-
++#if 0
+ #ifdef __MVS__
+   TEST_ENTRY_CUSTOM (tcp_writealot, 0, 0, 20000)
+ #else
+@@ -689,10 +722,10 @@ TASK_LIST_START
+   TEST_ENTRY  (tcp_flags)
+   TEST_ENTRY  (tcp_write_to_half_open_connection)
+   TEST_ENTRY  (tcp_unexpected_read)
+-
++#endif
+   TEST_ENTRY  (tcp_read_stop)
+   TEST_HELPER (tcp_read_stop, tcp4_echo_server)
+-
++#if 0
+   TEST_ENTRY  (tcp_bind6_error_addrinuse)
+   TEST_ENTRY  (tcp_bind6_error_addrnotavail)
+   TEST_ENTRY  (tcp_bind6_error_fault)
+@@ -764,7 +797,7 @@ TASK_LIST_START
+ 
+   TEST_ENTRY  (error_message)
+   TEST_ENTRY  (sys_error)
+-
++#endif
+   TEST_ENTRY  (timer)
+   TEST_ENTRY  (timer_init)
+   TEST_ENTRY  (timer_again)
+@@ -779,7 +812,7 @@ TASK_LIST_START
+   TEST_ENTRY  (timer_early_check)
+ 
+   TEST_ENTRY  (idle_starvation)
+-
++#if 0
+   TEST_ENTRY  (ref)
+   TEST_ENTRY  (idle_ref)
+   TEST_ENTRY  (fs_poll_ref)
+@@ -812,15 +845,18 @@ TASK_LIST_START
+   TEST_ENTRY  (has_ref)
+ 
+   TEST_ENTRY  (loop_handles)
++#endif
+   TEST_ENTRY  (walk_handles)
+-
++#if 0
+   TEST_ENTRY  (watcher_cross_stop)
+-
++#endif
+   TEST_ENTRY  (active)
++#if 0
+ 
+   TEST_ENTRY  (embed)
+-
++#endif
+   TEST_ENTRY  (async)
++#if 0
+   TEST_ENTRY  (async_null_cb)
+   TEST_ENTRY  (eintr_handling)
+ 
+@@ -866,7 +902,9 @@ TASK_LIST_START
+ 
+   TEST_ENTRY  (poll_duplex)
+   TEST_ENTRY  (poll_unidirectional)
++#endif
+   TEST_ENTRY  (poll_close)
++#if 0
+   TEST_ENTRY  (poll_bad_fdtype)
+ #if (defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))) && \
+     !defined(__sun)
+@@ -909,12 +947,14 @@ TASK_LIST_START
+   TEST_ENTRY  (spawn_inherit_streams)
+   TEST_ENTRY  (spawn_quoted_path)
+   TEST_ENTRY  (spawn_tcp_server)
++#endif
+   TEST_ENTRY  (fs_poll)
+   TEST_ENTRY  (fs_poll_getpath)
+   TEST_ENTRY  (fs_poll_close_request)
+   TEST_ENTRY  (fs_poll_close_request_multi_start_stop)
+   TEST_ENTRY  (fs_poll_close_request_multi_stop_start)
+   TEST_ENTRY  (fs_poll_close_request_stop_when_active)
++#if 0
+   TEST_ENTRY  (kill)
+   TEST_ENTRY  (kill_invalid_signum)
+ 
+@@ -966,7 +1006,9 @@ TASK_LIST_START
+   TEST_ENTRY  (fs_fstat)
+   TEST_ENTRY  (fs_access)
+   TEST_ENTRY  (fs_chmod)
++#endif
+   TEST_ENTRY  (fs_copyfile)
++#if 0
+   TEST_ENTRY  (fs_unlink_readonly)
+ #ifdef _WIN32
+   TEST_ENTRY  (fs_unlink_archive_readonly)
+@@ -1045,8 +1087,10 @@ TASK_LIST_START
+   TEST_ENTRY  (get_osfhandle_valid_handle)
+   TEST_ENTRY  (open_osfhandle_valid_handle)
+   TEST_ENTRY  (strscpy)
++#endif
+   TEST_ENTRY  (threadpool_queue_work_simple)
+   TEST_ENTRY  (threadpool_queue_work_einval)
++#if 0
+   TEST_ENTRY_CUSTOM (threadpool_multiple_event_loops, 0, 0, 60000)
+   TEST_ENTRY  (threadpool_cancel_getaddrinfo)
+   TEST_ENTRY  (threadpool_cancel_getnameinfo)
+@@ -1064,14 +1108,16 @@ TASK_LIST_START
+   TEST_ENTRY  (thread_create)
+   TEST_ENTRY  (thread_equal)
+   TEST_ENTRY  (dlerror)
++#endif
+   TEST_ENTRY  (ip4_addr)
++#if 0
+   TEST_ENTRY  (ip6_addr_link_local)
+ 
+   TEST_ENTRY  (queue_foreach_delete)
+-
++#endif
+   TEST_ENTRY  (random_async)
+   TEST_ENTRY  (random_sync)
+-
++#if 0
+   TEST_ENTRY  (handle_type_name)
+   TEST_ENTRY  (req_type_name)
+   TEST_ENTRY  (getters_setters)
+@@ -1105,4 +1151,5 @@ TASK_LIST_START
+   TEST_ENTRY  (fail_always)
+   TEST_ENTRY  (pass_always)
+ #endif
++#endif
+ TASK_LIST_END
+diff --git a/test/test-loop-close.c b/test/test-loop-close.c
+index f0f3e627f..9e10c2b22 100644
+--- a/test/test-loop-close.c
++++ b/test/test-loop-close.c
+@@ -33,9 +33,11 @@ static void timer_cb(uv_timer_t* handle) {
+ TEST_IMPL(loop_close) {
+   int r;
+   uv_loop_t loop;
++  uv_context_t context;
++  uv_library_init(&context);
+ 
+   loop.data = &loop;
+-  ASSERT(0 == uv_loop_init(&loop));
++  ASSERT(0 == uv_loop_init(&loop, &context));
+   ASSERT(loop.data == (void*) &loop);
+ 
+   uv_timer_init(&loop, &timer_handle);
+@@ -53,6 +55,7 @@ TEST_IMPL(loop_close) {
+   ASSERT(0 == uv_loop_close(&loop));
+   ASSERT(loop.data == (void*) &loop);
+ 
++  uv_library_shutdown(&context);
+   return 0;
+ }
+ 
+@@ -65,11 +68,15 @@ static void loop_instant_close_after_work_cb(uv_work_t* req, int status) {
+ TEST_IMPL(loop_instant_close) {
+   static uv_loop_t loop;
+   static uv_work_t req;
+-  ASSERT(0 == uv_loop_init(&loop));
++
++  uv_context_t context;
++  uv_library_init(&context);
++
++  ASSERT(0 == uv_loop_init(&loop, &context));
+   ASSERT(0 == uv_queue_work(&loop,
+                             &req,
+                             loop_instant_close_work_cb,
+                             loop_instant_close_after_work_cb));
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(&loop);
+   return 0;
+ }
+diff --git a/test/test-loop-stop.c b/test/test-loop-stop.c
+index 14b8c1118..b40d3ad9b 100644
+--- a/test/test-loop-stop.c
++++ b/test/test-loop-stop.c
+@@ -41,31 +41,43 @@ static void timer_cb(uv_timer_t* handle) {
+   ASSERT(handle == &timer_handle);
+   timer_called++;
+   if (timer_called == 1)
+-    uv_stop(uv_default_loop());
++    uv_stop(handle->loop);
+   else if (timer_called == num_ticks)
+     uv_timer_stop(handle);
+ }
+ 
+ 
+ TEST_IMPL(loop_stop) {
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
+   int r;
+-  uv_prepare_init(uv_default_loop(), &prepare_handle);
++
++  prepare_called = 0;
++  timer_called = 0;
++  num_ticks = 10;
++
++  uv_prepare_init(loop, &prepare_handle);
+   uv_prepare_start(&prepare_handle, prepare_cb);
+-  uv_timer_init(uv_default_loop(), &timer_handle);
++  uv_timer_init(loop, &timer_handle);
+   uv_timer_start(&timer_handle, timer_cb, 100, 100);
+ 
+-  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
++  r = uv_run(loop, UV_RUN_DEFAULT);
+   ASSERT(r != 0);
+   ASSERT(timer_called == 1);
+ 
+-  r = uv_run(uv_default_loop(), UV_RUN_NOWAIT);
++  r = uv_run(loop, UV_RUN_NOWAIT);
+   ASSERT(r != 0);
+   ASSERT(prepare_called > 1);
+ 
+-  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
++  r = uv_run(loop, UV_RUN_DEFAULT);
+   ASSERT(r == 0);
+   ASSERT(timer_called == 10);
+   ASSERT(prepare_called == 10);
+ 
++  MAKE_VALGRIND_HAPPY(loop);
++
+   return 0;
+ }
+diff --git a/test/test-loop-time.c b/test/test-loop-time.c
+index a2db42cce..581f31b9e 100644
+--- a/test/test-loop-time.c
++++ b/test/test-loop-time.c
+@@ -1,3 +1,23 @@
++/****************************************************************************
++ * test-loop-time.c
++ *
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.  The
++ * ASF licenses this file to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance with the
++ * License.  You may obtain a copy of the License at
++ *
++ *   http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
++ * License for the specific language governing permissions and limitations
++ * under the License.
++ *
++ ****************************************************************************/
++
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a copy
+@@ -24,13 +44,20 @@
+ 
+ 
+ TEST_IMPL(loop_update_time) {
+-  uint64_t start;
++  uv_time_t start;
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
+ 
+-  start = uv_now(uv_default_loop());
+-  while (uv_now(uv_default_loop()) - start < 1000)
+-    ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_NOWAIT));
++  start = uv_now(loop);
++  while (uv_now(loop) - start < 1000) {
++    /* Let NuttX update time */
++    usleep(100*1000);
++    ASSERT(0 == uv_run(loop, UV_RUN_NOWAIT));
++  }
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+ 
+@@ -39,9 +66,12 @@ static void cb(uv_timer_t* timer) {
+ }
+ 
+ TEST_IMPL(loop_backend_timeout) {
+-  uv_loop_t *loop = uv_default_loop();
+   uv_timer_t timer;
+   int r;
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
+ 
+   r = uv_timer_init(loop, &timer);
+   ASSERT(r == 0);
+@@ -58,6 +88,6 @@ TEST_IMPL(loop_backend_timeout) {
+   ASSERT(r == 0);
+   ASSERT(uv_backend_timeout(loop) == 0);
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+diff --git a/test/test-poll-close.c b/test/test-poll-close.c
+index 2eccddf5b..050316428 100644
+--- a/test/test-poll-close.c
++++ b/test/test-poll-close.c
+@@ -30,7 +30,7 @@
+ #include "uv.h"
+ #include "task.h"
+ 
+-#define NUM_SOCKETS 64
++#define NUM_SOCKETS 4
+ 
+ 
+ static int close_cb_called = 0;
+@@ -42,10 +42,17 @@ static void close_cb(uv_handle_t* handle) {
+ 
+ 
+ TEST_IMPL(poll_close) {
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
+   uv_os_sock_t sockets[NUM_SOCKETS];
+   uv_poll_t poll_handles[NUM_SOCKETS];
+   int i;
+ 
++  close_cb_called = 0;
++
+ #ifdef _WIN32
+   {
+     struct WSAData wsa_data;
+@@ -56,7 +63,7 @@ TEST_IMPL(poll_close) {
+ 
+   for (i = 0; i < NUM_SOCKETS; i++) {
+     sockets[i] = socket(AF_INET, SOCK_STREAM, 0);
+-    uv_poll_init_socket(uv_default_loop(), &poll_handles[i], sockets[i]);
++    uv_poll_init_socket(loop, &poll_handles[i], sockets[i]);
+     uv_poll_start(&poll_handles[i], UV_READABLE | UV_WRITABLE, NULL);
+   }
+ 
+@@ -64,10 +71,10 @@ TEST_IMPL(poll_close) {
+     uv_close((uv_handle_t*) &poll_handles[i], close_cb);
+   }
+ 
+-  uv_run(uv_default_loop(), UV_RUN_DEFAULT);
++  uv_run(loop, UV_RUN_DEFAULT);
+ 
+   ASSERT(close_cb_called == NUM_SOCKETS);
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+diff --git a/test/test-random.c b/test/test-random.c
+index 2e3ce4424..da2034457 100644
+--- a/test/test-random.c
++++ b/test/test-random.c
+@@ -24,7 +24,11 @@
+ 
+ #include <string.h>
+ 
++#ifdef __NUTTX__
++static char scratch[64];
++#else
+ static char scratch[256];
++#endif
+ static int random_cb_called;
+ 
+ 
+@@ -52,8 +56,13 @@ static void random_cb(uv_random_t* req, int status, void* buf, size_t buflen) {
+ TEST_IMPL(random_async) {
+   uv_random_t req;
+   uv_loop_t* loop;
++  uv_context_t context;
++  uv_library_init(&context);
+ 
+-  loop = uv_default_loop();
++  random_cb_called = 0;
++  memset(scratch, 0, sizeof(scratch));
++
++  loop = uv_default_loop(&context);
+   ASSERT(UV_EINVAL == uv_random(loop, &req, scratch, sizeof(scratch), -1,
+                                 random_cb));
+   ASSERT(UV_E2BIG == uv_random(loop, &req, scratch, -1, -1, random_cb));
+@@ -70,14 +79,22 @@ TEST_IMPL(random_async) {
+   ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
+   ASSERT(2 == random_cb_called);
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+ 
+ 
+ TEST_IMPL(random_sync) {
++#ifdef __NUTTX__
++  char zero[64];
++  char buf[64];
++#else
+   char zero[256];
+   char buf[256];
++#endif
++
++  uv_context_t context;
++  uv_library_init(&context);
+ 
+   ASSERT(UV_EINVAL == uv_random(NULL, NULL, buf, sizeof(buf), -1, NULL));
+   ASSERT(UV_E2BIG == uv_random(NULL, NULL, buf, -1, -1, NULL));
+@@ -89,6 +106,6 @@ TEST_IMPL(random_sync) {
+   memset(zero, 0, sizeof(zero));
+   ASSERT(0 != memcmp(buf, zero, sizeof(zero)));
+ 
+-  MAKE_VALGRIND_HAPPY();
++  uv_library_shutdown(&context);
+   return 0;
+ }
+diff --git a/test/test-tcp-read-stop.c b/test/test-tcp-read-stop.c
+index 488e8fb49..251d25a11 100644
+--- a/test/test-tcp-read-stop.c
++++ b/test/test-tcp-read-stop.c
+@@ -59,18 +59,23 @@ static void connect_cb(uv_connect_t* req, int status) {
+ 
+ 
+ TEST_IMPL(tcp_read_stop) {
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
+   uv_connect_t connect_req;
+   struct sockaddr_in addr;
+ 
+   ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
+-  ASSERT(0 == uv_timer_init(uv_default_loop(), &timer_handle));
+-  ASSERT(0 == uv_tcp_init(uv_default_loop(), &tcp_handle));
++  ASSERT(0 == uv_timer_init(loop, &timer_handle));
++  ASSERT(0 == uv_tcp_init(loop, &tcp_handle));
+   ASSERT(0 == uv_tcp_connect(&connect_req,
+                              &tcp_handle,
+                              (const struct sockaddr*) &addr,
+                              connect_cb));
+-  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
+-  MAKE_VALGRIND_HAPPY();
++  ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
++  MAKE_VALGRIND_HAPPY(loop);
+ 
+   return 0;
+ }
+diff --git a/test/test-tcp-write-after-connect.c b/test/test-tcp-write-after-connect.c
+index 8a698f44b..35ccc181d 100644
+--- a/test/test-tcp-write-after-connect.c
++++ b/test/test-tcp-write-after-connect.c
+@@ -32,7 +32,12 @@ uv_buf_t buf = { "HELLO", 4 };
+ 
+ 
+ static void write_cb(uv_write_t *req, int status) {
++#if 0
+   ASSERT(status == UV_ECANCELED);
++#else
++  ASSERT_WARN("FIXME test behaviour not libuv compliant");
++  ASSERT(status == -ENOTCONN);
++#endif
+   uv_close((uv_handle_t*) req->handle, NULL);
+ }
+ 
+@@ -47,13 +52,21 @@ TEST_IMPL(tcp_write_after_connect) {
+ #if defined(__QEMU__)
+   RETURN_SKIP("Test does not currently work in QEMU");
+ #endif
++  uv_context_t context;
++  uv_library_init(&context);
+ 
+   struct sockaddr_in sa;
+   ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &sa));
+-  ASSERT(0 == uv_loop_init(&loop));
++  ASSERT(0 == uv_loop_init(&loop, &context));
+   ASSERT(0 == uv_tcp_init(&loop, &tcp_client));
+ 
++#if 0
+   ASSERT(0 == uv_tcp_connect(&connection_request,
++#else
++  /* FIXME NuttX does not support NONBLOCKING for tcp_connect */
++  ASSERT_WARN("FIXME test behaviour not libuv compliant");
++  ASSERT(-ECONNREFUSED == uv_tcp_connect(&connection_request,
++#endif
+                              &tcp_client,
+                              (const struct sockaddr *)
+                              &sa,
+@@ -66,7 +79,7 @@ TEST_IMPL(tcp_write_after_connect) {
+ 
+   uv_run(&loop, UV_RUN_DEFAULT);
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(&loop);
+   return 0;
+ }
+ 
+diff --git a/test/test-threadpool.c b/test/test-threadpool.c
+index e3d17d754..09b86d5cf 100644
+--- a/test/test-threadpool.c
++++ b/test/test-threadpool.c
+@@ -44,33 +44,49 @@ static void after_work_cb(uv_work_t* req, int status) {
+ 
+ 
+ TEST_IMPL(threadpool_queue_work_simple) {
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
+   int r;
+ 
++  work_cb_count = 0;
++  after_work_cb_count = 0;
++
+   work_req.data = &data;
+-  r = uv_queue_work(uv_default_loop(), &work_req, work_cb, after_work_cb);
++  r = uv_queue_work(loop, &work_req, work_cb, after_work_cb);
+   ASSERT(r == 0);
+-  uv_run(uv_default_loop(), UV_RUN_DEFAULT);
++  uv_run(loop, UV_RUN_DEFAULT);
+ 
+   ASSERT(work_cb_count == 1);
+   ASSERT(after_work_cb_count == 1);
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+ 
+ 
+ TEST_IMPL(threadpool_queue_work_einval) {
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
+   int r;
+ 
++  work_cb_count = 0;
++  after_work_cb_count = 0;
++
+   work_req.data = &data;
+-  r = uv_queue_work(uv_default_loop(), &work_req, NULL, after_work_cb);
++  r = uv_queue_work(loop, &work_req, NULL, after_work_cb);
+   ASSERT(r == UV_EINVAL);
+ 
+-  uv_run(uv_default_loop(), UV_RUN_DEFAULT);
++  uv_run(loop, UV_RUN_DEFAULT);
+ 
+   ASSERT(work_cb_count == 0);
+   ASSERT(after_work_cb_count == 0);
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+diff --git a/test/test-timer-again.c b/test/test-timer-again.c
+index e87d2edf1..8fd0854b8 100644
+--- a/test/test-timer-again.c
++++ b/test/test-timer-again.c
+@@ -48,7 +48,7 @@ static void repeat_1_cb(uv_timer_t* handle) {
+   ASSERT(uv_timer_get_repeat((uv_timer_t*)handle) == 50);
+ 
+   fprintf(stderr, "repeat_1_cb called after %ld ms\n",
+-          (long int)(uv_now(uv_default_loop()) - start_time));
++          (long int)(uv_now(handle->loop) - start_time));
+   fflush(stderr);
+ 
+   repeat_1_cb_called++;
+@@ -71,7 +71,7 @@ static void repeat_2_cb(uv_timer_t* handle) {
+   ASSERT(repeat_2_cb_allowed);
+ 
+   fprintf(stderr, "repeat_2_cb called after %ld ms\n",
+-          (long int)(uv_now(uv_default_loop()) - start_time));
++          (long int)(uv_now(handle->loop) - start_time));
+   fflush(stderr);
+ 
+   repeat_2_cb_called++;
+@@ -93,20 +93,30 @@ static void repeat_2_cb(uv_timer_t* handle) {
+ 
+ 
+ TEST_IMPL(timer_again) {
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
+   int r;
+ 
+-  start_time = uv_now(uv_default_loop());
++  close_cb_called = 0;
++  repeat_1_cb_called = 0;
++  repeat_2_cb_called = 0;
++  repeat_2_cb_allowed = 0;
++
++  start_time = uv_now(loop);
+   ASSERT(0 < start_time);
+ 
+   /* Verify that it is not possible to uv_timer_again a never-started timer. */
+-  r = uv_timer_init(uv_default_loop(), &dummy);
++  r = uv_timer_init(loop, &dummy);
+   ASSERT(r == 0);
+   r = uv_timer_again(&dummy);
+   ASSERT(r == UV_EINVAL);
+   uv_unref((uv_handle_t*)&dummy);
+ 
+   /* Start timer repeat_1. */
+-  r = uv_timer_init(uv_default_loop(), &repeat_1);
++  r = uv_timer_init(loop, &repeat_1);
+   ASSERT(r == 0);
+   r = uv_timer_start(&repeat_1, repeat_1_cb, 50, 0);
+   ASSERT(r == 0);
+@@ -120,22 +130,22 @@ TEST_IMPL(timer_again) {
+    * Start another repeating timer. It'll be again()ed by the repeat_1 so
+    * it should not time out until repeat_1 stops.
+    */
+-  r = uv_timer_init(uv_default_loop(), &repeat_2);
++  r = uv_timer_init(loop, &repeat_2);
+   ASSERT(r == 0);
+   r = uv_timer_start(&repeat_2, repeat_2_cb, 100, 100);
+   ASSERT(r == 0);
+   ASSERT(uv_timer_get_repeat(&repeat_2) == 100);
+ 
+-  uv_run(uv_default_loop(), UV_RUN_DEFAULT);
++  uv_run(loop, UV_RUN_DEFAULT);
+ 
+   ASSERT(repeat_1_cb_called == 10);
+   ASSERT(repeat_2_cb_called == 2);
+   ASSERT(close_cb_called == 2);
+ 
+   fprintf(stderr, "Test took %ld ms (expected ~700 ms)\n",
+-          (long int)(uv_now(uv_default_loop()) - start_time));
++          (long int)(uv_now(loop) - start_time));
+   fflush(stderr);
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+diff --git a/test/test-timer-from-check.c b/test/test-timer-from-check.c
+index a18c7e1fb..d99c7f4c3 100644
+--- a/test/test-timer-from-check.c
++++ b/test/test-timer-from-check.c
+@@ -62,19 +62,28 @@ static void check_cb(uv_check_t* handle) {
+ 
+ 
+ TEST_IMPL(timer_from_check) {
+-  ASSERT(0 == uv_prepare_init(uv_default_loop(), &prepare_handle));
+-  ASSERT(0 == uv_check_init(uv_default_loop(), &check_handle));
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
++  prepare_cb_called = 0;
++  check_cb_called = 0;
++  timer_cb_called = 0;
++
++  ASSERT(0 == uv_prepare_init(loop, &prepare_handle));
++  ASSERT(0 == uv_check_init(loop, &check_handle));
+   ASSERT(0 == uv_check_start(&check_handle, check_cb));
+-  ASSERT(0 == uv_timer_init(uv_default_loop(), &timer_handle));
++  ASSERT(0 == uv_timer_init(loop, &timer_handle));
+   ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 50, 0));
+-  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
++  ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
+   ASSERT(1 == prepare_cb_called);
+   ASSERT(1 == check_cb_called);
+   ASSERT(1 == timer_cb_called);
+   uv_close((uv_handle_t*) &prepare_handle, NULL);
+   uv_close((uv_handle_t*) &check_handle, NULL);
+   uv_close((uv_handle_t*) &timer_handle, NULL);
+-  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
+-  MAKE_VALGRIND_HAPPY();
++  ASSERT(0 == uv_run(loop, UV_RUN_ONCE));
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+diff --git a/test/test-timer.c b/test/test-timer.c
+index c667da00e..dac515dd1 100644
+--- a/test/test-timer.c
++++ b/test/test-timer.c
+@@ -45,6 +45,7 @@ static void once_close_cb(uv_handle_t* handle) {
+ 
+ 
+ static void once_cb(uv_timer_t* handle) {
++  uv_loop_t *loop = handle->loop;
+   printf("ONCE_CB %d\n", once_cb_called);
+ 
+   ASSERT(handle != NULL);
+@@ -55,7 +56,7 @@ static void once_cb(uv_timer_t* handle) {
+   uv_close((uv_handle_t*)handle, once_close_cb);
+ 
+   /* Just call this randomly for the code coverage. */
+-  uv_update_time(uv_default_loop());
++  uv_update_time(loop);
+ }
+ 
+ 
+@@ -88,32 +89,42 @@ static void never_cb(uv_timer_t* handle) {
+ 
+ 
+ TEST_IMPL(timer) {
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
+   uv_timer_t once_timers[10];
+   uv_timer_t *once;
+   uv_timer_t repeat, never;
+   unsigned int i;
+   int r;
+ 
+-  start_time = uv_now(uv_default_loop());
++  once_cb_called = 0;
++  once_close_cb_called = 0;
++  repeat_cb_called = 0;
++  repeat_close_cb_called = 0;
++
++  start_time = uv_now(loop);
+   ASSERT(0 < start_time);
+ 
+   /* Let 10 timers time out in 500 ms total. */
+   for (i = 0; i < ARRAY_SIZE(once_timers); i++) {
+     once = once_timers + i;
+-    r = uv_timer_init(uv_default_loop(), once);
++    r = uv_timer_init(loop, once);
+     ASSERT(r == 0);
+     r = uv_timer_start(once, once_cb, i * 50, 0);
+     ASSERT(r == 0);
+   }
+ 
+   /* The 11th timer is a repeating timer that runs 4 times */
+-  r = uv_timer_init(uv_default_loop(), &repeat);
++  r = uv_timer_init(loop, &repeat);
+   ASSERT(r == 0);
+   r = uv_timer_start(&repeat, repeat_cb, 100, 100);
+   ASSERT(r == 0);
+ 
+   /* The 12th timer should not do anything. */
+-  r = uv_timer_init(uv_default_loop(), &never);
++  r = uv_timer_init(loop, &never);
+   ASSERT(r == 0);
+   r = uv_timer_start(&never, never_cb, 100, 100);
+   ASSERT(r == 0);
+@@ -121,7 +132,7 @@ TEST_IMPL(timer) {
+   ASSERT(r == 0);
+   uv_unref((uv_handle_t*)&never);
+ 
+-  uv_run(uv_default_loop(), UV_RUN_DEFAULT);
++  uv_run(loop, UV_RUN_DEFAULT);
+ 
+   ASSERT(once_cb_called == 10);
+   ASSERT(once_close_cb_called == 10);
+@@ -129,41 +140,53 @@ TEST_IMPL(timer) {
+   ASSERT(repeat_cb_called == 5);
+   ASSERT(repeat_close_cb_called == 1);
+ 
+-  ASSERT(500 <= uv_now(uv_default_loop()) - start_time);
++  ASSERT(500 <= uv_now(loop) - start_time);
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+ 
+ 
+ TEST_IMPL(timer_start_twice) {
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
+   uv_timer_t once;
+   int r;
+ 
+-  r = uv_timer_init(uv_default_loop(), &once);
++  once_cb_called = 0;
++
++  r = uv_timer_init(loop, &once);
+   ASSERT(r == 0);
+   r = uv_timer_start(&once, never_cb, 86400 * 1000, 0);
+   ASSERT(r == 0);
+   r = uv_timer_start(&once, once_cb, 10, 0);
+   ASSERT(r == 0);
+-  r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
++  r = uv_run(loop, UV_RUN_DEFAULT);
+   ASSERT(r == 0);
+ 
+   ASSERT(once_cb_called == 1);
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+ 
+ 
+ TEST_IMPL(timer_init) {
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
+   uv_timer_t handle;
+ 
+-  ASSERT(0 == uv_timer_init(uv_default_loop(), &handle));
++  ASSERT(0 == uv_timer_init(loop, &handle));
+   ASSERT(0 == uv_timer_get_repeat(&handle));
+   ASSERT(0 == uv_is_active((uv_handle_t*) &handle));
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+ 
+@@ -179,22 +202,29 @@ static void order_cb_b(uv_timer_t *handle) {
+ 
+ 
+ TEST_IMPL(timer_order) {
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
+   int first;
+   int second;
+   uv_timer_t handle_a;
+   uv_timer_t handle_b;
+ 
++  order_cb_called = 0;
++
+   first = 0;
+   second = 1;
+-  ASSERT(0 == uv_timer_init(uv_default_loop(), &handle_a));
+-  ASSERT(0 == uv_timer_init(uv_default_loop(), &handle_b));
++  ASSERT(0 == uv_timer_init(loop, &handle_a));
++  ASSERT(0 == uv_timer_init(loop, &handle_b));
+ 
+   /* Test for starting handle_a then handle_b */
+   handle_a.data = &first;
+   ASSERT(0 == uv_timer_start(&handle_a, order_cb_a, 0, 0));
+   handle_b.data = &second;
+   ASSERT(0 == uv_timer_start(&handle_b, order_cb_b, 0, 0));
+-  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
++  ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
+ 
+   ASSERT(order_cb_called == 2);
+ 
+@@ -208,11 +238,11 @@ TEST_IMPL(timer_order) {
+ 
+   handle_a.data = &second;
+   ASSERT(0 == uv_timer_start(&handle_a, order_cb_a, 0, 0));
+-  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
++  ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
+ 
+   ASSERT(order_cb_called == 2);
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+ 
+@@ -226,21 +256,26 @@ static void tiny_timer_cb(uv_timer_t* handle) {
+ 
+ 
+ TEST_IMPL(timer_huge_timeout) {
+-  ASSERT(0 == uv_timer_init(uv_default_loop(), &tiny_timer));
+-  ASSERT(0 == uv_timer_init(uv_default_loop(), &huge_timer1));
+-  ASSERT(0 == uv_timer_init(uv_default_loop(), &huge_timer2));
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
++  ASSERT(0 == uv_timer_init(loop, &tiny_timer));
++  ASSERT(0 == uv_timer_init(loop, &huge_timer1));
++  ASSERT(0 == uv_timer_init(loop, &huge_timer2));
+   ASSERT(0 == uv_timer_start(&tiny_timer, tiny_timer_cb, 1, 0));
+-  ASSERT(0 == uv_timer_start(&huge_timer1, tiny_timer_cb, 0xffffffffffffLL, 0));
+-  ASSERT(0 == uv_timer_start(&huge_timer2, tiny_timer_cb, (uint64_t) -1, 0));
+-  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
+-  MAKE_VALGRIND_HAPPY();
++  // ASSERT(0 == uv_timer_start(&huge_timer1, tiny_timer_cb, 0xffffffffffffLL, 0));
++  ASSERT(0 == uv_timer_start(&huge_timer2, tiny_timer_cb, ((uv_time_t)-1)>>1, 0));
++  ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+ 
+ 
+-static void huge_repeat_cb(uv_timer_t* handle) {
+-  static int ncalls;
++static int ncalls;
+ 
++static void huge_repeat_cb(uv_timer_t* handle) {
+   if (ncalls == 0)
+     ASSERT(handle == &huge_timer1);
+   else
+@@ -254,12 +289,19 @@ static void huge_repeat_cb(uv_timer_t* handle) {
+ 
+ 
+ TEST_IMPL(timer_huge_repeat) {
+-  ASSERT(0 == uv_timer_init(uv_default_loop(), &tiny_timer));
+-  ASSERT(0 == uv_timer_init(uv_default_loop(), &huge_timer1));
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
++  ncalls = 0;
++
++  ASSERT(0 == uv_timer_init(loop, &tiny_timer));
++  ASSERT(0 == uv_timer_init(loop, &huge_timer1));
+   ASSERT(0 == uv_timer_start(&tiny_timer, huge_repeat_cb, 2, 2));
+-  ASSERT(0 == uv_timer_start(&huge_timer1, huge_repeat_cb, 1, (uint64_t) -1));
+-  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
+-  MAKE_VALGRIND_HAPPY();
++  ASSERT(0 == uv_timer_start(&huge_timer1, huge_repeat_cb, 1, ((uv_time_t)-1)>>1));
++  ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+ 
+@@ -273,50 +315,67 @@ static void timer_run_once_timer_cb(uv_timer_t* handle) {
+ 
+ 
+ TEST_IMPL(timer_run_once) {
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
+   uv_timer_t timer_handle;
+ 
+-  ASSERT(0 == uv_timer_init(uv_default_loop(), &timer_handle));
++  timer_run_once_timer_cb_called = 0;
++
++  ASSERT(0 == uv_timer_init(loop, &timer_handle));
+   ASSERT(0 == uv_timer_start(&timer_handle, timer_run_once_timer_cb, 0, 0));
+-  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
++  ASSERT(0 == uv_run(loop, UV_RUN_ONCE));
+   ASSERT(1 == timer_run_once_timer_cb_called);
+ 
+   ASSERT(0 == uv_timer_start(&timer_handle, timer_run_once_timer_cb, 1, 0));
+-  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
++  ASSERT(0 == uv_run(loop, UV_RUN_ONCE));
+   ASSERT(2 == timer_run_once_timer_cb_called);
+ 
+   uv_close((uv_handle_t*) &timer_handle, NULL);
+-  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
++  ASSERT(0 == uv_run(loop, UV_RUN_ONCE));
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+ 
+ 
+ TEST_IMPL(timer_is_closing) {
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
+   uv_timer_t handle;
+ 
+-  ASSERT(0 == uv_timer_init(uv_default_loop(), &handle));
++  ASSERT(0 == uv_timer_init(loop, &handle));
+   uv_close((uv_handle_t *)&handle, NULL);
+ 
+   ASSERT(UV_EINVAL == uv_timer_start(&handle, never_cb, 100, 100));
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+ 
+ 
+ TEST_IMPL(timer_null_callback) {
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
+   uv_timer_t handle;
+ 
+-  ASSERT(0 == uv_timer_init(uv_default_loop(), &handle));
++  ASSERT(0 == uv_timer_init(loop, &handle));
+   ASSERT(UV_EINVAL == uv_timer_start(&handle, NULL, 100, 100));
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+ 
+ 
+-static uint64_t timer_early_check_expected_time;
++static uv_time_t timer_early_check_expected_time;
+ 
+ 
+ static void timer_early_check_cb(uv_timer_t* handle) {
+@@ -326,18 +385,23 @@ static void timer_early_check_cb(uv_timer_t* handle) {
+ 
+ 
+ TEST_IMPL(timer_early_check) {
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
++  loop = uv_default_loop(&context);
++
+   uv_timer_t timer_handle;
+-  const uint64_t timeout_ms = 10;
++  const uv_interval_t timeout_ms = 10;
+ 
+-  timer_early_check_expected_time = uv_now(uv_default_loop()) + timeout_ms;
++  timer_early_check_expected_time = uv_now(loop) + (uv_time_t)timeout_ms;
+ 
+-  ASSERT(0 == uv_timer_init(uv_default_loop(), &timer_handle));
++  ASSERT(0 == uv_timer_init(loop, &timer_handle));
+   ASSERT(0 == uv_timer_start(&timer_handle, timer_early_check_cb, timeout_ms, 0));
+-  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
++  ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
+ 
+   uv_close((uv_handle_t*) &timer_handle, NULL);
+-  ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
++  ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+diff --git a/test/test-walk-handles.c b/test/test-walk-handles.c
+index 4b0ca6ebc..3cd1c2f6e 100644
+--- a/test/test-walk-handles.c
++++ b/test/test-walk-handles.c
+@@ -50,10 +50,12 @@ static void timer_cb(uv_timer_t* handle) {
+ 
+ 
+ TEST_IMPL(walk_handles) {
+-  uv_loop_t* loop;
++  uv_context_t context;
++  uv_loop_t *loop;
++  uv_library_init(&context);
+   int r;
+ 
+-  loop = uv_default_loop();
++  loop = uv_default_loop(&context);
+ 
+   r = uv_timer_init(loop, &timer);
+   ASSERT(r == 0);
+@@ -72,6 +74,6 @@ TEST_IMPL(walk_handles) {
+   uv_walk(loop, walk_cb, magic_cookie);
+   ASSERT(seen_timer_handle == 0);
+ 
+-  MAKE_VALGRIND_HAPPY();
++  MAKE_VALGRIND_HAPPY(loop);
+   return 0;
+ }
+-- 
+2.17.1
+
diff --git a/system/libuv/Make.defs b/system/libuv/Make.defs
new file mode 100644
index 0000000..228ca68
--- /dev/null
+++ b/system/libuv/Make.defs
@@ -0,0 +1,32 @@
+############################################################################
+# system/libuv/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+# Set up build configuration and environment
+
+LIBUV_DIR := $(APPDIR)/system/libuv
+
+CONFIG_LIBUV_URL ?= "https://github.com/libuv/libuv/archive"
+CONFIG_LIBUV_VERSION ?= 1.38.1
+CONFIG_LIBUV_TARBALL ?= v$(CONFIG_LIBUV_VERSION).zip
+
+LIBUV_UNPACKNAME := libuv-$(CONFIG_LIBUV_VERSION)
+LIBUV_UNPACKDIR := $(LIBUV_DIR)/$(LIBUV_UNPACKNAME)
+
+include $(wildcard $(APPDIR)/system/libuv/*/Make.defs)
diff --git a/system/libuv/Makefile b/system/libuv/Makefile
new file mode 100644
index 0000000..7251d9a
--- /dev/null
+++ b/system/libuv/Makefile
@@ -0,0 +1,23 @@
+############################################################################
+# system/libuv/Makefile
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+MENUDESC = "libuv async i/o Library"
+
+include $(APPDIR)/Directory.mk
diff --git a/system/libuv/libuv/Kconfig b/system/libuv/libuv/Kconfig
new file mode 100644
index 0000000..41c0102
--- /dev/null
+++ b/system/libuv/libuv/Kconfig
@@ -0,0 +1,123 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+config LIBUV
+	bool "libuv asynchronous I/O Library"
+	default n
+	---help---
+		Enable build for libuv asynchronous I/O Library
+
+if LIBUV
+
+config LIBUV_NPOLLWAITERS
+	int "Number of uv loop poll waiters"
+	default 8
+	---help---
+		Maximum number of events a loop can wait on.
+
+config LIBUV_ASYNC
+	bool "libuv async support"
+	default n
+	select EVENT_FD
+	select EVENT_FD_POLL
+	---help---
+		Enable async support in libuv.
+		Eventfd is required for this feature.
+
+config LIBUV_TIMER
+	bool "libuv software timers support"
+	default n
+	select CLOCK_MONOTONIC
+	---help---
+		Enable software timers support in libuv.
+
+config LIBUV_TIMER_NUTTX
+	bool "optimized software timers"
+	default y
+	depends on LIBUV_TIMER
+	---help---
+		Replace default libuv timer with optimized implementation
+		with low memory footprint.
+
+config LIBUV_STREAM
+	bool "libuv stream support"
+	default n
+	---help---
+		Enable stream support in libuv.
+
+config LIBUV_STREAM_READ_SIZE
+	int "Stream read buffer size"
+	default 128
+	depends on LIBUV_STREAM
+	---help---
+		Defines the size of buffer used for stream reads.
+
+config LIBUV_FS
+	bool "libuv FS support"
+	default n
+	---help---
+		Enable libuv FS support.
+		This feature may require LIBUV_WQ to support async FS operations.
+
+config LIBUV_FS_POLL
+	bool "libuv fs-poll support"
+	default n
+	select LIBUV_FS
+	select LIBUV_TIMER
+	---help---
+		Enable libuv uv_fs_poll_*() API.
+
+config LIBUV_NET
+	bool
+
+config LIBUV_TCP
+	bool "libuv TCP support"
+	default n
+	depends on NET_TCP
+	depends on NET_TCPBACKLOG
+	select LIBUV_STREAM
+	select LIBUV_NET
+	---help---
+		Enable TCP support in libuv.
+		NET_TCPBACKLOG is required to poll on accept().
+
+config LIBUV_WQ
+	bool "libuv workqueue support"
+	default n
+	select LIBUV_ASYNC
+	---help---
+		Enable workqueue support in libuv
+
+config LIBUV_WQ_THREADS_COUNT
+	int "libuv workqueue thread count"
+	depends on LIBUV_WQ
+	default 1
+	---help---
+		Specify worker thread count shared between all uv loops
+
+config LIBUV_LOOP_WATCHERS
+	bool "libuv loop watchers support"
+	default n
+	---help---
+		Enable loop watchers support in libuv (idle,prepare and check)
+
+config LIBUV_CONTEXT
+	bool "Use static context for loops"
+	default y
+	---help---
+		Modify libuv API to remove static memory usage.
+		User must call "uv_context_init()" before any other libuv API and
+		must call "uv_library_shutdown()" when done.
+		This is required for flat memory builds else some libuv structures
+		will be shared between processes which can lead to inconsistency.
+		This option disable support for uv_default_loop() API.
+
+config LIBUV_LOW_FOOTPRINT
+	bool "Reduce libuv memory usage"
+	default y
+	---help---
+		Enable optimizations to reduce libuv memory usage
+
+endif # LIBUV
diff --git a/system/libuv/libuv/Make.defs b/system/libuv/libuv/Make.defs
new file mode 100644
index 0000000..94b88c7
--- /dev/null
+++ b/system/libuv/libuv/Make.defs
@@ -0,0 +1,31 @@
+############################################################################
+# system/libuv/libuv/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+ifneq ($(CONFIG_LIBUV),)
+CONFIGURED_APPS += $(APPDIR)/system/libuv/libuv
+
+# Enable <uv.h> include.
+
+CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" \
+	$(APPDIR)/system/libuv/$(LIBUV_UNPACKNAME)/include}
+CXXFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" \
+	$(APPDIR)/system/libuv/$(LIBUV_UNPACKNAME)/include}
+
+endif
diff --git a/system/libuv/libuv/Makefile b/system/libuv/libuv/Makefile
new file mode 100644
index 0000000..558ec61
--- /dev/null
+++ b/system/libuv/libuv/Makefile
@@ -0,0 +1,121 @@
+############################################################################
+# system/libuv/Makefile
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include $(APPDIR)/Make.defs
+
+LIBUV_PATCHS ?= $(sort $(wildcard $(LIBUV_DIR)/000*.patch))
+WGET ?= wget
+UNPACK ?= unzip -q
+
+$(LIBUV_DIR)/$(CONFIG_LIBUV_TARBALL):
+	@echo "Downloading: $(CONFIG_LIBUV_TARBALL)"
+	$(Q) $(WGET) $(CONFIG_LIBUV_URL)/$(CONFIG_LIBUV_TARBALL) \
+		-O $(LIBUV_DIR)/$(CONFIG_LIBUV_TARBALL)
+
+$(LIBUV_UNPACKDIR): $(LIBUV_DIR)/$(CONFIG_LIBUV_TARBALL)
+	@echo "Unpacking: $(CONFIG_LIBUV_TARBALL) -> $(LIBUV_UNPACKDIR)"
+	$(call DELDIR, $(LIBUV_UNPACKDIR))
+	$(Q) unzip -q -d "$(LIBUV_DIR)" "$(LIBUV_DIR)/$(CONFIG_LIBUV_TARBALL)"
+	$(Q) cat $(LIBUV_PATCHS) | \
+		patch -s -N -d $(LIBUV_UNPACKDIR) -p1
+	$(Q) touch $(LIBUV_UNPACKDIR)
+
+# Build libuv library
+
+CFLAGS += -I$(LIBUV_UNPACKDIR)/src
+CFLAGS += -I$(LIBUV_UNPACKDIR)/src/unix
+CFLAGS += -D__NUTTX__
+
+CSRCS += $(LIBUV_UNPACKDIR)/src/unix/core.c
+CSRCS += $(LIBUV_UNPACKDIR)/src/unix/poll.c
+CSRCS += $(LIBUV_UNPACKDIR)/src/unix/loop.c
+CSRCS += $(LIBUV_UNPACKDIR)/src/unix/thread.c
+CSRCS += $(LIBUV_UNPACKDIR)/src/unix/no-proctitle.c
+
+ifeq ($(CONFIG_DEV_URANDOM),y)
+CSRCS += $(LIBUV_UNPACKDIR)/src/unix/random-devurandom.c
+CSRCS += $(LIBUV_UNPACKDIR)/src/random.c
+endif
+
+ifeq ($(CONFIG_LIBUV_LOOP_WATCHERS),y)
+CSRCS += $(LIBUV_UNPACKDIR)/src/unix/loop-watcher.c
+endif
+
+# FIXME signal does not work yet
+ifeq ($(CONFIG_LIBUV_SIGNAL),y)
+CSRCS += $(LIBUV_UNPACKDIR)/src/unix/signal.c
+endif
+
+# FIXME process does not work yet
+ifeq ($(CONFIG_LIBUV_PROCESS),y)
+CSRCS += $(LIBUV_UNPACKDIR)/src/unix/process.c
+endif
+
+CSRCS += $(LIBUV_UNPACKDIR)/src/unix/nuttx.c
+
+ifeq ($(CONFIG_LIBUV_STREAM),y)
+CSRCS += $(LIBUV_UNPACKDIR)/src/unix/nuttx_stream.c
+endif
+
+ifeq ($(CONFIG_LIBUV_TCP),y)
+CSRCS += $(LIBUV_UNPACKDIR)/src/unix/nuttx_tcp.c
+endif
+
+ifeq ($(CONFIG_LIBUV_WQ),y)
+CSRCS += $(LIBUV_UNPACKDIR)/src/unix/nuttx_threadpool.c
+endif
+
+ifeq ($(CONFIG_LIBUV_ASYNC),y)
+CSRCS += $(LIBUV_UNPACKDIR)/src/unix/async.c
+endif
+
+ifeq ($(CONFIG_LIBUV_FS),y)
+CSRCS += $(LIBUV_UNPACKDIR)/src/unix/fs.c
+endif
+
+ifeq ($(CONFIG_LIBUV_FS_POLL),y)
+CSRCS += $(LIBUV_UNPACKDIR)/src/fs-poll.c
+endif
+
+ifeq ($(CONFIG_LIBUV_TIMER),y)
+ifeq ($(CONFIG_LIBUV_TIMER_NUTTX),y)
+CSRCS += $(LIBUV_UNPACKDIR)/src/unix/nuttx_timer.c
+else
+CSRCS += $(LIBUV_UNPACKDIR)/src/timer.c
+endif
+endif
+
+CSRCS += $(LIBUV_UNPACKDIR)/src/uv-common.c
+CSRCS += $(LIBUV_UNPACKDIR)/src/strscpy.c
+
+ifeq ($(CONFIG_LIBUV_NET),y)
+CSRCS += $(LIBUV_UNPACKDIR)/src/inet.c
+endif
+
+context:: $(LIBUV_UNPACKDIR)
+
+clean::
+	$(call DELFILE, $(OBJS))
+
+distclean::
+	$(call DELDIR, $(LIBUV_UNPACKDIR))
+	$(call DELFILE, $(LIBUV_DIR)/$(CONFIG_LIBUV_TARBALL))
+
+include $(APPDIR)/Application.mk
diff --git a/system/libuv/tests/Kconfig b/system/libuv/tests/Kconfig
new file mode 100644
index 0000000..cf3d7ca
--- /dev/null
+++ b/system/libuv/tests/Kconfig
@@ -0,0 +1,35 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+menuconfig LIBUV_UNIT_TESTS
+	tristate "libuv unit-tests command"
+	default n
+	depends on LIBUV
+	select LIBUV_TIMER
+	select LIBUV_ASYNC
+	select LIBUV_WQ
+	select LIBUV_LOOP_WATCHERS
+	select LIBUV_CONTEXT
+	---help---
+		Add executable that runs all libuv unit-tests.
+
+if LIBUV_UNIT_TESTS
+
+config LIBUV_UNIT_TESTS_PROGNAME
+	string "libuv unit-tests program name"
+	default "libuvtest"
+	---help---
+		This is the name of the program that will be used when the NSH ELF
+		program is installed.
+
+config LIBUV_UNIT_TESTS_PRIORITY
+	int "libuv unit-tests task priority"
+	default 100
+
+config LIBUV_UNIT_TESTS_STACKSIZE
+	int "libuv unit-tests stack size"
+	default DEFAULT_TASK_STACKSIZE
+
+endif # LIBUV_UNIT_TESTS
diff --git a/system/libuv/tests/Make.defs b/system/libuv/tests/Make.defs
new file mode 100644
index 0000000..46c8f6c
--- /dev/null
+++ b/system/libuv/tests/Make.defs
@@ -0,0 +1,23 @@
+############################################################################
+# system/libuv/tests/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+ifneq ($(CONFIG_LIBUV_UNIT_TESTS),)
+CONFIGURED_APPS += $(APPDIR)/system/libuv/tests
+endif
diff --git a/system/libuv/tests/Makefile b/system/libuv/tests/Makefile
new file mode 100644
index 0000000..26728c5
--- /dev/null
+++ b/system/libuv/tests/Makefile
@@ -0,0 +1,70 @@
+############################################################################
+# system/libuv/tests/Makefile
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include $(APPDIR)/Make.defs
+
+# libuv unit-tests command
+
+PROGNAME := $(CONFIG_LIBUV_UNIT_TESTS_PROGNAME)
+PRIORITY := $(CONFIG_LIBUV_UNIT_TESTS_PRIORITY)
+STACKSIZE := $(CONFIG_LIBUV_UNIT_TESTS_STACKSIZE)
+MODULE := $(CONFIG_LIBUV_UNIT_TESTS)
+
+# Files
+
+MAINSRC := test_main.c
+CSRCS += runner-nuttx.c
+CSRCS += $(LIBUV_UNPACKDIR)/test/runner.c
+
+# Tests
+
+CSRCS += $(LIBUV_UNPACKDIR)/test/test-loop-time.c
+CSRCS += $(LIBUV_UNPACKDIR)/test/test-async.c
+CSRCS += $(LIBUV_UNPACKDIR)/test/test-ip4-addr.c
+CSRCS += $(LIBUV_UNPACKDIR)/test/test-active.c
+CSRCS += $(LIBUV_UNPACKDIR)/test/test-idle.c
+CSRCS += $(LIBUV_UNPACKDIR)/test/test-timer.c
+CSRCS += $(LIBUV_UNPACKDIR)/test/test-timer-from-check.c
+CSRCS += $(LIBUV_UNPACKDIR)/test/test-timer-again.c
+CSRCS += $(LIBUV_UNPACKDIR)/test/test-threadpool.c
+CSRCS += $(LIBUV_UNPACKDIR)/test/test-walk-handles.c
+CSRCS += $(LIBUV_UNPACKDIR)/test/test-poll-close.c
+CSRCS += $(LIBUV_UNPACKDIR)/test/test-loop-close.c
+CSRCS += $(LIBUV_UNPACKDIR)/test/test-loop-stop.c
+CSRCS += $(LIBUV_UNPACKDIR)/test/test-tcp-read-stop.c
+CSRCS += $(LIBUV_UNPACKDIR)/test/test-tcp-write-after-connect.c
+CSRCS += $(LIBUV_UNPACKDIR)/test/test-fs-copyfile.c
+CSRCS += $(LIBUV_UNPACKDIR)/test/test-fs-poll.c
+CSRCS += $(LIBUV_UNPACKDIR)/test/test-random.c
+
+# Test helpers
+
+CSRCS += $(LIBUV_UNPACKDIR)/test/echo-server.c
+
+# Compilation flags
+
+CFLAGS += -I$(LIBUV_UNPACKDIR)/test
+CFLAGS += -I.
+CFLAGS += -D__NUTTX__
+
+clean::
+	$(call DELFILE, $(OBJS))
+
+include $(APPDIR)/Application.mk
diff --git a/system/libuv/tests/runner-nuttx.c b/system/libuv/tests/runner-nuttx.c
new file mode 100644
index 0000000..2de0c92
--- /dev/null
+++ b/system/libuv/tests/runner-nuttx.c
@@ -0,0 +1,152 @@
+/****************************************************************************
+ * system/libuv/tests/runner-nuttx.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <debug.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdint.h>
+
+#include <uv.h>
+#include "runner-nuttx.h"
+#include "runner.h"
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static uint32_t get_time_ms(void);
+static void *process_launcher(void *arg);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static uint32_t get_time_ms(void)
+{
+  struct timespec ts;
+  clock_gettime(CLOCK_MONOTONIC, &ts);
+  return (uint32_t)(((uint64_t) ts.tv_sec) * 1000 +
+    (ts.tv_nsec / 1000 / 1000));
+}
+
+static void *process_launcher(void *arg)
+{
+  process_info_t *p = (process_info_t *)arg;
+  p->task->main();
+  sem_post(&p->sem);
+  return NULL;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+void platform_init(int argc, char **argv)
+{
+}
+
+int process_start(task_entry_t *task, process_info_t *p, int is_helper)
+{
+  if (is_helper)
+    {
+      printf("===> START HELPER %s/%s\n",
+             task->task_name, task->process_name);
+    }
+  else
+    {
+      printf("===> START TEST   %s\n", task->task_name);
+    }
+
+  p->task = task;
+
+  if (sem_init(&p->sem, 0, 0))
+    {
+      return -1;
+    }
+
+  if (pthread_create(&p->tid, NULL, process_launcher, p) != 0)
+    {
+      fprintf(stderr, "Failed to start process %s\n", task->process_name);
+      sem_destroy(&p->sem);
+      return -1;
+    }
+
+  return 0;
+}
+
+int process_wait(process_info_t *vec, int n, int timeout)
+{
+  uv_time_t time = get_time_ms();
+
+  while (--n >= 0)
+    {
+      int found = 0;
+      while ((uv_time_t)(get_time_ms()-time) < (uv_time_t)timeout)
+        {
+          if (sem_trywait(&vec[n].sem) == 0)
+            {
+              FAR pthread_addr_t value;
+              pthread_join(vec[n].tid, &value);
+              found = 1;
+              break;
+            }
+
+          if (errno != EAGAIN)
+            {
+              break;
+            }
+
+          /* Let NuttX update time */
+
+          usleep(100 * 1000);
+        }
+
+      if (!found)
+        {
+          /* Timeout or error */
+
+          return -1;
+        }
+    }
+
+  return 0;
+}
+
+int process_terminate(process_info_t *p)
+{
+  /* TODO */
+
+  return 0;
+}
+
+int process_reap(process_info_t *p)
+{
+  /* TODO */
+
+  return 0;
+}
+
+void process_cleanup(process_info_t *p)
+{
+}
diff --git a/system/libuv/tests/runner-nuttx.h b/system/libuv/tests/runner-nuttx.h
new file mode 100644
index 0000000..6c67aac
--- /dev/null
+++ b/system/libuv/tests/runner-nuttx.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+ * system/libuv/tests/runner-nuttx.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef TEST_RUNNER_NUTTX_H
+#define TEST_RUNNER_NUTTX_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <pthread.h>
+#include <stdio.h>
+
+/****************************************************************************
+ * Public Type Declarations
+ ****************************************************************************/
+
+struct task_entry_s;
+
+struct process_info_s
+{
+  pthread_t tid;
+  sem_t sem;
+  struct task_entry_s *task;
+};
+
+typedef struct process_info_s process_info_t;
+
+#endif  /* TEST_RUNNER_NUTTX_H */
diff --git a/system/libuv/tests/test_main.c b/system/libuv/tests/test_main.c
new file mode 100644
index 0000000..96d379c
--- /dev/null
+++ b/system/libuv/tests/test_main.c
@@ -0,0 +1,56 @@
+/****************************************************************************
+ * system/libuv/tests/test_main.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "runner.h"
+#include "test-list.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int main(int argc, FAR char **argv)
+{
+  platform_init(argc, argv);
+
+  if (argc > 1)
+    {
+      if (strcmp(argv[1], "--list") == 0)
+        {
+          print_tests(stdout);
+          return 0;
+        }
+
+      if (argc > 2)
+        {
+          return run_test_part(argv[1], argv[2]);
+        }
+    }
+
+  return run_tests(0);
+}
+