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/11/08 16:12:00 UTC
[incubator-nuttx-apps] 01/02: libuv: fix bugs and add partial pipe
support
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
commit efd81744d10c4e3895663e7c37b6fc9b588d8b37
Author: Simon Piriou <sp...@gmail.com>
AuthorDate: Mon Oct 26 11:39:28 2020 +0100
libuv: fix bugs and add partial pipe support
---
.../libuv/0001-initial-libuv-port-to-nuttx.patch | 1122 ++++++++++++++------
system/libuv/libuv/Kconfig | 7 +
system/libuv/libuv/Makefile | 4 +
system/libuv/tests/Makefile | 4 +-
4 files changed, 815 insertions(+), 322 deletions(-)
diff --git a/system/libuv/0001-initial-libuv-port-to-nuttx.patch b/system/libuv/0001-initial-libuv-port-to-nuttx.patch
index d7d4e1b..8f22764 100644
--- a/system/libuv/0001-initial-libuv-port-to-nuttx.patch
+++ b/system/libuv/0001-initial-libuv-port-to-nuttx.patch
@@ -1,26 +1,27 @@
-From e589c4790e8367c5d3c0c37ba20338539ee6f76e Mon Sep 17 00:00:00 2001
+From 3307fabda302b693acbec3a9f11b6542428d5b96 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.h | 109 ++-
include/uv/nuttx.h | 67 ++
- include/uv/unix.h | 146 +++-
+ include/uv/unix.h | 155 +++-
src/inet.c | 50 +-
src/queue.h | 4 +-
- src/random.c | 4 +
+ src/random.c | 42 +-
src/unix/async.c | 71 +-
- src/unix/core.c | 178 ++++-
- src/unix/fs.c | 62 +-
- src/unix/internal.h | 30 +-
+ src/unix/core.c | 209 +++++-
+ src/unix/fs.c | 77 +-
+ src/unix/internal.h | 32 +-
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.c | 238 +++++++
+ src/unix/nuttx_stream.c | 1016 +++++++++++++++++++++++++++
src/unix/nuttx_tcp.c | 311 ++++++++
- src/unix/nuttx_threadpool.c | 361 +++++++++
- src/unix/nuttx_timer.c | 199 +++++
+ src/unix/nuttx_threadpool.c | 361 ++++++++++
+ src/unix/nuttx_timer.c | 199 ++++++
+ src/unix/pipe.c | 24 +-
src/unix/poll.c | 26 +
src/unix/process.c | 35 +-
src/unix/random-devurandom.c | 19 +-
@@ -33,24 +34,25 @@ Subject: [PATCH] initial libuv port to nuttx
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-fs-copyfile.c | 30 +-
+ test/test-fs-poll.c | 162 +++--
test/test-idle.c | 20 +-
test/test-ip4-addr.c | 2 +-
- test/test-list.h | 75 +-
+ test/test-list.h | 85 ++-
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-ping-pong.c | 92 ++-
+ test/test-poll-close.c | 16 +-
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-timer.c | 160 +++--
test/test-walk-handles.c | 8 +-
- 46 files changed, 3929 insertions(+), 363 deletions(-)
+ 48 files changed, 4024 insertions(+), 433 deletions(-)
create mode 100644 include/uv/nuttx.h
create mode 100644 src/unix/nuttx.c
create mode 100644 src/unix/nuttx_stream.c
@@ -59,7 +61,7 @@ Subject: [PATCH] initial libuv port to nuttx
create mode 100644 src/unix/nuttx_timer.c
diff --git a/include/uv.h b/include/uv.h
-index fec663136..e4b989afb 100644
+index fec663136..d025e8a0b 100644
--- a/include/uv.h
+++ b/include/uv.h
@@ -1,3 +1,23 @@
@@ -161,7 +163,15 @@ index fec663136..e4b989afb 100644
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 {
+@@ -399,7 +449,6 @@ UV_EXTERN char* uv_err_name_r(int err, char* buf, size_t buflen);
+ /* read-only */ \
+ uv_req_type type; \
+ /* private */ \
+- void* reserved[6]; \
+ UV_REQ_PRIVATE_FIELDS \
+
+ /* Abstract base class of all requests. */
+@@ -423,7 +472,7 @@ struct uv_shutdown_s {
UV_SHUTDOWN_PRIVATE_FIELDS
};
@@ -170,7 +180,7 @@ index fec663136..e4b989afb 100644
#define UV_HANDLE_FIELDS \
/* public */ \
void* data; \
-@@ -439,6 +489,20 @@ struct uv_shutdown_s {
+@@ -439,6 +488,20 @@ struct uv_shutdown_s {
} u; \
UV_HANDLE_PRIVATE_FIELDS \
@@ -191,7 +201,7 @@ index fec663136..e4b989afb 100644
/* The abstract base class of all handles. */
struct uv_handle_s {
UV_HANDLE_FIELDS
-@@ -857,12 +921,12 @@ struct uv_timer_s {
+@@ -857,12 +920,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,
@@ -208,7 +218,7 @@ index fec663136..e4b989afb 100644
/*
-@@ -1770,6 +1834,10 @@ union uv_any_req {
+@@ -1770,6 +1833,10 @@ union uv_any_req {
struct uv_loop_s {
/* User data - use this for whatever. */
void* data;
@@ -219,7 +229,7 @@ index fec663136..e4b989afb 100644
/* Loop reference counting. */
unsigned int active_handles;
void* handle_queue[2];
-@@ -1779,12 +1847,28 @@ struct uv_loop_s {
+@@ -1779,12 +1846,28 @@ struct uv_loop_s {
} active_reqs;
/* Internal flag to signal loop stop. */
unsigned int stop_flag;
@@ -322,7 +332,7 @@ index 000000000..62574f93b
+
+#endif /* UV_NUTTX_H */
diff --git a/include/uv/unix.h b/include/uv/unix.h
-index 3a131638f..294708654 100644
+index 3a131638f..2c56e8a55 100644
--- a/include/uv/unix.h
+++ b/include/uv/unix.h
@@ -1,3 +1,23 @@
@@ -360,17 +370,17 @@ index 3a131638f..294708654 100644
# include "uv/linux.h"
#elif defined (__MVS__)
# include "uv/os390.h"
-@@ -93,7 +115,9 @@ typedef struct uv__io_s uv__io_t;
+@@ -93,7 +115,8 @@ typedef struct uv__io_s uv__io_t;
struct uv__io_s {
uv__io_cb cb;
-+#if 0
- void* pending_queue[2];
-+#endif
+- void* pending_queue[2];
++ /* FIXME moved in uv_stream_t for now.
++ * void* pending_queue[2]; */
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 {
+@@ -218,37 +241,105 @@ typedef struct {
char* errmsg;
} uv_lib_t;
@@ -475,11 +485,12 @@ index 3a131638f..294708654 100644
+ unsigned int nfds;
+#endif
+
-+#if 0
-+#define UV_LOOP_PRIVATE_TODO_FIELDS \
++#ifdef CONFIG_LIBUV_STREAM
++/* FIXME pending_queue is only required for uv_streams for now */
++#define UV_LOOP_PRIVATE_STREAM_FIELDS \
+ void* pending_queue[2];
+#else
-+#define UV_LOOP_PRIVATE_TODO_FIELDS
++#define UV_LOOP_PRIVATE_STREAM_FIELDS
+#endif
+
+#define UV_LOOP_PRIVATE_FIELDS \
@@ -489,23 +500,28 @@ index 3a131638f..294708654 100644
+ UV_LOOP_PRIVATE_WATCHERS_FIELDS \
+ UV_LOOP_PRIVATE_ASYNC_FIELDS \
+ UV_LOOP_PRIVATE_TIMER_FIELDS \
-+ uv_time_t time; \
++ uv_time_t time; \
+ UV_LOOP_PRIVATE_SIGNAL_FIELDS \
+ UV_LOOP_PRIVATE_PROCESS_FIELDS \
++ UV_LOOP_PRIVATE_STREAM_FIELDS \
+ UV_LOOP_PRIVATE_PERFS_FIELDS \
UV_PLATFORM_LOOP_FIELDS \
#define UV_REQ_TYPE_PRIVATE /* empty */
-@@ -290,7 +380,7 @@ typedef struct {
+@@ -289,10 +380,10 @@ typedef struct {
+ uv__io_t io_watcher; \
void* write_queue[2]; \
void* write_completed_queue[2]; \
++ void* pending_queue[2]; \
uv_connection_cb connection_cb; \
- int delayed_error; \
+ /*int delayed_error;*/ \
int accepted_fd; \
- void* queued_fds; \
+- void* queued_fds; \
UV_STREAM_PRIVATE_PLATFORM_FIELDS \
-@@ -327,12 +417,20 @@ typedef struct {
+
+ #define UV_TCP_PRIVATE_FIELDS /* empty */
+@@ -327,12 +418,20 @@ typedef struct {
void* queue[2]; \
int pending; \
@@ -526,6 +542,20 @@ index 3a131638f..294708654 100644
#define UV_GETADDRINFO_PRIVATE_FIELDS \
struct uv__work work_req; \
+@@ -374,9 +473,13 @@ typedef struct {
+ #define UV_WORK_PRIVATE_FIELDS \
+ struct uv__work work_req;
+
++#ifdef CONFIG_LIBUV_TTY
+ #define UV_TTY_PRIVATE_FIELDS \
+ struct termios orig_termios; \
+ int mode;
++#else /* CONFIG_LIBUV_TTY */
++ #define UV_TTY_PRIVATE_FIELDS
++#endif /* CONFIG_LIBUV_TTY */
+
+ #define UV_SIGNAL_PRIVATE_FIELDS \
+ /* RB_ENTRY(uv_signal_s) tree_entry; */ \
diff --git a/src/inet.c b/src/inet.c
index 698ab232e..63aa2b81b 100644
--- a/src/inet.c
@@ -656,7 +686,7 @@ index 698ab232e..63aa2b81b 100644
}
+#endif
diff --git a/src/queue.h b/src/queue.h
-index ff3540a0a..1e3e92904 100644
+index ff3540a0a..6fa87975f 100644
--- a/src/queue.h
+++ b/src/queue.h
@@ -74,8 +74,8 @@ typedef void *QUEUE[2];
@@ -665,13 +695,13 @@ index ff3540a0a..1e3e92904 100644
else { \
- QUEUE* q = QUEUE_HEAD(h); \
- QUEUE_SPLIT(h, q, n); \
-+ 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
+index 491bf7033..26e45b334 100644
--- a/src/random.c
+++ b/src/random.c
@@ -31,6 +31,9 @@
@@ -684,7 +714,7 @@ index 491bf7033..6b2280f02 100644
#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) {
+@@ -65,11 +68,12 @@ static int uv__random(void* buf, size_t buflen) {
#else
rc = uv__random_devurandom(buf, buflen);
#endif
@@ -692,6 +722,61 @@ index 491bf7033..6b2280f02 100644
return rc;
}
+
+-
++#ifdef CONFIG_LIBUV_WQ
+ static void uv__random_work(struct uv__work* w) {
+ uv_random_t* req;
+
+@@ -89,7 +93,7 @@ static void uv__random_done(struct uv__work* w, int status) {
+
+ req->cb(req, status, req->buf, req->buflen);
+ }
+-
++#endif
+
+ int uv_random(uv_loop_t* loop,
+ uv_random_t* req,
+@@ -103,21 +107,23 @@ int uv_random(uv_loop_t* loop,
+ if (flags != 0)
+ return UV_EINVAL;
+
+- if (cb == NULL)
+- return uv__random(buf, buflen);
+-
+- uv__req_init(loop, req, UV_RANDOM);
+- req->loop = loop;
+- req->status = 0;
+- req->cb = cb;
+- req->buf = buf;
+- req->buflen = buflen;
+-
+- uv__work_submit(loop,
+- &req->work_req,
+- UV__WORK_CPU,
+- uv__random_work,
+- uv__random_done);
++#ifdef CONFIG_LIBUV_WQ
++ if (cb != NULL) {
++ uv__req_init(loop, req, UV_RANDOM);
++ req->loop = loop;
++ req->status = 0;
++ req->cb = cb;
++ req->buf = buf;
++ req->buflen = buflen;
++
++ uv__work_submit(loop,
++ &req->work_req,
++ UV__WORK_CPU,
++ uv__random_work,
++ uv__random_done);
++ return 0;
++ }
++#endif
+
+- return 0;
++ return uv__random(buf, buflen);
+ }
diff --git a/src/unix/async.c b/src/unix/async.c
index 5f58fb88d..00b6a858c 100644
--- a/src/unix/async.c
@@ -879,7 +964,7 @@ index 5f58fb88d..00b6a858c 100644
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
+index 5b0b64dd4..237a6b1bb 100644
--- a/src/unix/core.c
+++ b/src/unix/core.c
@@ -1,3 +1,23 @@
@@ -921,23 +1006,29 @@ index 5b0b64dd4..2438614f0 100644
#if defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__) || \
-@@ -89,6 +112,7 @@ extern char** environ;
+@@ -87,8 +110,11 @@ extern char** environ;
+ # include <sys/syscall.h>
+ # define uv__accept4 accept4
#endif
++#endif
++#ifdef CONFIG_LIBUV_STREAM
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) {
+@@ -112,22 +138,31 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
handle->close_cb = close_cb;
switch (handle->type) {
-+#if 0
++#ifdef CONFIG_LIBUV_PIPE
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) {
++#endif
+
++#if 0
case UV_TTY:
uv__stream_close((uv_stream_t*)handle);
break;
@@ -959,7 +1050,7 @@ index 5b0b64dd4..2438614f0 100644
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) {
+@@ -139,15 +174,20 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
case UV_IDLE:
uv__idle_close((uv_idle_t*)handle);
break;
@@ -981,7 +1072,7 @@ index 5b0b64dd4..2438614f0 100644
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) {
+@@ -155,21 +195,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;
@@ -1008,7 +1099,7 @@ index 5b0b64dd4..2438614f0 100644
default:
assert(0);
}
-@@ -177,6 +216,7 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
+@@ -177,6 +220,7 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
uv__make_close_pending(handle);
}
@@ -1016,7 +1107,7 @@ index 5b0b64dd4..2438614f0 100644
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) {
+@@ -204,6 +248,7 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
return 0;
}
@@ -1024,7 +1115,7 @@ index 5b0b64dd4..2438614f0 100644
void uv__make_close_pending(uv_handle_t* handle) {
assert(handle->flags & UV_HANDLE_CLOSING);
-@@ -241,7 +282,9 @@ int uv__getiovmax(void) {
+@@ -241,7 +286,9 @@ int uv__getiovmax(void) {
static void uv__finish_close(uv_handle_t* handle) {
@@ -1034,7 +1125,7 @@ index 5b0b64dd4..2438614f0 100644
/* 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) {
+@@ -256,17 +303,28 @@ static void uv__finish_close(uv_handle_t* handle) {
handle->flags |= UV_HANDLE_CLOSED;
switch (handle->type) {
@@ -1064,23 +1155,27 @@ index 5b0b64dd4..2438614f0 100644
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) {
+@@ -280,17 +338,26 @@ static void uv__finish_close(uv_handle_t* handle) {
return;
}
break;
--
+#endif
-+#if 0
+
++#ifdef CONFIG_LIBUV_STREAM
++#ifdef CONFIG_LIBUV_PIPE
case UV_NAMED_PIPE:
- case UV_TCP:
++#endif
++#if 0
case UV_TTY:
+#endif
+#ifdef CONFIG_LIBUV_TCP
+ case UV_TCP:
++#endif
uv__stream_destroy((uv_stream_t*)handle);
break;
-
-+#endif
++#endif /* CONFIG_LIBUV_STREAM */
+#ifdef CONFIG_LIBUV_UDP
case UV_UDP:
uv__udp_finish_close((uv_udp_t*)handle);
@@ -1090,7 +1185,7 @@ index 5b0b64dd4..2438614f0 100644
default:
assert(0);
break;
-@@ -324,10 +382,11 @@ int uv_is_closing(const uv_handle_t* handle) {
+@@ -324,10 +391,11 @@ int uv_is_closing(const uv_handle_t* handle) {
return uv__is_closing(handle);
}
@@ -1103,7 +1198,7 @@ index 5b0b64dd4..2438614f0 100644
int uv_backend_timeout(const uv_loop_t* loop) {
-@@ -337,16 +396,24 @@ int uv_backend_timeout(const uv_loop_t* loop) {
+@@ -337,16 +405,24 @@ int uv_backend_timeout(const uv_loop_t* loop) {
if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop))
return 0;
@@ -1112,7 +1207,7 @@ index 5b0b64dd4..2438614f0 100644
return 0;
+#endif
-+#if 0
++#ifdef CONFIG_LIBUV_STREAM
if (!QUEUE_EMPTY(&loop->pending_queue))
return 0;
+#endif
@@ -1128,7 +1223,7 @@ index 5b0b64dd4..2438614f0 100644
}
-@@ -373,17 +440,30 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) {
+@@ -373,17 +449,30 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) {
while (r != 0 && loop->stop_flag == 0) {
uv__update_time(loop);
@@ -1137,7 +1232,7 @@ index 5b0b64dd4..2438614f0 100644
uv__run_timers(loop);
+#endif
+
-+#if 0
++#ifdef CONFIG_LIBUV_STREAM
ran_pending = uv__run_pending(loop);
+#else
+ ran_pending = 0;
@@ -1159,7 +1254,7 @@ index 5b0b64dd4..2438614f0 100644
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) {
+@@ -396,7 +485,10 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) {
* the check.
*/
uv__update_time(loop);
@@ -1170,7 +1265,7 @@ index 5b0b64dd4..2438614f0 100644
}
r = uv__loop_alive(loop);
-@@ -423,7 +506,7 @@ int uv_is_active(const uv_handle_t* handle) {
+@@ -423,7 +515,7 @@ int uv_is_active(const uv_handle_t* handle) {
return uv__is_active(handle);
}
@@ -1179,7 +1274,7 @@ index 5b0b64dd4..2438614f0 100644
/* 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) {
+@@ -460,6 +552,7 @@ int uv__socket(int domain, int type, int protocol) {
return sockfd;
}
@@ -1187,16 +1282,16 @@ index 5b0b64dd4..2438614f0 100644
/* 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) {
+@@ -477,7 +570,7 @@ FILE* uv__open_file(const char* path) {
return fp;
}
-
-+#ifdef CONFIG_LIBUV_STREAM
++#if defined(CONFIG_LIBUV_STREAM) && defined(CONFIG_LIBUV_NET)
int uv__accept(int sockfd) {
int peerfd;
int err;
-@@ -509,7 +593,7 @@ int uv__accept(int sockfd) {
+@@ -509,7 +602,7 @@ int uv__accept(int sockfd) {
return peerfd;
}
@@ -1205,7 +1300,7 @@ index 5b0b64dd4..2438614f0 100644
/* 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) {
+@@ -531,6 +624,8 @@ int uv__close_nocancel(int fd) {
return close$NOCANCEL$UNIX2003(fd);
#endif
#pragma GCC diagnostic pop
@@ -1214,7 +1309,7 @@ index 5b0b64dd4..2438614f0 100644
#elif defined(__linux__)
return syscall(SYS_close, fd);
#else
-@@ -559,11 +645,18 @@ int uv__close_nocheckstdio(int fd) {
+@@ -559,11 +654,18 @@ int uv__close_nocheckstdio(int fd) {
int uv__close(int fd) {
@@ -1233,7 +1328,7 @@ index 5b0b64dd4..2438614f0 100644
}
-@@ -581,7 +674,8 @@ int uv__nonblock_ioctl(int fd, int set) {
+@@ -581,7 +683,8 @@ int uv__nonblock_ioctl(int fd, int set) {
}
@@ -1243,7 +1338,7 @@ index 5b0b64dd4..2438614f0 100644
int uv__cloexec_ioctl(int fd, int set) {
int r;
-@@ -658,7 +752,7 @@ int uv__cloexec_fcntl(int fd, int set) {
+@@ -658,7 +761,7 @@ int uv__cloexec_fcntl(int fd, int set) {
return 0;
}
@@ -1252,7 +1347,7 @@ index 5b0b64dd4..2438614f0 100644
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) {
+@@ -695,7 +798,7 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
uv__cloexec(*pfd, 1);
return rc;
}
@@ -1261,7 +1356,7 @@ index 5b0b64dd4..2438614f0 100644
int uv_cwd(char* buffer, size_t* size) {
char scratch[1 + UV__PATH_MAX];
-@@ -743,7 +837,7 @@ int uv_chdir(const char* dir) {
+@@ -743,7 +846,7 @@ int uv_chdir(const char* dir) {
return 0;
}
@@ -1270,7 +1365,7 @@ index 5b0b64dd4..2438614f0 100644
void uv_disable_stdio_inheritance(void) {
int fd;
-@@ -754,7 +848,7 @@ void uv_disable_stdio_inheritance(void) {
+@@ -754,21 +857,31 @@ void uv_disable_stdio_inheritance(void) {
if (uv__cloexec(fd, 1) && fd > 15)
break;
}
@@ -1279,16 +1374,53 @@ index 5b0b64dd4..2438614f0 100644
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) {
+
+ switch (handle->type) {
++#ifdef CONFIG_LIBUV_TCP
+ case UV_TCP:
++#endif
++#ifdef CONFIG_LIBUV_PIPE
+ case UV_NAMED_PIPE:
++#endif
++#if 0
+ case UV_TTY:
++#endif
++#if defined(CONFIG_LIBUV_PIPE) || defined(CONFIG_LIBUV_TCP)
+ fd_out = uv__stream_fd((uv_stream_t*) handle);
+ break;
++#endif
+
++#ifdef CONFIG_LIBUV_UDP
+ case UV_UDP:
+ fd_out = ((uv_udp_t *) handle)->io_watcher.fd;
+ break;
++#endif
+
+ case UV_POLL:
+ fd_out = ((uv_poll_t *) handle)->io_watcher.fd;
+@@ -785,11 +898,11 @@ int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) {
return 0;
}
-
-+#if 0
++#ifdef CONFIG_LIBUV_STREAM
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) {
+- uv__io_t* w;
++ uv_stream_t* handle;
+
+ if (QUEUE_EMPTY(&loop->pending_queue))
+ return 0;
+@@ -800,14 +913,15 @@ static int uv__run_pending(uv_loop_t* loop) {
+ q = QUEUE_HEAD(&pq);
+ QUEUE_REMOVE(q);
+ QUEUE_INIT(q);
+- w = QUEUE_DATA(q, uv__io_t, pending_queue);
+- w->cb(loop, w, POLLOUT);
++ handle = QUEUE_DATA(q, uv_stream_t, pending_queue);
++ handle->io_watcher.cb(loop, &handle->io_watcher, POLLOUT);
+ }
return 1;
}
@@ -1299,7 +1431,7 @@ index 5b0b64dd4..2438614f0 100644
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) {
+@@ -852,12 +966,14 @@ static void maybe_resize(uv_loop_t* loop, unsigned int len) {
loop->watchers = watchers;
loop->nwatchers = nwatchers;
}
@@ -1315,7 +1447,7 @@ index 5b0b64dd4..2438614f0 100644
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) {
+@@ -878,7 +994,9 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
assert(w->fd < INT_MAX);
w->pevents |= events;
@@ -1325,7 +1457,7 @@ index 5b0b64dd4..2438614f0 100644
#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) {
+@@ -892,10 +1010,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);
@@ -1338,7 +1470,7 @@ index 5b0b64dd4..2438614f0 100644
}
-@@ -909,8 +1010,10 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
+@@ -909,8 +1029,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. */
@@ -1349,7 +1481,7 @@ index 5b0b64dd4..2438614f0 100644
w->pevents &= ~events;
-@@ -918,6 +1021,7 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
+@@ -918,6 +1040,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);
@@ -1357,7 +1489,7 @@ index 5b0b64dd4..2438614f0 100644
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) {
+@@ -925,6 +1048,9 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
loop->nfds--;
w->events = 0;
}
@@ -1367,29 +1499,34 @@ index 5b0b64dd4..2438614f0 100644
}
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) {
+@@ -933,19 +1059,21 @@ 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);
++#if 0
+ QUEUE_REMOVE(&w->pending_queue);
++#endif
/* 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) {
+ uv__platform_invalidate_fd(loop, w->fd);
}
-
-+#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);
+-
+-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);
++#ifdef CONFIG_LIBUV_STREAM
++void uv__stream_feed(uv_loop_t* loop, uv_stream_t* s) {
++ if (QUEUE_EMPTY(&s->pending_queue))
++ QUEUE_INSERT_TAIL(&loop->pending_queue, &s->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) {
+ assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI)));
+@@ -955,10 +1083,22 @@ int uv__io_active(const uv__io_t* w, unsigned int events) {
int uv__fd_exists(uv_loop_t* loop, int fd) {
@@ -1413,7 +1550,7 @@ index 5b0b64dd4..2438614f0 100644
int uv_getrusage(uv_rusage_t* rusage) {
struct rusage usage;
-@@ -990,7 +1111,7 @@ int uv_getrusage(uv_rusage_t* rusage) {
+@@ -990,7 +1130,7 @@ int uv_getrusage(uv_rusage_t* rusage) {
return 0;
}
@@ -1422,7 +1559,7 @@ index 5b0b64dd4..2438614f0 100644
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) {
+@@ -1019,7 +1159,7 @@ int uv__open_cloexec(const char* path, int flags) {
#endif /* O_CLOEXEC */
}
@@ -1431,7 +1568,7 @@ index 5b0b64dd4..2438614f0 100644
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) {
+@@ -1046,7 +1186,7 @@ int uv__dup2_cloexec(int oldfd, int newfd) {
return r;
#endif
}
@@ -1440,7 +1577,7 @@ index 5b0b64dd4..2438614f0 100644
int uv_os_homedir(char* buffer, size_t* size) {
uv_passwd_t pwd;
-@@ -1390,12 +1511,13 @@ uv_pid_t uv_os_getpid(void) {
+@@ -1390,12 +1530,13 @@ uv_pid_t uv_os_getpid(void) {
return getpid();
}
@@ -1456,7 +1593,7 @@ index 5b0b64dd4..2438614f0 100644
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) {
+@@ -1422,7 +1563,7 @@ int uv_os_setpriority(uv_pid_t pid, int priority) {
return 0;
}
@@ -1466,7 +1603,7 @@ index 5b0b64dd4..2438614f0 100644
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
+index dd08ea541..302d4f0c6 100644
--- a/src/unix/fs.c
+++ b/src/unix/fs.c
@@ -56,6 +56,12 @@
@@ -1591,35 +1728,21 @@ index dd08ea541..4e32d0783 100644
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) {
+@@ -968,7 +980,7 @@ static ssize_t uv__fs_sendfile(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) {
+ static ssize_t uv__fs_utime(uv_fs_t* req) {
+ #if defined(__linux__) \
+ || defined(_AIX71) \
+@@ -1035,10 +1047,10 @@ static ssize_t uv__fs_lutime(uv_fs_t* req) {
return -1;
#endif
}
-
-+#endif
++#endif /* !__NUTTX__ */
static ssize_t uv__fs_write(uv_fs_t* req) {
-#if defined(__linux__)
@@ -1627,7 +1750,7 @@ index dd08ea541..4e32d0783 100644
static int no_pwritev;
#endif
ssize_t r;
-@@ -1067,13 +1084,13 @@ static ssize_t uv__fs_write(uv_fs_t* req) {
+@@ -1067,13 +1079,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
@@ -1643,7 +1766,7 @@ index dd08ea541..4e32d0783 100644
else {
r = uv__pwritev(req->file,
(struct iovec*) req->bufs,
-@@ -1102,7 +1119,9 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
+@@ -1102,7 +1114,9 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
uv_file srcfd;
uv_file dstfd;
struct stat src_statsbuf;
@@ -1653,7 +1776,7 @@ index dd08ea541..4e32d0783 100644
int dst_flags;
int result;
int err;
-@@ -1146,6 +1165,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
+@@ -1146,6 +1160,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
goto out;
}
@@ -1661,7 +1784,7 @@ index dd08ea541..4e32d0783 100644
/* 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) {
+@@ -1157,9 +1172,12 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
src_statsbuf.st_ino == dst_statsbuf.st_ino) {
goto out;
}
@@ -1674,7 +1797,7 @@ index dd08ea541..4e32d0783 100644
#ifdef __linux__
if (err != UV_EPERM)
goto out;
-@@ -1183,6 +1206,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
+@@ -1183,6 +1201,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
goto out;
#endif /* !__linux__ */
}
@@ -1682,7 +1805,7 @@ index dd08ea541..4e32d0783 100644
#ifdef FICLONE
if (req->flags & UV_FS_COPYFILE_FICLONE ||
-@@ -1343,7 +1367,7 @@ static int uv__fs_statx(int fd,
+@@ -1343,7 +1362,7 @@ static int uv__fs_statx(int fd,
int is_lstat,
uv_stat_t* buf) {
STATIC_ASSERT(UV_ENOSYS != -1);
@@ -1691,17 +1814,18 @@ index dd08ea541..4e32d0783 100644
static int no_statx;
struct uv__statx statxbuf;
int dirfd;
-@@ -1543,30 +1567,40 @@ static void uv__fs_work(struct uv__work* w) {
+@@ -1542,40 +1561,56 @@ 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(CHMOD, chmod(req->path, req->mode));
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(FCHMOD, fchmod(req->file, req->mode));
X(FCHOWN, fchown(req->file, req->uid, req->gid));
X(LCHOWN, lchown(req->path, req->uid, req->gid));
+#endif
@@ -1714,7 +1838,9 @@ index dd08ea541..4e32d0783 100644
X(LUTIME, uv__fs_lutime(req));
+#endif
X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));
++#ifdef CONFIG_PSEUDOFS_SOFTLINKS
X(LINK, link(req->path, req->new_path));
++#endif
X(MKDIR, mkdir(req->path, req->mode));
+#ifndef __NUTTX__
X(MKDTEMP, uv__fs_mkdtemp(req));
@@ -1732,8 +1858,93 @@ index dd08ea541..4e32d0783 100644
X(REALPATH, uv__fs_realpath(req));
X(RENAME, rename(req->path, req->new_path));
X(RMDIR, rmdir(req->path));
+ X(SENDFILE, uv__fs_sendfile(req));
+ X(STAT, uv__fs_stat(req->path, &req->statbuf));
+ X(STATFS, uv__fs_statfs(req));
++#ifdef CONFIG_PSEUDOFS_SOFTLINKS
+ X(SYMLINK, symlink(req->path, req->new_path));
++#endif
+ X(UNLINK, unlink(req->path));
++#ifndef __NUTTX__
+ X(UTIME, uv__fs_utime(req));
++#endif
+ X(WRITE, uv__fs_write_all(req));
+ default: abort();
+ }
+@@ -1621,7 +1656,7 @@ int uv_fs_access(uv_loop_t* loop,
+ POST;
+ }
+
+-
++#ifndef __NUTTX__
+ int uv_fs_chmod(uv_loop_t* loop,
+ uv_fs_t* req,
+ const char* path,
+@@ -1646,7 +1681,7 @@ int uv_fs_chown(uv_loop_t* loop,
+ req->gid = gid;
+ POST;
+ }
+-
++#endif
+
+ int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
+ INIT(CLOSE);
+@@ -1654,7 +1689,7 @@ int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
+ POST;
+ }
+
+-
++#ifndef __NUTTX__
+ int uv_fs_fchmod(uv_loop_t* loop,
+ uv_fs_t* req,
+ uv_file file,
+@@ -1693,7 +1728,7 @@ int uv_fs_lchown(uv_loop_t* loop,
+ req->gid = gid;
+ POST;
+ }
+-
++#endif
+
+ int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
+ INIT(FDATASYNC);
+@@ -1957,7 +1992,7 @@ int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
+ POST;
+ }
+
+-
++#ifdef CONFIG_PSEUDOFS_SOFTLINKS
+ int uv_fs_symlink(uv_loop_t* loop,
+ uv_fs_t* req,
+ const char* path,
+@@ -1969,7 +2004,7 @@ int uv_fs_symlink(uv_loop_t* loop,
+ req->flags = flags;
+ POST;
+ }
+-
++#endif
+
+ int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
+ INIT(UNLINK);
+@@ -1977,7 +2012,7 @@ int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
+ POST;
+ }
+
+-
++#ifndef __NUTTX__
+ int uv_fs_utime(uv_loop_t* loop,
+ uv_fs_t* req,
+ const char* path,
+@@ -1990,7 +2025,7 @@ int uv_fs_utime(uv_loop_t* loop,
+ req->mtime = mtime;
+ POST;
+ }
+-
++#endif
+
+ int uv_fs_write(uv_loop_t* loop,
+ uv_fs_t* req,
diff --git a/src/unix/internal.h b/src/unix/internal.h
-index 402ee877d..9f828a223 100644
+index 402ee877d..107565e4c 100644
--- a/src/unix/internal.h
+++ b/src/unix/internal.h
@@ -1,3 +1,23 @@
@@ -1778,6 +1989,15 @@ index 402ee877d..9f828a223 100644
#define uv__cloexec uv__cloexec_ioctl
#define uv__nonblock uv__nonblock_ioctl
#else
+@@ -201,7 +222,7 @@ void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd);
+ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events);
+ 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);
+-void uv__io_feed(uv_loop_t* loop, uv__io_t* w);
++void uv__stream_feed(uv_loop_t* loop, uv_stream_t *s);
+ int uv__io_active(const uv__io_t* w, unsigned int events);
+ int uv__io_check_fd(uv_loop_t* loop, int fd);
+ void uv__io_poll(uv_loop_t* loop, int timeout); /* in milliseconds or -1 */
@@ -247,6 +268,7 @@ int uv__signal_loop_fork(uv_loop_t* loop);
/* platform specific */
@@ -1799,7 +2019,7 @@ index 402ee877d..9f828a223 100644
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
+index e5b288956..bb100390a 100644
--- a/src/unix/loop.c
+++ b/src/unix/loop.c
@@ -1,3 +1,23 @@
@@ -1875,7 +2095,7 @@ index e5b288956..de5d5aa80 100644
loop->watchers = NULL;
loop->nwatchers = 0;
+#endif
-+#if 0
++#ifdef CONFIG_LIBUV_STREAM
QUEUE_INIT(&loop->pending_queue);
+#endif
QUEUE_INIT(&loop->watcher_queue);
@@ -2334,10 +2554,10 @@ index 000000000..4549e48eb
+}
diff --git a/src/unix/nuttx_stream.c b/src/unix/nuttx_stream.c
new file mode 100644
-index 000000000..891a872dd
+index 000000000..0642d057c
--- /dev/null
+++ b/src/unix/nuttx_stream.c
-@@ -0,0 +1,1077 @@
+@@ -0,0 +1,1016 @@
+/****************************************************************************
+ * libuv/src/unix/nuttx_stream.c
+ *
@@ -2395,7 +2615,10 @@ index 000000000..891a872dd
+#include <unistd.h>
+#include <limits.h> /* IOV_MAX */
+
++#ifdef CONFIG_LIBUV_NET
+static void uv__stream_connect(uv_stream_t*);
++#endif
++
+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);
@@ -2412,11 +2635,13 @@ index 000000000..891a872dd
+ stream->close_cb = NULL;
+ stream->connection_cb = NULL;
+ stream->connect_req = NULL;
++ /* shutdown() not supported by NuttX */
+ stream->shutdown_req = NULL;
+ stream->accepted_fd = -1;
-+ stream->queued_fds = NULL;
+ QUEUE_INIT(&stream->write_queue);
+ QUEUE_INIT(&stream->write_completed_queue);
++ /* FIXME move back to uv__io_t if needed */
++ QUEUE_INIT(&stream->pending_queue);
+ stream->write_queue_size = 0;
+
+ uv__io_init(&stream->io_watcher, uv__stream_io, -1);
@@ -2490,49 +2715,13 @@ index 000000000..891a872dd
+ 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) */
+
-+
++#ifdef CONFIG_LIBUV_NET
+void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
+ uv_stream_t* stream;
+ int err;
@@ -2542,8 +2731,6 @@ index 000000000..891a872dd
+ 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.
+ */
@@ -2555,17 +2742,9 @@ index 000000000..891a872dd
+ if (err == UV_EAGAIN || err == UV__ERR(EWOULDBLOCK))
+ return; /* Not an error. */
+
-+ if (err == UV_ECONNABORTED)
++ if (err == UV__ERR(ENOTCONN))
+ 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;
+ }
@@ -2590,7 +2769,7 @@ index 000000000..891a872dd
+#endif
+ }
+}
-+
++#endif
+
+#undef UV_DEC_BACKLOG
+
@@ -2604,11 +2783,13 @@ index 000000000..891a872dd
+ return UV_EAGAIN;
+
+ switch (client->type) {
-+#if 0
++#ifdef CONFIG_LIBUV_PIPE
+ case UV_NAMED_PIPE:
+#endif
+#ifdef CONFIG_LIBUV_TCP
+ case UV_TCP:
++#endif
++#if defined(CONFIG_LIBUV_PIPE) || defined(CONFIG_LIBUV_TCP)
+ err = uv__stream_open(client,
+ server->accepted_fd,
+ UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
@@ -2636,36 +2817,14 @@ index 000000000..891a872dd
+ 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;
++ server->accepted_fd = -1;
++ uv__io_start(server->loop, &server->io_watcher, POLLIN);
+
-+ if (err == 0)
-+ uv__io_start(server->loop, &server->io_watcher, POLLIN);
-+ }
+ return err;
+}
+
-+
++#ifdef CONFIG_LIBUV_NET
+int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {
+ int err;
+
@@ -2675,11 +2834,14 @@ index 000000000..891a872dd
+ err = uv_tcp_listen((uv_tcp_t*)stream, backlog, cb);
+ break;
+#endif
-+#if 0
++#ifndef __NUTTX__
++ /* TODO Revist uv_pipe_listen() port */
++#ifdef CONFIG_LIBUV_PIPE
+ case UV_NAMED_PIPE:
+ err = uv_pipe_listen((uv_pipe_t*)stream, backlog, cb);
+ break;
+#endif
++#endif /* !__NUTTX__ */
+
+ default:
+ err = UV_EINVAL;
@@ -2690,7 +2852,7 @@ index 000000000..891a872dd
+
+ return err;
+}
-+
++#endif
+
+static void uv__drain(uv_stream_t* stream) {
+ uv_shutdown_t* req;
@@ -2711,8 +2873,13 @@ index 000000000..891a872dd
+ uv__req_unregister(stream->loop, req);
+
+ err = 0;
++
++#ifndef __NUTTX__
++ /* shutdown not implemented in NuttX */
++
+ if (shutdown(uv__stream_fd(stream), SHUT_WR))
+ err = UV__ERR(errno);
++#endif
+
+ if (err == 0)
+ stream->flags |= UV_HANDLE_SHUT;
@@ -2792,16 +2959,11 @@ index 000000000..891a872dd
+ 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
++ uv__stream_feed(stream->loop, stream);
+}
+
+#if 0
@@ -2829,59 +2991,61 @@ index 000000000..891a872dd
+ ssize_t n;
+ int err;
+
-+start:
-+
+ assert(uv__stream_fd(stream) >= 0);
+
-+ if (QUEUE_EMPTY(&stream->write_queue))
-+ return;
++ while (!QUEUE_EMPTY(&stream->write_queue)) {
+
-+ q = QUEUE_HEAD(&stream->write_queue);
-+ req = QUEUE_DATA(q, uv_write_t, queue);
-+ assert(req->handle == stream);
++ 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;
++ /*
++ * 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();
++ iovmax = uv__getiovmax();
+
-+ /* Limit iov count to avoid EINVALs from writev() */
-+ if (iovcnt > iovmax)
-+ iovcnt = iovmax;
++ /* 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.
-+ */
++ /*
++ * 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;
-+ }
++ do {
++ n = uv__writev(uv__stream_fd(stream), iov, iovcnt);
++ } while (n == -1 && errno == EINTR);
+
-+ 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 (n == -1 &&
++ errno != EAGAIN &&
++ errno != EWOULDBLOCK &&
++ errno != ENOBUFS) {
++ err = UV__ERR(errno);
++ goto error;
++ }
+
-+ /* If this is a blocking stream, try again. */
-+ if (stream->flags & UV_HANDLE_BLOCKING_WRITES)
-+ goto start;
++ if (n >= 0 && uv__write_req_update(stream, req, n)) {
++ uv__write_req_finish(req);
++ continue; /* TODO(bnoordhuis) Start trying to write the next request. */
++ }
+
-+ /* We're not done. */
-+ uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
++ /* If this is a blocking stream, try again. */
++ if (stream->flags & UV_HANDLE_BLOCKING_WRITES)
++ continue;
++
++ /* Wait for next POLLOUT to continue writing.
++ * FIXME: what if user called uv_read_stop() before ?
++ * stream handle may be in invalid state.
++ */
++ uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
++ return;
++ }
+
+ return;
+
@@ -2924,7 +3088,7 @@ index 000000000..891a872dd
+ }
+}
+
-+
++#ifdef CONFIG_LIBUV_NET
+uv_handle_type uv__handle_type(int fd) {
+ struct sockaddr_storage ss;
+ socklen_t sslen;
@@ -2966,7 +3130,7 @@ index 000000000..891a872dd
+
+ return UV_UNKNOWN_HANDLE;
+}
-+
++#endif
+
+static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) {
+ stream->flags |= UV_HANDLE_READ_EOF;
@@ -3084,24 +3248,30 @@ index 000000000..891a872dd
+
+ stream = container_of(w, uv_stream_t, io_watcher);
+
-+ assert(stream->type == UV_TCP ||
-+ stream->type == UV_NAMED_PIPE ||
-+ stream->type == UV_TTY);
++ assert(
++#ifdef CONFIG_LIBUV_NET
++ stream->type == UV_TCP ||
++#endif
++ stream->type == UV_NAMED_PIPE
++ // || stream->type == UV_TTY
++ );
+ assert(!(stream->flags & UV_HANDLE_CLOSING));
+
++#ifdef CONFIG_LIBUV_NET
+ if (stream->connect_req) {
+ uv__stream_connect(stream);
+ return;
+ }
++#endif
+
+ 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))
++ if (events & (POLLIN | POLLERR | POLLHUP)) {
+ uv__read(stream);
-+
-+ if (uv__stream_fd(stream) == -1)
-+ return; /* read_cb closed stream. */
++ if (uv__stream_fd(stream) == -1)
++ return; /* read_cb closed stream. */
++ }
+
+ /* Short-circuit iff POLLHUP is set, the user is still interested in read
+ * events and uv__read() reported a partial read but not EOF. If the EOF
@@ -3115,12 +3285,12 @@ index 000000000..891a872dd
+ !(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 (uv__stream_fd(stream) == -1)
-+ return; /* read_cb closed stream. */
-+
+ if (events & (POLLOUT | POLLERR | POLLHUP)) {
++ /* Called by either real poll event or stream_feed */
+ uv__write(stream);
+ uv__write_callbacks(stream);
+
@@ -3130,7 +3300,7 @@ index 000000000..891a872dd
+ }
+}
+
-+
++#ifdef CONFIG_LIBUV_NET
+/**
+ * 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
@@ -3174,7 +3344,7 @@ index 000000000..891a872dd
+ uv__write_callbacks(stream);
+ }
+}
-+
++#endif
+
+int uv_write2(uv_write_t* req,
+ uv_stream_t* stream,
@@ -3244,7 +3414,6 @@ index 000000000..891a872dd
+ * sufficiently flushed in uv__write.
+ */
+ assert(!(stream->flags & UV_HANDLE_BLOCKING_WRITES));
-+ uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
+ }
+
+ return 0;
@@ -3376,8 +3545,7 @@ index 000000000..891a872dd
+
+
+void uv__stream_close(uv_stream_t* handle) {
-+ unsigned int i;
-+ uv__stream_queued_fds_t* queued_fds;
++ QUEUE_REMOVE(&handle->pending_queue);
+
+ uv__io_close(handle->loop, &handle->io_watcher);
+ uv_read_stop(handle);
@@ -3396,15 +3564,6 @@ index 000000000..891a872dd
+ 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));
+}
+
@@ -4304,6 +4463,90 @@ index 000000000..d56fdc287
+void uv__timer_close(uv_timer_t* handle) {
+ uv_timer_stop(handle);
+}
+diff --git a/src/unix/pipe.c b/src/unix/pipe.c
+index 040d57817..7d6105083 100644
+--- a/src/unix/pipe.c
++++ b/src/unix/pipe.c
+@@ -39,7 +39,8 @@ int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
+ return 0;
+ }
+
+-
++// #ifdef CONFIG_LIBUV_NET
++#if 0
+ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
+ struct sockaddr_un saddr;
+ const char* pipe_fname;
+@@ -115,7 +116,7 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
+ uv__io_start(handle->loop, &handle->io_watcher, POLLIN);
+ return 0;
+ }
+-
++#endif
+
+ void uv__pipe_close(uv_pipe_t* handle) {
+ if (handle->pipe_fname) {
+@@ -169,7 +170,8 @@ int uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
+ return uv__stream_open((uv_stream_t*)handle, fd, flags);
+ }
+
+-
++// #ifdef CONFIG_LIBUV_NET
++#if 0
+ void uv_pipe_connect(uv_connect_t* req,
+ uv_pipe_t* handle,
+ const char* name,
+@@ -198,6 +200,10 @@ void uv_pipe_connect(uv_connect_t* req,
+ }
+ while (r == -1 && errno == EINTR);
+
++ /* FIXME NuttX does not support NONBLOCKING connect,
++ * no need to check for EINPROGRESS.
++ */
++
+ if (r == -1 && errno != EINPROGRESS) {
+ err = UV__ERR(errno);
+ #if defined(__CYGWIN__) || defined(__MSYS__)
+@@ -230,10 +236,13 @@ out:
+ req->cb = cb;
+ QUEUE_INIT(&req->queue);
+
++#ifdef __NUTTX__
++ return 0;
++#else
+ /* Force callback to run on next tick in case of error. */
+ if (err)
+- uv__io_feed(handle->loop, &handle->io_watcher);
+-
++ uv__stream_feed(handle->loop, (uv_stream_t*)handle);
++#endif
+ }
+
+
+@@ -280,7 +289,6 @@ static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
+ return 0;
+ }
+
+-
+ int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) {
+ return uv__pipe_getsockpeername(handle, getsockname, buffer, size);
+ }
+@@ -289,8 +297,9 @@ int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) {
+ int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) {
+ return uv__pipe_getsockpeername(handle, getpeername, buffer, size);
+ }
++#endif
+
+-
++#if 0
+ void uv_pipe_pending_instances(uv_pipe_t* handle, int count) {
+ }
+
+@@ -379,3 +388,4 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
+
+ return r != -1 ? 0 : UV__ERR(errno);
+ }
++#endif
diff --git a/src/unix/poll.c b/src/unix/poll.c
index 3d5022b22..d2f442132 100644
--- a/src/unix/poll.c
@@ -5403,7 +5646,7 @@ index 6801564f9..15619088d 100644
/* 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
+index e95e3bde5..3b4556d86 100644
--- a/test/task.h
+++ b/test/task.h
@@ -1,3 +1,23 @@
@@ -5466,7 +5709,7 @@ index e95e3bde5..29a20afbc 100644
do { \
- close_loop(uv_default_loop()); \
- ASSERT(0 == uv_loop_close(uv_default_loop())); \
-+ if (loop != NULL) { \
++ if ((uv_loop_t*)(loop) != NULL) { \
+ uv_context_t *tmp_ctx = \
+ ((uv_loop_t*)(loop))->context; \
+ close_loop(loop); \
@@ -5625,10 +5868,20 @@ index 6f5351bf1..fb29059e2 100644
return 0;
}
diff --git a/test/test-fs-copyfile.c b/test/test-fs-copyfile.c
-index 3335c8810..a70e6304c 100644
+index 3335c8810..51d0b26b8 100644
--- a/test/test-fs-copyfile.c
+++ b/test/test-fs-copyfile.c
-@@ -33,8 +33,8 @@
+@@ -22,7 +22,8 @@
+ #include "uv.h"
+ #include "task.h"
+
+-#if defined(__unix__) || defined(__POSIX__) || \
++#if defined(__NUTTX__) || \
++ defined(__unix__) || defined(__POSIX__) || \
+ defined(__APPLE__) || defined(__sun) || \
+ defined(_AIX) || defined(__MVS__) || \
+ defined(__HAIKU__)
+@@ -33,8 +34,8 @@
# define unlink _unlink
#endif
@@ -5639,7 +5892,7 @@ index 3335c8810..a70e6304c 100644
static int result_check_count;
-@@ -96,12 +96,19 @@ static void touch_file(const char* name, unsigned int size) {
+@@ -96,12 +97,19 @@ static void touch_file(const char* name, unsigned int size) {
TEST_IMPL(fs_copyfile) {
@@ -5661,7 +5914,7 @@ index 3335c8810..a70e6304c 100644
/* 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) {
+@@ -121,10 +129,14 @@ TEST_IMPL(fs_copyfile) {
uv_fs_req_cleanup(&req);
/* Succeeds if src and dst files are identical. */
@@ -5676,7 +5929,7 @@ index 3335c8810..a70e6304c 100644
unlink(src);
/* Copies file synchronously. Creates new file. */
-@@ -193,10 +204,9 @@ TEST_IMPL(fs_copyfile) {
+@@ -193,10 +205,9 @@ TEST_IMPL(fs_copyfile) {
if (r == 0)
handle_result(&req);
@@ -5688,7 +5941,7 @@ index 3335c8810..a70e6304c 100644
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) {
+@@ -207,6 +218,9 @@ TEST_IMPL(fs_copyfile) {
uv_fs_req_cleanup(&req);
#endif
@@ -6043,7 +6296,7 @@ index dfefb0f91..1cd9cd33f 100644
return 0;
}
diff --git a/test/test-list.h b/test/test-list.h
-index 58e174d1d..ec5ac09c9 100644
+index 58e174d1d..edf5077cd 100644
--- a/test/test-list.h
+++ b/test/test-list.h
@@ -21,17 +21,20 @@
@@ -6067,7 +6320,17 @@ index 58e174d1d..ec5ac09c9 100644
TEST_DECLARE (loop_configure)
TEST_DECLARE (default_loop_close)
TEST_DECLARE (barrier_1)
-@@ -102,9 +105,11 @@ TEST_DECLARE (pipe_ping_pong)
+@@ -94,17 +97,21 @@ TEST_DECLARE (ipc_send_zero)
+ TEST_DECLARE (ipc_closed_handle)
+ #endif
+ TEST_DECLARE (tcp_alloc_cb_fail)
++#endif
+ TEST_DECLARE (tcp_ping_pong)
+ TEST_DECLARE (tcp_ping_pong_vec)
++#if 0
+ TEST_DECLARE (tcp6_ping_pong)
+ TEST_DECLARE (tcp6_ping_pong_vec)
+ TEST_DECLARE (pipe_ping_pong)
TEST_DECLARE (pipe_ping_pong_vec)
TEST_DECLARE (delayed_accept)
TEST_DECLARE (multiple_listen)
@@ -6079,7 +6342,7 @@ index 58e174d1d..ec5ac09c9 100644
TEST_DECLARE (tcp_writealot)
TEST_DECLARE (tcp_write_fail)
TEST_DECLARE (tcp_try_write)
-@@ -144,7 +149,9 @@ TEST_DECLARE (tcp_oob)
+@@ -144,7 +151,9 @@ TEST_DECLARE (tcp_oob)
TEST_DECLARE (tcp_flags)
TEST_DECLARE (tcp_write_to_half_open_connection)
TEST_DECLARE (tcp_unexpected_read)
@@ -6089,7 +6352,7 @@ index 58e174d1d..ec5ac09c9 100644
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)
+@@ -206,6 +215,7 @@ TEST_DECLARE (callback_stack)
TEST_DECLARE (env_vars)
TEST_DECLARE (error_message)
TEST_DECLARE (sys_error)
@@ -6097,7 +6360,7 @@ index 58e174d1d..ec5ac09c9 100644
TEST_DECLARE (timer)
TEST_DECLARE (timer_init)
TEST_DECLARE (timer_again)
-@@ -218,10 +226,14 @@ TEST_DECLARE (timer_from_check)
+@@ -218,10 +228,14 @@ TEST_DECLARE (timer_from_check)
TEST_DECLARE (timer_is_closing)
TEST_DECLARE (timer_null_callback)
TEST_DECLARE (timer_early_check)
@@ -6112,7 +6375,7 @@ index 58e174d1d..ec5ac09c9 100644
TEST_DECLARE (watcher_cross_stop)
TEST_DECLARE (ref)
TEST_DECLARE (idle_ref)
-@@ -253,9 +265,13 @@ TEST_DECLARE (pipe_set_chmod)
+@@ -253,9 +267,13 @@ TEST_DECLARE (pipe_set_chmod)
TEST_DECLARE (process_ref)
TEST_DECLARE (process_priority)
TEST_DECLARE (has_ref)
@@ -6126,7 +6389,7 @@ index 58e174d1d..ec5ac09c9 100644
TEST_DECLARE (async_null_cb)
TEST_DECLARE (eintr_handling)
TEST_DECLARE (get_currentexe)
-@@ -311,12 +327,14 @@ TEST_DECLARE (spawn_reads_child_path)
+@@ -311,12 +329,14 @@ TEST_DECLARE (spawn_reads_child_path)
TEST_DECLARE (spawn_inherit_streams)
TEST_DECLARE (spawn_quoted_path)
TEST_DECLARE (spawn_tcp_server)
@@ -6141,7 +6404,7 @@ index 58e174d1d..ec5ac09c9 100644
TEST_DECLARE (kill)
TEST_DECLARE (kill_invalid_signum)
TEST_DECLARE (fs_file_noent)
-@@ -333,7 +351,9 @@ TEST_DECLARE (fs_mkstemp)
+@@ -333,7 +353,9 @@ TEST_DECLARE (fs_mkstemp)
TEST_DECLARE (fs_fstat)
TEST_DECLARE (fs_access)
TEST_DECLARE (fs_chmod)
@@ -6151,7 +6414,7 @@ index 58e174d1d..ec5ac09c9 100644
TEST_DECLARE (fs_unlink_readonly)
#ifdef _WIN32
TEST_DECLARE (fs_unlink_archive_readonly)
-@@ -413,8 +433,10 @@ TEST_DECLARE (fs_invalid_mkdir_name)
+@@ -413,8 +435,10 @@ TEST_DECLARE (fs_invalid_mkdir_name)
#endif
TEST_DECLARE (fs_get_system_error)
TEST_DECLARE (strscpy)
@@ -6162,7 +6425,7 @@ index 58e174d1d..ec5ac09c9 100644
TEST_DECLARE (threadpool_multiple_event_loops)
TEST_DECLARE (threadpool_cancel_getaddrinfo)
TEST_DECLARE (threadpool_cancel_getnameinfo)
-@@ -438,7 +460,9 @@ TEST_DECLARE (poll_oob)
+@@ -438,7 +462,9 @@ TEST_DECLARE (poll_oob)
#endif
TEST_DECLARE (poll_duplex)
TEST_DECLARE (poll_unidirectional)
@@ -6172,7 +6435,7 @@ index 58e174d1d..ec5ac09c9 100644
TEST_DECLARE (poll_bad_fdtype)
#ifdef __linux__
TEST_DECLARE (poll_nested_epoll)
-@@ -447,7 +471,9 @@ TEST_DECLARE (poll_nested_epoll)
+@@ -447,7 +473,9 @@ TEST_DECLARE (poll_nested_epoll)
TEST_DECLARE (poll_nested_kqueue)
#endif
@@ -6182,7 +6445,7 @@ index 58e174d1d..ec5ac09c9 100644
TEST_DECLARE (ip6_addr_link_local)
TEST_DECLARE (poll_close_doesnt_corrupt_stack)
-@@ -482,16 +508,18 @@ TEST_DECLARE (closed_fd_events)
+@@ -482,16 +510,20 @@ TEST_DECLARE (closed_fd_events)
TEST_DECLARE (osx_select)
TEST_DECLARE (osx_select_many_fds)
#endif
@@ -6196,14 +6459,16 @@ index 58e174d1d..ec5ac09c9 100644
TEST_DECLARE (queue_foreach_delete)
-
+#endif
++#ifdef CONFIG_DEV_URANDOM
TEST_DECLARE (random_async)
TEST_DECLARE (random_sync)
-
++#endif
+#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)
+@@ -517,22 +549,27 @@ TEST_DECLARE (fork_threadpool_queue_work_simple)
TEST_DECLARE (idna_toascii)
TEST_DECLARE (utf8_decode1)
TEST_DECLARE (uname)
@@ -6232,7 +6497,23 @@ index 58e174d1d..ec5ac09c9 100644
TEST_ENTRY (loop_configure)
TEST_ENTRY (default_loop_close)
TEST_ENTRY (barrier_1)
-@@ -628,11 +661,11 @@ TASK_LIST_START
+@@ -607,13 +644,13 @@ TASK_LIST_START
+ #endif
+
+ TEST_ENTRY (tcp_alloc_cb_fail)
+-
++#endif
+ TEST_ENTRY (tcp_ping_pong)
+ TEST_HELPER (tcp_ping_pong, tcp4_echo_server)
+
+ TEST_ENTRY (tcp_ping_pong_vec)
+ TEST_HELPER (tcp_ping_pong_vec, tcp4_echo_server)
+-
++#if 0
+ TEST_ENTRY (tcp6_ping_pong)
+ TEST_HELPER (tcp6_ping_pong, tcp6_echo_server)
+
+@@ -628,11 +665,11 @@ TASK_LIST_START
TEST_ENTRY (delayed_accept)
TEST_ENTRY (multiple_listen)
@@ -6246,7 +6527,7 @@ index 58e174d1d..ec5ac09c9 100644
#ifdef __MVS__
TEST_ENTRY_CUSTOM (tcp_writealot, 0, 0, 20000)
#else
-@@ -689,10 +722,10 @@ TASK_LIST_START
+@@ -689,10 +726,10 @@ TASK_LIST_START
TEST_ENTRY (tcp_flags)
TEST_ENTRY (tcp_write_to_half_open_connection)
TEST_ENTRY (tcp_unexpected_read)
@@ -6259,7 +6540,7 @@ index 58e174d1d..ec5ac09c9 100644
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
+@@ -764,7 +801,7 @@ TASK_LIST_START
TEST_ENTRY (error_message)
TEST_ENTRY (sys_error)
@@ -6268,7 +6549,7 @@ index 58e174d1d..ec5ac09c9 100644
TEST_ENTRY (timer)
TEST_ENTRY (timer_init)
TEST_ENTRY (timer_again)
-@@ -779,7 +812,7 @@ TASK_LIST_START
+@@ -779,7 +816,7 @@ TASK_LIST_START
TEST_ENTRY (timer_early_check)
TEST_ENTRY (idle_starvation)
@@ -6277,7 +6558,7 @@ index 58e174d1d..ec5ac09c9 100644
TEST_ENTRY (ref)
TEST_ENTRY (idle_ref)
TEST_ENTRY (fs_poll_ref)
-@@ -812,15 +845,18 @@ TASK_LIST_START
+@@ -812,15 +849,18 @@ TASK_LIST_START
TEST_ENTRY (has_ref)
TEST_ENTRY (loop_handles)
@@ -6299,7 +6580,7 @@ index 58e174d1d..ec5ac09c9 100644
TEST_ENTRY (async_null_cb)
TEST_ENTRY (eintr_handling)
-@@ -866,7 +902,9 @@ TASK_LIST_START
+@@ -866,7 +906,9 @@ TASK_LIST_START
TEST_ENTRY (poll_duplex)
TEST_ENTRY (poll_unidirectional)
@@ -6309,7 +6590,7 @@ index 58e174d1d..ec5ac09c9 100644
TEST_ENTRY (poll_bad_fdtype)
#if (defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))) && \
!defined(__sun)
-@@ -909,12 +947,14 @@ TASK_LIST_START
+@@ -909,12 +951,14 @@ TASK_LIST_START
TEST_ENTRY (spawn_inherit_streams)
TEST_ENTRY (spawn_quoted_path)
TEST_ENTRY (spawn_tcp_server)
@@ -6324,7 +6605,7 @@ index 58e174d1d..ec5ac09c9 100644
TEST_ENTRY (kill)
TEST_ENTRY (kill_invalid_signum)
-@@ -966,7 +1006,9 @@ TASK_LIST_START
+@@ -966,7 +1010,9 @@ TASK_LIST_START
TEST_ENTRY (fs_fstat)
TEST_ENTRY (fs_access)
TEST_ENTRY (fs_chmod)
@@ -6334,7 +6615,7 @@ index 58e174d1d..ec5ac09c9 100644
TEST_ENTRY (fs_unlink_readonly)
#ifdef _WIN32
TEST_ENTRY (fs_unlink_archive_readonly)
-@@ -1045,8 +1087,10 @@ TASK_LIST_START
+@@ -1045,8 +1091,10 @@ TASK_LIST_START
TEST_ENTRY (get_osfhandle_valid_handle)
TEST_ENTRY (open_osfhandle_valid_handle)
TEST_ENTRY (strscpy)
@@ -6345,7 +6626,7 @@ index 58e174d1d..ec5ac09c9 100644
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
+@@ -1064,14 +1112,18 @@ TASK_LIST_START
TEST_ENTRY (thread_create)
TEST_ENTRY (thread_equal)
TEST_ENTRY (dlerror)
@@ -6357,14 +6638,16 @@ index 58e174d1d..ec5ac09c9 100644
TEST_ENTRY (queue_foreach_delete)
-
+#endif
++#ifdef CONFIG_DEV_URANDOM
TEST_ENTRY (random_async)
TEST_ENTRY (random_sync)
-
++#endif
+#if 0
TEST_ENTRY (handle_type_name)
TEST_ENTRY (req_type_name)
TEST_ENTRY (getters_setters)
-@@ -1105,4 +1151,5 @@ TASK_LIST_START
+@@ -1105,4 +1157,5 @@ TASK_LIST_START
TEST_ENTRY (fail_always)
TEST_ENTRY (pass_always)
#endif
@@ -6543,8 +6826,204 @@ index a2db42cce..581f31b9e 100644
+ MAKE_VALGRIND_HAPPY(loop);
return 0;
}
+diff --git a/test/test-ping-pong.c b/test/test-ping-pong.c
+index c86a3f4a6..50e47d6a3 100644
+--- a/test/test-ping-pong.c
++++ b/test/test-ping-pong.c
+@@ -49,7 +49,7 @@ typedef struct {
+ uv_pipe_t pipe;
+ } stream;
+ uv_connect_t connect_req;
+- char read_buffer[BUFSIZE];
++ // char read_buffer[BUFSIZE];
+ } pinger_t;
+
+
+@@ -102,7 +102,34 @@ static void pinger_write_ping(pinger_t* pinger) {
+ FATAL("uv_write failed");
+ }
+
+- puts("PING");
++ // puts("PING");
++}
++
++
++static void pinger_after_stop_write(uv_write_t *req, int status) {
++ ASSERT(status == 0);
++ pinger_t* pinger = (pinger_t*)req->data;
++ uv_close((uv_handle_t*)(&pinger->stream.tcp), pinger_on_close);
++ free(req);
++}
++
++
++static void pinger_write_stop(pinger_t* pinger) {
++ uv_write_t *req;
++ uv_buf_t bufs;
++
++ bufs.base = "QQS";
++ bufs.len = 3;
++
++ req = malloc(sizeof(*req));
++ req->data = pinger;
++ if (uv_write(req,
++ (uv_stream_t*) &pinger->stream.tcp,
++ &bufs,
++ 1,
++ pinger_after_stop_write)) {
++ FATAL("uv_write failed");
++ }
+ }
+
+
+@@ -133,13 +160,13 @@ static void pinger_read_cb(uv_stream_t* stream,
+ if (pinger->state != 0)
+ continue;
+
+- printf("PONG %d\n", pinger->pongs);
++ // printf("PONG %d\n", pinger->pongs);
+ pinger->pongs++;
+
+ if (pinger->pongs < NUM_PINGS) {
+ pinger_write_ping(pinger);
+ } else {
+- uv_close((uv_handle_t*)(&pinger->stream.tcp), pinger_on_close);
++ pinger_write_stop(pinger);
+ break;
+ }
+ }
+@@ -164,7 +191,7 @@ static void pinger_on_connect(uv_connect_t *req, int status) {
+ uv_read_start((uv_stream_t*)(req->handle), alloc_cb, pinger_read_cb);
+ }
+
+-
++#if 0
+ /* same ping-pong test, but using IPv6 connection */
+ static void tcp_pinger_v6_new(int vectored_writes) {
+ int r;
+@@ -195,13 +222,16 @@ static void tcp_pinger_v6_new(int vectored_writes) {
+ /* Synchronous connect callbacks are not allowed. */
+ ASSERT(pinger_on_connect_count == 0);
+ }
++#endif
+
+-
+-static void tcp_pinger_new(int vectored_writes) {
++static void tcp_pinger_new(uv_context_t *ctx, int vectored_writes) {
+ int r;
+ struct sockaddr_in server_addr;
+ pinger_t *pinger;
+
++ pinger_on_connect_count = 0;
++ completed_pingers = 0;
++
+ ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &server_addr));
+ pinger = malloc(sizeof(*pinger));
+ ASSERT(pinger != NULL);
+@@ -210,7 +240,7 @@ static void tcp_pinger_new(int vectored_writes) {
+ pinger->pongs = 0;
+
+ /* Try to connect to the server and do NUM_PINGS ping-pongs. */
+- r = uv_tcp_init(uv_default_loop(), &pinger->stream.tcp);
++ r = uv_tcp_init(uv_default_loop(ctx), &pinger->stream.tcp);
+ pinger->stream.tcp.data = pinger;
+ ASSERT(!r);
+
+@@ -226,11 +256,14 @@ static void tcp_pinger_new(int vectored_writes) {
+ ASSERT(pinger_on_connect_count == 0);
+ }
+
+-
+-static void pipe_pinger_new(int vectored_writes) {
++#if 0
++static void pipe_pinger_new(uv_context_t *ctx, int vectored_writes) {
+ int r;
+ pinger_t *pinger;
+
++ pinger_on_connect_count = 0;
++ completed_pingers = 0;
++
+ pinger = (pinger_t*)malloc(sizeof(*pinger));
+ ASSERT(pinger != NULL);
+ pinger->vectored_writes = vectored_writes;
+@@ -238,7 +271,7 @@ static void pipe_pinger_new(int vectored_writes) {
+ pinger->pongs = 0;
+
+ /* Try to connect to the server and do NUM_PINGS ping-pongs. */
+- r = uv_pipe_init(uv_default_loop(), &pinger->stream.pipe, 0);
++ r = uv_pipe_init(uv_default_loop(ctx), &pinger->stream.pipe, 0);
+ pinger->stream.pipe.data = pinger;
+ ASSERT(!r);
+
+@@ -250,29 +283,34 @@ static void pipe_pinger_new(int vectored_writes) {
+ /* Synchronous connect callbacks are not allowed. */
+ ASSERT(pinger_on_connect_count == 0);
+ }
++#endif
+
+-
+-static int run_ping_pong_test(void) {
+- uv_run(uv_default_loop(), UV_RUN_DEFAULT);
++static int run_ping_pong_test(uv_context_t *ctx) {
++ uv_loop_t *loop = uv_default_loop(ctx);
++ uv_run(loop, UV_RUN_DEFAULT);
+ ASSERT(completed_pingers == 1);
+
+- MAKE_VALGRIND_HAPPY();
++ MAKE_VALGRIND_HAPPY(loop);
+ return 0;
+ }
+
+
+ TEST_IMPL(tcp_ping_pong) {
+- tcp_pinger_new(0);
+- return run_ping_pong_test();
++ uv_context_t context;
++ uv_library_init(&context);
++ tcp_pinger_new(&context, 0);
++ return run_ping_pong_test(&context);
+ }
+
+
+ TEST_IMPL(tcp_ping_pong_vec) {
+- tcp_pinger_new(1);
+- return run_ping_pong_test();
++ uv_context_t context;
++ uv_library_init(&context);
++ tcp_pinger_new(&context, 1);
++ return run_ping_pong_test(&context);
+ }
+
+-
++#if 0
+ TEST_IMPL(tcp6_ping_pong) {
+ if (!can_ipv6())
+ RETURN_SKIP("IPv6 not supported");
+@@ -288,14 +326,18 @@ TEST_IMPL(tcp6_ping_pong_vec) {
+ return run_ping_pong_test();
+ }
+
+-
+ TEST_IMPL(pipe_ping_pong) {
+- pipe_pinger_new(0);
+- return run_ping_pong_test();
++ uv_context_t context;
++ uv_library_init(&context);
++ pipe_pinger_new(&context, 0);
++ return run_ping_pong_test(&context);
+ }
+
+
+ TEST_IMPL(pipe_ping_pong_vec) {
+- pipe_pinger_new(1);
+- return run_ping_pong_test();
++ uv_context_t context;
++ uv_library_init(&context);
++ pipe_pinger_new(&context, 1);
++ return run_ping_pong_test(&context);
+ }
++#endif
diff --git a/test/test-poll-close.c b/test/test-poll-close.c
-index 2eccddf5b..050316428 100644
+index 2eccddf5b..c5b059d03 100644
--- a/test/test-poll-close.c
+++ b/test/test-poll-close.c
@@ -30,7 +30,7 @@
@@ -6574,7 +7053,7 @@ index 2eccddf5b..050316428 100644
#ifdef _WIN32
{
struct WSAData wsa_data;
-@@ -56,7 +63,7 @@ TEST_IMPL(poll_close) {
+@@ -56,18 +63,19 @@ TEST_IMPL(poll_close) {
for (i = 0; i < NUM_SOCKETS; i++) {
sockets[i] = socket(AF_INET, SOCK_STREAM, 0);
@@ -6583,8 +7062,9 @@ index 2eccddf5b..050316428 100644
uv_poll_start(&poll_handles[i], UV_READABLE | UV_WRITABLE, NULL);
}
-@@ -64,10 +71,10 @@ TEST_IMPL(poll_close) {
+ for (i = 0; i < NUM_SOCKETS; i++) {
uv_close((uv_handle_t*) &poll_handles[i], close_cb);
++ close(sockets[i]);
}
- uv_run(uv_default_loop(), UV_RUN_DEFAULT);
diff --git a/system/libuv/libuv/Kconfig b/system/libuv/libuv/Kconfig
index 41c0102..22cb439 100644
--- a/system/libuv/libuv/Kconfig
+++ b/system/libuv/libuv/Kconfig
@@ -54,6 +54,13 @@ config LIBUV_STREAM_READ_SIZE
---help---
Defines the size of buffer used for stream reads.
+config LIBUV_PIPE
+ bool "libuv pipe support"
+ default n
+ depends on LIBUV_STREAM
+ ---help---
+ Enable libuv pipe support.
+
config LIBUV_FS
bool "libuv FS support"
default n
diff --git a/system/libuv/libuv/Makefile b/system/libuv/libuv/Makefile
index 558ec61..4556fdd 100644
--- a/system/libuv/libuv/Makefile
+++ b/system/libuv/libuv/Makefile
@@ -86,6 +86,10 @@ ifeq ($(CONFIG_LIBUV_ASYNC),y)
CSRCS += $(LIBUV_UNPACKDIR)/src/unix/async.c
endif
+ifeq ($(CONFIG_LIBUV_PIPE),y)
+CSRCS += $(LIBUV_UNPACKDIR)/src/unix/pipe.c
+endif
+
ifeq ($(CONFIG_LIBUV_FS),y)
CSRCS += $(LIBUV_UNPACKDIR)/src/unix/fs.c
endif
diff --git a/system/libuv/tests/Makefile b/system/libuv/tests/Makefile
index 26728c5..d567f6b 100644
--- a/system/libuv/tests/Makefile
+++ b/system/libuv/tests/Makefile
@@ -49,11 +49,13 @@ 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-ping-pong.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
+ifeq ($(CONFIG_DEV_URANDOM),y)
CSRCS += $(LIBUV_UNPACKDIR)/test/test-random.c
-
+endif
# Test helpers
CSRCS += $(LIBUV_UNPACKDIR)/test/echo-server.c