From 3307fabda302b693acbec3a9f11b6542428d5b96 Mon Sep 17 00:00:00 2001 From: Simon Piriou Date: Fri, 7 Aug 2020 19:48:02 +0200 Subject: [PATCH] initial libuv port to nuttx --- include/uv.h | 109 ++- include/uv/nuttx.h | 67 ++ include/uv/unix.h | 155 +++- src/inet.c | 50 +- src/queue.h | 4 +- src/random.c | 42 +- src/unix/async.c | 71 +- 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 | 1016 +++++++++++++++++++++++++++ src/unix/nuttx_tcp.c | 311 ++++++++ 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 +- 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 | 30 +- test/test-fs-poll.c | 162 +++-- test/test-idle.c | 20 +- test/test-ip4-addr.c | 2 +- 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-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-walk-handles.c | 8 +- 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 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..d025e8a0b 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*); @@ -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 }; - +#ifndef CONFIG_LIBUV_LOW_FOOTPRINT #define UV_HANDLE_FIELDS \ /* public */ \ void* data; \ @@ -439,6 +488,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 +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, - 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 +1833,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 +1846,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 +#include + +#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..2c56e8a55 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,8 @@ typedef struct uv__io_s uv__io_t; struct uv__io_s { uv__io_cb cb; - 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 +241,105 @@ 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 + +#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_STREAM_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_STREAM_FIELDS \ + UV_LOOP_PRIVATE_PERFS_FIELDS \ UV_PLATFORM_LOOP_FIELDS \ #define UV_REQ_TYPE_PRIVATE /* empty */ @@ -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; \ UV_STREAM_PRIVATE_PLATFORM_FIELDS \ #define UV_TCP_PRIVATE_FIELDS /* empty */ @@ -327,12 +418,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; \ @@ -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 +++ 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..6fa87975f 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..26e45b334 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,11 +68,12 @@ static int uv__random(void* buf, size_t buflen) { #else rc = uv__random_devurandom(buf, buflen); #endif +#endif /* __NUTTX__ */ 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 +++ 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 #include /* sched_yield() */ -#ifdef __linux__ +#if defined (__linux__) || defined(__NUTTX__) #include #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..237a6b1bb 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 # include /* _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__) || \ @@ -87,8 +110,11 @@ extern char** environ; # include # 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,22 +138,31 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { handle->close_cb = close_cb; switch (handle->type) { +#ifdef CONFIG_LIBUV_PIPE case UV_NAMED_PIPE: uv__pipe_close((uv_pipe_t*)handle); break; +#endif +#if 0 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 +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; +#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 +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; - +#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 +220,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 +248,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 +286,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 +303,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 +338,26 @@ static void uv__finish_close(uv_handle_t* handle) { return; } break; +#endif +#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 /* CONFIG_LIBUV_STREAM */ +#ifdef CONFIG_LIBUV_UDP case UV_UDP: uv__udp_finish_close((uv_udp_t*)handle); break; - +#endif default: assert(0); break; @@ -324,10 +391,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 +405,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 +#ifdef CONFIG_LIBUV_STREAM 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 +449,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 + +#ifdef CONFIG_LIBUV_STREAM 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 +485,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 +515,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 +552,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 +570,7 @@ FILE* uv__open_file(const char* path) { return fp; } - +#if defined(CONFIG_LIBUV_STREAM) && defined(CONFIG_LIBUV_NET) int uv__accept(int sockfd) { int peerfd; int err; @@ -509,7 +602,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 +624,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 +654,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 +683,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 +761,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 +798,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 +846,7 @@ int uv_chdir(const char* dir) { return 0; } - +#if 0 void uv_disable_stdio_inheritance(void) { int fd; @@ -754,21 +857,31 @@ 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; 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; } - +#ifdef CONFIG_LIBUV_STREAM static int uv__run_pending(uv_loop_t* loop) { QUEUE* q; QUEUE pq; - 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; } +#endif - +#ifndef CONFIG_LIBUV_LOW_FOOTPRINT static unsigned int next_power_of_two(unsigned int val) { val -= 1; val |= val >> 1; @@ -852,12 +966,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 +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; +#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 +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); +#ifndef CONFIG_LIBUV_LOW_FOOTPRINT if (loop->watchers[w->fd] == NULL) { loop->watchers[w->fd] = w; loop->nfds++; } +#endif } @@ -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. */ +#ifndef CONFIG_LIBUV_LOW_FOOTPRINT if ((unsigned) w->fd >= loop->nwatchers) return; +#endif w->pevents &= ~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); +#ifndef CONFIG_LIBUV_LOW_FOOTPRINT if (loop->watchers[w->fd] != NULL) { assert(loop->watchers[w->fd] == w); assert(loop->nfds > 0); @@ -925,6 +1048,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,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); +#if 0 QUEUE_REMOVE(&w->pending_queue); +#endif /* Remove stale events for this file descriptor */ if (w->fd != -1) uv__platform_invalidate_fd(loop, w->fd); } - -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) { 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) { +#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 +1130,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 +1159,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 +1186,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 +1530,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 +1563,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..302d4f0c6 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -56,6 +56,12 @@ # define HAVE_PREADV 0 #endif +#ifdef __NUTTX__ +# include +# include + +#else /* __NUTTX__ */ + #if defined(__linux__) || defined(__sun) # include #endif @@ -84,6 +90,7 @@ #else # include #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__) || \ @@ -968,7 +980,7 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) { #endif } - +#ifndef __NUTTX__ 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 /* !__NUTTX__ */ 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 +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 -# 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 +1114,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 +1160,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 +1172,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 +1201,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 +1362,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; @@ -1542,40 +1561,56 @@ static void uv__fs_work(struct uv__work* w) { switch (req->fs_type) { X(ACCESS, access(req->path, req->flags)); +#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)); +#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 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)); +#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)); 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)); 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..107565e4c 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 @@ -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 */ 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..bb100390a 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 #include +#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 +#ifdef CONFIG_LIBUV_STREAM 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 +#include +#include + +#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..0642d057c --- /dev/null +++ b/src/unix/nuttx_stream.c @@ -0,0 +1,1016 @@ +/**************************************************************************** + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include /* 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); +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; + /* shutdown() not supported by NuttX */ + stream->shutdown_req = NULL; + stream->accepted_fd = -1; + 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); +} + + +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); +} + +#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; + + stream = container_of(w, uv_stream_t, io_watcher); + assert(events & POLLIN); + assert(stream->accepted_fd == -1); + assert(!(stream->flags & UV_HANDLE_CLOSING)); + + /* 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__ERR(ENOTCONN)) + continue; /* Ignore. Nothing we can do about that. */ + + 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 + } +} +#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) { +#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); + 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: + + server->accepted_fd = -1; + 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; + + switch (stream->type) { +#ifdef CONFIG_LIBUV_TCP + case UV_TCP: + err = uv_tcp_listen((uv_tcp_t*)stream, backlog, cb); + break; +#endif +#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; + } + + if (err == 0) + uv__handle_start(stream); + + return err; +} +#endif + +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; + +#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; + + 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; + } + + /* 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__stream_feed(stream->loop, stream); +} + +#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; + + assert(uv__stream_fd(stream) >= 0); + + while (!QUEUE_EMPTY(&stream->write_queue)) { + + 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); + continue; /* TODO(bnoordhuis) Start trying to write the next request. */ + } + + /* 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; + +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); + } +} + +#ifdef CONFIG_LIBUV_NET +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; +} +#endif + +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( +#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)) { + 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)) { + /* Called by either real poll event or stream_feed */ + uv__write(stream); + uv__write_callbacks(stream); + + /* Write queue drained. */ + if (QUEUE_EMPTY(&stream->write_queue)) + uv__drain(stream); + } +} + +#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 + * 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); + } +} +#endif + +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)); + } + + 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) { + QUEUE_REMOVE(&handle->pending_queue); + + 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; + } + + 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 +#include +#include +#include + +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 + +#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 +#include + +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/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 +++ 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 #include +#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, ¶ms, 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..3b4556d86 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 ((uv_loop_t*)(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..51d0b26b8 100644 --- a/test/test-fs-copyfile.c +++ b/test/test-fs-copyfile.c @@ -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 -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 +97,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 +129,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 +205,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 +218,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 -#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..edf5077cd 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) @@ -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) +#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 +151,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 +215,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 +228,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 +267,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 +329,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 +353,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 +435,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 +462,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 +473,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 +510,20 @@ 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 +#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 +549,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) @@ -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) - +#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 +726,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 +801,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 +816,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 +849,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 +906,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 +951,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 +1010,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 +1091,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 +1112,18 @@ 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 +#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 +1157,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-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..c5b059d03 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,18 +63,19 @@ 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); } 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); + 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 +#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