Commit 69b139cf authored by Brad King's avatar Brad King
Browse files

Merge branch 'upstream-libuv' into update-libuv

* upstream-libuv:
  libuv 2019-06-10 (ee24ce90)
parents ab630723 b4069b04
...@@ -206,6 +206,7 @@ typedef enum { ...@@ -206,6 +206,7 @@ typedef enum {
/* Handle types. */ /* Handle types. */
typedef struct uv_loop_s uv_loop_t; typedef struct uv_loop_s uv_loop_t;
typedef struct uv_handle_s uv_handle_t; typedef struct uv_handle_s uv_handle_t;
typedef struct uv_dir_s uv_dir_t;
typedef struct uv_stream_s uv_stream_t; typedef struct uv_stream_s uv_stream_t;
typedef struct uv_tcp_s uv_tcp_t; typedef struct uv_tcp_s uv_tcp_t;
typedef struct uv_udp_s uv_udp_t; typedef struct uv_udp_s uv_udp_t;
...@@ -634,7 +635,11 @@ UV_EXTERN int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock); ...@@ -634,7 +635,11 @@ UV_EXTERN int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock);
UV_EXTERN int uv_udp_bind(uv_udp_t* handle, UV_EXTERN int uv_udp_bind(uv_udp_t* handle,
const struct sockaddr* addr, const struct sockaddr* addr,
unsigned int flags); unsigned int flags);
UV_EXTERN int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr);
UV_EXTERN int uv_udp_getpeername(const uv_udp_t* handle,
struct sockaddr* name,
int* namelen);
UV_EXTERN int uv_udp_getsockname(const uv_udp_t* handle, UV_EXTERN int uv_udp_getsockname(const uv_udp_t* handle,
struct sockaddr* name, struct sockaddr* name,
int* namelen); int* namelen);
...@@ -1111,6 +1116,11 @@ typedef struct { ...@@ -1111,6 +1116,11 @@ typedef struct {
long tv_usec; long tv_usec;
} uv_timeval_t; } uv_timeval_t;
typedef struct {
int64_t tv_sec;
int32_t tv_usec;
} uv_timeval64_t;
typedef struct { typedef struct {
uv_timeval_t ru_utime; /* user CPU time used */ uv_timeval_t ru_utime; /* user CPU time used */
uv_timeval_t ru_stime; /* system CPU time used */ uv_timeval_t ru_stime; /* system CPU time used */
...@@ -1162,6 +1172,17 @@ UV_EXTERN int uv_os_getenv(const char* name, char* buffer, size_t* size); ...@@ -1162,6 +1172,17 @@ UV_EXTERN int uv_os_getenv(const char* name, char* buffer, size_t* size);
UV_EXTERN int uv_os_setenv(const char* name, const char* value); UV_EXTERN int uv_os_setenv(const char* name, const char* value);
UV_EXTERN int uv_os_unsetenv(const char* name); UV_EXTERN int uv_os_unsetenv(const char* name);
#ifdef MAXHOSTNAMELEN
# define UV_MAXHOSTNAMESIZE (MAXHOSTNAMELEN + 1)
#else
/*
Fallback for the maximum hostname size, including the null terminator. The
Windows gethostname() documentation states that 256 bytes will always be
large enough to hold the null-terminated hostname.
*/
# define UV_MAXHOSTNAMESIZE 256
#endif
UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size); UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size);
UV_EXTERN int uv_os_uname(uv_utsname_t* buffer); UV_EXTERN int uv_os_uname(uv_utsname_t* buffer);
...@@ -1199,9 +1220,19 @@ typedef enum { ...@@ -1199,9 +1220,19 @@ typedef enum {
UV_FS_FCHOWN, UV_FS_FCHOWN,
UV_FS_REALPATH, UV_FS_REALPATH,
UV_FS_COPYFILE, UV_FS_COPYFILE,
UV_FS_LCHOWN UV_FS_LCHOWN,
UV_FS_OPENDIR,
UV_FS_READDIR,
UV_FS_CLOSEDIR
} uv_fs_type; } uv_fs_type;
struct uv_dir_s {
uv_dirent_t* dirents;
size_t nentries;
void* reserved[4];
UV_DIR_PRIVATE_FIELDS
};
/* uv_fs_t is a subclass of uv_req_t. */ /* uv_fs_t is a subclass of uv_req_t. */
struct uv_fs_s { struct uv_fs_s {
UV_REQ_FIELDS UV_REQ_FIELDS
...@@ -1294,6 +1325,18 @@ UV_EXTERN int uv_fs_scandir(uv_loop_t* loop, ...@@ -1294,6 +1325,18 @@ UV_EXTERN int uv_fs_scandir(uv_loop_t* loop,
uv_fs_cb cb); uv_fs_cb cb);
UV_EXTERN int uv_fs_scandir_next(uv_fs_t* req, UV_EXTERN int uv_fs_scandir_next(uv_fs_t* req,
uv_dirent_t* ent); uv_dirent_t* ent);
UV_EXTERN int uv_fs_opendir(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
uv_fs_cb cb);
UV_EXTERN int uv_fs_readdir(uv_loop_t* loop,
uv_fs_t* req,
uv_dir_t* dir,
uv_fs_cb cb);
UV_EXTERN int uv_fs_closedir(uv_loop_t* loop,
uv_fs_t* req,
uv_dir_t* dir,
uv_fs_cb cb);
UV_EXTERN int uv_fs_stat(uv_loop_t* loop, UV_EXTERN int uv_fs_stat(uv_loop_t* loop,
uv_fs_t* req, uv_fs_t* req,
const char* path, const char* path,
...@@ -1536,6 +1579,7 @@ UV_EXTERN int uv_chdir(const char* dir); ...@@ -1536,6 +1579,7 @@ UV_EXTERN int uv_chdir(const char* dir);
UV_EXTERN uint64_t uv_get_free_memory(void); UV_EXTERN uint64_t uv_get_free_memory(void);
UV_EXTERN uint64_t uv_get_total_memory(void); UV_EXTERN uint64_t uv_get_total_memory(void);
UV_EXTERN uint64_t uv_get_constrained_memory(void);
UV_EXTERN uint64_t uv_hrtime(void); UV_EXTERN uint64_t uv_hrtime(void);
...@@ -1589,9 +1633,29 @@ UV_EXTERN void uv_key_delete(uv_key_t* key); ...@@ -1589,9 +1633,29 @@ UV_EXTERN void uv_key_delete(uv_key_t* key);
UV_EXTERN void* uv_key_get(uv_key_t* key); UV_EXTERN void* uv_key_get(uv_key_t* key);
UV_EXTERN void uv_key_set(uv_key_t* key, void* value); UV_EXTERN void uv_key_set(uv_key_t* key, void* value);
UV_EXTERN int uv_gettimeofday(uv_timeval64_t* tv);
typedef void (*uv_thread_cb)(void* arg); typedef void (*uv_thread_cb)(void* arg);
UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg); UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg);
typedef enum {
UV_THREAD_NO_FLAGS = 0x00,
UV_THREAD_HAS_STACK_SIZE = 0x01
} uv_thread_create_flags;
struct uv_thread_options_s {
unsigned int flags;
size_t stack_size;
/* More fields may be added at any time. */
};
typedef struct uv_thread_options_s uv_thread_options_t;
UV_EXTERN int uv_thread_create_ex(uv_thread_t* tid,
const uv_thread_options_t* params,
uv_thread_cb entry,
void* arg);
UV_EXTERN uv_thread_t uv_thread_self(void); UV_EXTERN uv_thread_t uv_thread_self(void);
UV_EXTERN int uv_thread_join(uv_thread_t *tid); UV_EXTERN int uv_thread_join(uv_thread_t *tid);
UV_EXTERN int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2); UV_EXTERN int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2);
......
...@@ -31,13 +31,14 @@ ...@@ -31,13 +31,14 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h> /* MAXHOSTNAMELEN on Solaris */
#include <termios.h> #include <termios.h>
#include <pwd.h> #include <pwd.h>
#if !defined(__MVS__) #if !defined(__MVS__)
#include <semaphore.h> #include <semaphore.h>
#include <sys/param.h> /* MAXHOSTNAMELEN on Linux and the BSDs */
#endif #endif
#include <pthread.h> #include <pthread.h>
#include <signal.h> #include <signal.h>
...@@ -50,8 +51,6 @@ ...@@ -50,8 +51,6 @@
# include "linux.h" # include "linux.h"
#elif defined (__MVS__) #elif defined (__MVS__)
# include "os390.h" # include "os390.h"
#elif defined(__PASE__)
# include "posix.h"
#elif defined(_AIX) #elif defined(_AIX)
# include "aix.h" # include "aix.h"
#elif defined(__sun) #elif defined(__sun)
...@@ -64,9 +63,12 @@ ...@@ -64,9 +63,12 @@
defined(__OpenBSD__) || \ defined(__OpenBSD__) || \
defined(__NetBSD__) defined(__NetBSD__)
# include "bsd.h" # include "bsd.h"
#elif defined(__CYGWIN__) || defined(__MSYS__) #elif defined(__PASE__) || \
defined(__CYGWIN__) || \
defined(__MSYS__) || \
defined(__GNU__)
# include "posix.h" # include "posix.h"
#elif defined(__GNU__) #elif defined(__HAIKU__)
# include "posix.h" # include "posix.h"
#endif #endif
...@@ -149,7 +151,9 @@ typedef pthread_cond_t uv_cond_t; ...@@ -149,7 +151,9 @@ typedef pthread_cond_t uv_cond_t;
typedef pthread_key_t uv_key_t; typedef pthread_key_t uv_key_t;
/* Note: guard clauses should match uv_barrier_init's in src/unix/thread.c. */ /* Note: guard clauses should match uv_barrier_init's in src/unix/thread.c. */
#if defined(_AIX) || !defined(PTHREAD_BARRIER_SERIAL_THREAD) #if defined(_AIX) || \
defined(__OpenBSD__) || \
!defined(PTHREAD_BARRIER_SERIAL_THREAD)
/* TODO(bnoordhuis) Merge into uv_barrier_t in v2. */ /* TODO(bnoordhuis) Merge into uv_barrier_t in v2. */
struct _uv_barrier { struct _uv_barrier {
uv_mutex_t mutex; uv_mutex_t mutex;
...@@ -178,6 +182,9 @@ typedef uid_t uv_uid_t; ...@@ -178,6 +182,9 @@ typedef uid_t uv_uid_t;
typedef struct dirent uv__dirent_t; typedef struct dirent uv__dirent_t;
#define UV_DIR_PRIVATE_FIELDS \
DIR* dir;
#if defined(DT_UNKNOWN) #if defined(DT_UNKNOWN)
# define HAVE_DIRENT_TYPES # define HAVE_DIRENT_TYPES
# if defined(DT_REG) # if defined(DT_REG)
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
*/ */
#define UV_VERSION_MAJOR 1 #define UV_VERSION_MAJOR 1
#define UV_VERSION_MINOR 24 #define UV_VERSION_MINOR 29
#define UV_VERSION_PATCH 2 #define UV_VERSION_PATCH 2
#define UV_VERSION_IS_RELEASE 0 #define UV_VERSION_IS_RELEASE 0
#define UV_VERSION_SUFFIX "dev" #define UV_VERSION_SUFFIX "dev"
......
...@@ -312,6 +312,11 @@ typedef struct uv__dirent_s { ...@@ -312,6 +312,11 @@ typedef struct uv__dirent_s {
char d_name[1]; char d_name[1];
} uv__dirent_t; } uv__dirent_t;
#define UV_DIR_PRIVATE_FIELDS \
HANDLE dir_handle; \
WIN32_FIND_DATAW find_data; \
BOOL need_find_call;
#define HAVE_DIRENT_TYPES #define HAVE_DIRENT_TYPES
#define UV__DT_DIR UV_DIRENT_DIR #define UV__DT_DIR UV_DIRENT_DIR
#define UV__DT_FILE UV_DIRENT_FILE #define UV__DT_FILE UV_DIRENT_FILE
......
...@@ -22,12 +22,20 @@ ...@@ -22,12 +22,20 @@
#include "uv.h" #include "uv.h"
#include "uv-common.h" #include "uv-common.h"
#ifdef _WIN32
#include "win/internal.h"
#include "win/handle-inl.h"
#define uv__make_close_pending(h) uv_want_endgame((h)->loop, (h))
#else
#include "unix/internal.h"
#endif
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
struct poll_ctx { struct poll_ctx {
uv_fs_poll_t* parent_handle; /* NULL if parent has been stopped or closed */ uv_fs_poll_t* parent_handle;
int busy_polling; int busy_polling;
unsigned int interval; unsigned int interval;
uint64_t start_time; uint64_t start_time;
...@@ -36,6 +44,7 @@ struct poll_ctx { ...@@ -36,6 +44,7 @@ struct poll_ctx {
uv_timer_t timer_handle; uv_timer_t timer_handle;
uv_fs_t fs_req; /* TODO(bnoordhuis) mark fs_req internal */ uv_fs_t fs_req; /* TODO(bnoordhuis) mark fs_req internal */
uv_stat_t statbuf; uv_stat_t statbuf;
struct poll_ctx* previous; /* context from previous start()..stop() period */
char path[1]; /* variable length */ char path[1]; /* variable length */
}; };
...@@ -49,6 +58,7 @@ static uv_stat_t zero_statbuf; ...@@ -49,6 +58,7 @@ static uv_stat_t zero_statbuf;
int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle) { int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle) {
uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_POLL); uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_POLL);
handle->poll_ctx = NULL;
return 0; return 0;
} }
...@@ -62,7 +72,7 @@ int uv_fs_poll_start(uv_fs_poll_t* handle, ...@@ -62,7 +72,7 @@ int uv_fs_poll_start(uv_fs_poll_t* handle,
size_t len; size_t len;
int err; int err;
if (uv__is_active(handle)) if (uv_is_active((uv_handle_t*)handle))
return 0; return 0;
loop = handle->loop; loop = handle->loop;
...@@ -90,6 +100,8 @@ int uv_fs_poll_start(uv_fs_poll_t* handle, ...@@ -90,6 +100,8 @@ int uv_fs_poll_start(uv_fs_poll_t* handle,
if (err < 0) if (err < 0)
goto error; goto error;
if (handle->poll_ctx != NULL)
ctx->previous = handle->poll_ctx;
handle->poll_ctx = ctx; handle->poll_ctx = ctx;
uv__handle_start(handle); uv__handle_start(handle);
...@@ -104,19 +116,17 @@ error: ...@@ -104,19 +116,17 @@ error:
int uv_fs_poll_stop(uv_fs_poll_t* handle) { int uv_fs_poll_stop(uv_fs_poll_t* handle) {
struct poll_ctx* ctx; struct poll_ctx* ctx;
if (!uv__is_active(handle)) if (!uv_is_active((uv_handle_t*)handle))
return 0; return 0;
ctx = handle->poll_ctx; ctx = handle->poll_ctx;
assert(ctx != NULL); assert(ctx != NULL);
assert(ctx->parent_handle != NULL); assert(ctx->parent_handle == handle);
ctx->parent_handle = NULL;
handle->poll_ctx = NULL;
/* Close the timer if it's active. If it's inactive, there's a stat request /* Close the timer if it's active. If it's inactive, there's a stat request
* in progress and poll_cb will take care of the cleanup. * in progress and poll_cb will take care of the cleanup.
*/ */
if (uv__is_active(&ctx->timer_handle)) if (uv_is_active((uv_handle_t*)&ctx->timer_handle))
uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb); uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
uv__handle_stop(handle); uv__handle_stop(handle);
...@@ -129,7 +139,7 @@ int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) { ...@@ -129,7 +139,7 @@ int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) {
struct poll_ctx* ctx; struct poll_ctx* ctx;
size_t required_len; size_t required_len;
if (!uv__is_active(handle)) { if (!uv_is_active((uv_handle_t*)handle)) {
*size = 0; *size = 0;
return UV_EINVAL; return UV_EINVAL;
} }
...@@ -153,6 +163,9 @@ int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) { ...@@ -153,6 +163,9 @@ int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) {
void uv__fs_poll_close(uv_fs_poll_t* handle) { void uv__fs_poll_close(uv_fs_poll_t* handle) {
uv_fs_poll_stop(handle); uv_fs_poll_stop(handle);
if (handle->poll_ctx == NULL)
uv__make_close_pending((uv_handle_t*)handle);
} }
...@@ -173,14 +186,13 @@ static void poll_cb(uv_fs_t* req) { ...@@ -173,14 +186,13 @@ static void poll_cb(uv_fs_t* req) {
uv_stat_t* statbuf; uv_stat_t* statbuf;
struct poll_ctx* ctx; struct poll_ctx* ctx;
uint64_t interval; uint64_t interval;
uv_fs_poll_t* handle;
ctx = container_of(req, struct poll_ctx, fs_req); ctx = container_of(req, struct poll_ctx, fs_req);
handle = ctx->parent_handle;
if (ctx->parent_handle == NULL) { /* handle has been stopped or closed */ if (!uv_is_active((uv_handle_t*)handle) || uv__is_closing(handle))
uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb); goto out;
uv_fs_req_cleanup(req);
return;
}
if (req->result != 0) { if (req->result != 0) {
if (ctx->busy_polling != req->result) { if (ctx->busy_polling != req->result) {
...@@ -205,7 +217,7 @@ static void poll_cb(uv_fs_t* req) { ...@@ -205,7 +217,7 @@ static void poll_cb(uv_fs_t* req) {
out: out:
uv_fs_req_cleanup(req); uv_fs_req_cleanup(req);
if (ctx->parent_handle == NULL) { /* handle has been stopped by callback */ if (!uv_is_active((uv_handle_t*)handle) || uv__is_closing(handle)) {
uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb); uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
return; return;
} }
...@@ -219,8 +231,27 @@ out: ...@@ -219,8 +231,27 @@ out:
} }
static void timer_close_cb(uv_handle_t* handle) { static void timer_close_cb(uv_handle_t* timer) {
uv__free(container_of(handle, struct poll_ctx, timer_handle)); struct poll_ctx* ctx;
struct poll_ctx* it;
struct poll_ctx* last;
uv_fs_poll_t* handle;
ctx = container_of(timer, struct poll_ctx, timer_handle);
handle = ctx->parent_handle;
if (ctx == handle->poll_ctx) {
handle->poll_ctx = ctx->previous;
if (handle->poll_ctx == NULL && uv__is_closing(handle))
uv__make_close_pending((uv_handle_t*)handle);
} else {
for (last = handle->poll_ctx, it = last->previous;
it != ctx;
last = it, it = it->previous) {
assert(last->previous != NULL);
}
last->previous = ctx->previous;
}
uv__free(ctx);
} }
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include <stdlib.h> #include <stdlib.h>
#define MAX_THREADPOOL_SIZE 128 #define MAX_THREADPOOL_SIZE 1024
static uv_once_t once = UV_ONCE_INIT; static uv_once_t once = UV_ONCE_INIT;
static uv_cond_t cond; static uv_cond_t cond;
......
...@@ -344,6 +344,11 @@ uint64_t uv_get_total_memory(void) { ...@@ -344,6 +344,11 @@ uint64_t uv_get_total_memory(void) {
} }
uint64_t uv_get_constrained_memory(void) {
return 0; /* Memory constraints are unknown. */
}
void uv_loadavg(double avg[3]) { void uv_loadavg(double avg[3]) {
perfstat_cpu_total_t ps_total; perfstat_cpu_total_t ps_total;
int result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1); int result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1);
...@@ -1041,6 +1046,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { ...@@ -1041,6 +1046,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
struct poll_ctl pc; struct poll_ctl pc;
assert(loop->watchers != NULL); assert(loop->watchers != NULL);
assert(fd >= 0);
events = (struct pollfd*) loop->watchers[loop->nwatchers]; events = (struct pollfd*) loop->watchers[loop->nwatchers];
nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
......
...@@ -61,14 +61,43 @@ int uv_async_send(uv_async_t* handle) { ...@@ -61,14 +61,43 @@ int uv_async_send(uv_async_t* handle) {
if (ACCESS_ONCE(int, handle->pending) != 0) if (ACCESS_ONCE(int, handle->pending) != 0)
return 0; return 0;
if (cmpxchgi(&handle->pending, 0, 1) == 0) /* Tell the other thread we're busy with the handle. */
if (cmpxchgi(&handle->pending, 0, 1) != 0)
return 0;
/* Wake up the other thread's event loop. */
uv__async_send(handle->loop); uv__async_send(handle->loop);
/* Tell the other thread we're done. */
if (cmpxchgi(&handle->pending, 1, 2) != 1)
abort();
return 0; return 0;
} }
/* Only call this from the event loop thread. */
static int uv__async_spin(uv_async_t* handle) {
int rc;
for (;;) {
/* rc=0 -- handle is not pending.
* rc=1 -- handle is pending, other thread is still working with it.
* rc=2 -- handle is pending, other thread is done.
*/
rc = cmpxchgi(&handle->pending, 2, 0);
if (rc != 1)
return rc;
/* Other thread is busy with this handle, spin until it's done. */
cpu_relax();
}
}
void uv__async_close(uv_async_t* handle) { void uv__async_close(uv_async_t* handle) {
uv__async_spin(handle);
QUEUE_REMOVE(&handle->queue); QUEUE_REMOVE(&handle->queue);
uv__handle_stop(handle); uv__handle_stop(handle);
} }
...@@ -109,8 +138,8 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { ...@@ -109,8 +138,8 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
QUEUE_REMOVE(q); QUEUE_REMOVE(q);
QUEUE_INSERT_TAIL(&loop->async_handles, q); QUEUE_INSERT_TAIL(&loop->async_handles, q);
if (cmpxchgi(&h->pending, 1, 0) == 0) if (0 == uv__async_spin(h))
continue; continue; /* Not pending. */