diff --git a/upstream_utils/libuv_patches/0001-Fix-missing-casts.patch b/upstream_utils/libuv_patches/0001-Fix-missing-casts.patch index 1c3b4bc27ac..4e2f01ae500 100644 --- a/upstream_utils/libuv_patches/0001-Fix-missing-casts.patch +++ b/upstream_utils/libuv_patches/0001-Fix-missing-casts.patch @@ -1,64 +1,49 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: PJ Reiniger Date: Tue, 26 Apr 2022 15:01:25 -0400 -Subject: [PATCH 01/10] Fix missing casts +Subject: [PATCH 1/9] Fix missing casts --- - include/uv/unix.h | 2 +- - src/fs-poll.c | 10 ++++----- - src/inet.c | 11 +++++----- + src/fs-poll.c | 10 ++++---- + src/inet.c | 11 ++++---- src/strscpy.c | 2 +- + src/thread-common.c | 2 +- src/threadpool.c | 2 +- src/unix/bsd-ifaddrs.c | 2 +- - src/unix/core.c | 12 +++++----- - src/unix/darwin-proctitle.c | 5 +++-- + src/unix/core.c | 18 ++++++------- + src/unix/darwin-proctitle.c | 5 ++-- src/unix/darwin.c | 2 +- - src/unix/epoll.c | 2 +- - src/unix/freebsd.c | 4 ++-- - src/unix/fs.c | 20 ++++++++--------- - src/unix/fsevents.c | 40 +++++++++++++++++----------------- - src/unix/getaddrinfo.c | 8 +++---- + src/unix/freebsd.c | 4 +-- + src/unix/fs.c | 20 +++++++-------- + src/unix/fsevents.c | 34 ++++++++++++------------- + src/unix/getaddrinfo.c | 8 +++--- src/unix/ibmi.c | 2 +- src/unix/kqueue.c | 6 ++--- - src/unix/linux-core.c | 5 ++--- - src/unix/linux-inotify.c | 4 ++-- + src/unix/linux.c | 46 +++++++++++++++++----------------- src/unix/loop.c | 2 +- - src/unix/netbsd.c | 4 ++-- - src/unix/openbsd.c | 4 ++-- - src/unix/pipe.c | 4 ++-- - src/unix/poll.c | 2 +- + src/unix/netbsd.c | 4 +-- + src/unix/openbsd.c | 4 +-- + src/unix/pipe.c | 4 +-- + src/unix/poll.c | 4 +-- src/unix/posix-poll.c | 2 +- - src/unix/process.c | 4 ++-- + src/unix/process.c | 4 +-- src/unix/proctitle.c | 2 +- src/unix/random-sysctl-linux.c | 2 +- - src/unix/stream.c | 35 ++++++++++++++--------------- - src/unix/thread.c | 7 +++--- - src/unix/udp.c | 8 +++---- - src/uv-common.c | 16 +++++++------- - src/win/core.c | 8 ++++--- - src/win/fs-event.c | 4 ++-- + src/unix/stream.c | 31 ++++++++++++----------- + src/unix/thread.c | 5 ++-- + src/unix/udp.c | 8 +++--- + src/uv-common.c | 16 ++++++------ + src/win/core.c | 8 +++--- + src/win/fs-event.c | 4 +-- src/win/fs-fd-hash-inl.h | 2 +- - src/win/fs.c | 26 +++++++++++----------- - src/win/pipe.c | 10 ++++----- - src/win/process.c | 12 +++++----- + src/win/fs.c | 28 ++++++++++----------- + src/win/pipe.c | 12 ++++----- + src/win/process.c | 16 ++++++------ src/win/tcp.c | 2 +- - src/win/thread.c | 4 ++-- - src/win/util.c | 29 ++++++++++++------------ - 40 files changed, 166 insertions(+), 162 deletions(-) + src/win/thread.c | 4 +-- + src/win/util.c | 27 ++++++++++---------- + 38 files changed, 185 insertions(+), 180 deletions(-) -diff --git a/include/uv/unix.h b/include/uv/unix.h -index ea37d78768654eef98e10982a6b6ddce934bbbbf..420be86c6f9984486c6420ff710c9dbcad09e411 100644 ---- a/include/uv/unix.h -+++ b/include/uv/unix.h -@@ -223,7 +223,7 @@ typedef struct { - int backend_fd; \ - void* pending_queue[2]; \ - void* watcher_queue[2]; \ -- uv__io_t** watchers; \ -+ void** watchers; \ - unsigned int nwatchers; \ - unsigned int nfds; \ - void* wq[2]; \ diff --git a/src/fs-poll.c b/src/fs-poll.c index 1bac1c568e36cadd0b68451926c6f045f88342d2..5a39daed095502b2db34f23fcaf0ab04f31f96ff 100644 --- a/src/fs-poll.c @@ -109,10 +94,10 @@ index 1bac1c568e36cadd0b68451926c6f045f88342d2..5a39daed095502b2db34f23fcaf0ab04 last = it, it = it->previous) { assert(last->previous != NULL); diff --git a/src/inet.c b/src/inet.c -index ddabf22fa52a0d4d25987c65f59e0e5456406fe3..ca8b6ac8b69779655f69da758aa63d810332c800 100644 +index cd77496846e90e8b8e61c63c10f498f153344fe5..dd94bea3886ca37945fcad7909d765e3700e3c21 100644 --- a/src/inet.c +++ b/src/inet.c -@@ -40,9 +40,9 @@ static int inet_pton6(const char *src, unsigned char *dst); +@@ -35,9 +35,9 @@ static int inet_pton6(const char *src, unsigned char *dst); int uv_inet_ntop(int af, const void* src, char* dst, size_t size) { switch (af) { case AF_INET: @@ -124,7 +109,7 @@ index ddabf22fa52a0d4d25987c65f59e0e5456406fe3..ca8b6ac8b69779655f69da758aa63d81 default: return UV_EAFNOSUPPORT; } -@@ -154,10 +154,11 @@ int uv_inet_pton(int af, const char* src, void* dst) { +@@ -149,10 +149,11 @@ int uv_inet_pton(int af, const char* src, void* dst) { switch (af) { case AF_INET: @@ -138,7 +123,7 @@ index ddabf22fa52a0d4d25987c65f59e0e5456406fe3..ca8b6ac8b69779655f69da758aa63d81 s = (char*) src; p = strchr(src, '%'); if (p != NULL) { -@@ -168,7 +169,7 @@ int uv_inet_pton(int af, const char* src, void* dst) { +@@ -163,7 +164,7 @@ int uv_inet_pton(int af, const char* src, void* dst) { memcpy(s, src, len); s[len] = '\0'; } @@ -160,11 +145,24 @@ index 20df6fcbed29e9d944c866ddbcd5c09345a426b3..6b4cc3bc741b40b9c2b13d4c06e7090f if (i == 0) return 0; +diff --git a/src/thread-common.c b/src/thread-common.c +index c67c0a7dd7279af6c67b7d5d4a623c47bdf3fff2..c0e39b543df229dd8cb8492bb695e61e40911453 100644 +--- a/src/thread-common.c ++++ b/src/thread-common.c +@@ -49,7 +49,7 @@ int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { + if (barrier == NULL || count == 0) + return UV_EINVAL; + +- b = uv__malloc(sizeof(*b)); ++ b = (struct _uv_barrier *)uv__malloc(sizeof(*b)); + if (b == NULL) + return UV_ENOMEM; + #endif diff --git a/src/threadpool.c b/src/threadpool.c -index e804c7c4b6f03c843965001f4c2179d349e156d4..1241ace1cc304c14bf1b79cc2a588c1a50ef4507 100644 +index dbef67f2f10f1df498f228c21eba2a71ceceee29..f572de5aaf1a1b150e58c7b989949441cac279c4 100644 --- a/src/threadpool.c +++ b/src/threadpool.c -@@ -206,7 +206,7 @@ static void init_threads(void) { +@@ -207,7 +207,7 @@ static void init_threads(void) { threads = default_threads; if (nthreads > ARRAY_SIZE(default_threads)) { @@ -187,10 +185,10 @@ index 11ca95591fc38244e931fecd9dd4038d3968af7a..c3dd71a1889bfae08cfdf95acda61e6c if (*addresses == NULL) { freeifaddrs(addrs); diff --git a/src/unix/core.c b/src/unix/core.c -index 54c769f37f2331136c87a37c13fb4e3f9a8f22f9..6353b0e3cc9448aa35dc2ccc9b259277b3fae9a5 100644 +index 25c5181f370e94983e8a5f797f02f7a8dc207e00..28c036f94f3e76717afa651451969f128c5a573c 100644 --- a/src/unix/core.c +++ b/src/unix/core.c -@@ -824,7 +824,7 @@ static unsigned int next_power_of_two(unsigned int val) { +@@ -855,7 +855,7 @@ static unsigned int next_power_of_two(unsigned int val) { } static void maybe_resize(uv_loop_t* loop, unsigned int len) { @@ -199,7 +197,7 @@ index 54c769f37f2331136c87a37c13fb4e3f9a8f22f9..6353b0e3cc9448aa35dc2ccc9b259277 void* fake_watcher_list; void* fake_watcher_count; unsigned int nwatchers; -@@ -843,8 +843,8 @@ static void maybe_resize(uv_loop_t* loop, unsigned int len) { +@@ -874,8 +874,8 @@ static void maybe_resize(uv_loop_t* loop, unsigned int len) { } nwatchers = next_power_of_two(len + 2) - 2; @@ -210,7 +208,16 @@ index 54c769f37f2331136c87a37c13fb4e3f9a8f22f9..6353b0e3cc9448aa35dc2ccc9b259277 if (watchers == NULL) abort(); -@@ -1184,7 +1184,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) { +@@ -884,7 +884,7 @@ static void maybe_resize(uv_loop_t* loop, unsigned int len) { + watchers[nwatchers] = fake_watcher_list; + watchers[nwatchers + 1] = fake_watcher_count; + +- loop->watchers = watchers; ++ loop->watchers = (uv__io_t**)watchers; + loop->nwatchers = nwatchers; + } + +@@ -1216,7 +1216,7 @@ static int uv__getpwuid_r(uv_passwd_t *pwd, uid_t uid) { * is frequently 1024 or 4096, so we can just use that directly. The pwent * will not usually be large. */ for (bufsize = 2000;; bufsize *= 2) { @@ -219,7 +226,7 @@ index 54c769f37f2331136c87a37c13fb4e3f9a8f22f9..6353b0e3cc9448aa35dc2ccc9b259277 if (buf == NULL) return UV_ENOMEM; -@@ -1210,7 +1210,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) { +@@ -1242,7 +1242,7 @@ static int uv__getpwuid_r(uv_passwd_t *pwd, uid_t uid) { name_size = strlen(pw.pw_name) + 1; homedir_size = strlen(pw.pw_dir) + 1; shell_size = strlen(pw.pw_shell) + 1; @@ -228,7 +235,25 @@ index 54c769f37f2331136c87a37c13fb4e3f9a8f22f9..6353b0e3cc9448aa35dc2ccc9b259277 if (pwd->username == NULL) { uv__free(buf); -@@ -1274,7 +1274,7 @@ int uv_os_environ(uv_env_item_t** envitems, int* count) { +@@ -1292,7 +1292,7 @@ int uv_os_get_group(uv_group_t* grp, uv_uid_t gid) { + * is frequently 1024 or 4096, so we can just use that directly. The pwent + * will not usually be large. */ + for (bufsize = 2000;; bufsize *= 2) { +- buf = uv__malloc(bufsize); ++ buf = (char*)uv__malloc(bufsize); + + if (buf == NULL) + return UV_ENOMEM; +@@ -1323,7 +1323,7 @@ int uv_os_get_group(uv_group_t* grp, uv_uid_t gid) { + members++; + } + +- gr_mem = uv__malloc(name_size + mem_size); ++ gr_mem = (char*)uv__malloc(name_size + mem_size); + if (gr_mem == NULL) { + uv__free(buf); + return UV_ENOMEM; +@@ -1380,7 +1380,7 @@ int uv_os_environ(uv_env_item_t** envitems, int* count) { for (i = 0; environ[i] != NULL; i++); @@ -254,10 +279,10 @@ index 5288083ef04fd78d90c34071cc76281adbc310d8..9bd55dd764b845cf8ea441d525b4e136 if (display_name_key == NULL || *display_name_key == NULL) goto out; diff --git a/src/unix/darwin.c b/src/unix/darwin.c -index 62f04d315423d5b642294ff588b57d2babacad89..5fbf734218fa17cc61c03402c8b1dd6b66110ecb 100644 +index 90790d701c4327518d17230c5aa69b9a74112e73..9ee5cd8eb9d02fb8b71986c47fe8a686f0983847 100644 --- a/src/unix/darwin.c +++ b/src/unix/darwin.c -@@ -353,7 +353,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { +@@ -217,7 +217,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { return UV_EINVAL; /* FIXME(bnoordhuis) Translate error. */ } @@ -266,24 +291,11 @@ index 62f04d315423d5b642294ff588b57d2babacad89..5fbf734218fa17cc61c03402c8b1dd6b if (!(*cpu_infos)) { vm_deallocate(mach_task_self(), (vm_address_t)info, msg_type); return UV_ENOMEM; -diff --git a/src/unix/epoll.c b/src/unix/epoll.c -index 97348e254b4556908a2d013300f3f9ee61ff230b..4c057fb3da37706906692750fc2fb42951843157 100644 ---- a/src/unix/epoll.c -+++ b/src/unix/epoll.c -@@ -325,7 +325,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { - assert(fd >= 0); - assert((unsigned) fd < loop->nwatchers); - -- w = loop->watchers[fd]; -+ w = (uv__io_t*)loop->watchers[fd]; - - if (w == NULL) { - /* File descriptor that we've stopped watching, disarm it. diff --git a/src/unix/freebsd.c b/src/unix/freebsd.c -index 658ff262d3738e95b24d8fb8992da905635170f7..6700ff6196245bdce7f14d9edd38607f18812200 100644 +index 191bc8bc213ffddb15c5e04baa66e2a0a8d69a3d..1bd63886b823be6451ac013d94e29885795375b7 100644 --- a/src/unix/freebsd.c +++ b/src/unix/freebsd.c -@@ -215,7 +215,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { +@@ -220,7 +220,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0)) return UV__ERR(errno); @@ -292,7 +304,7 @@ index 658ff262d3738e95b24d8fb8992da905635170f7..6700ff6196245bdce7f14d9edd38607f if (!(*cpu_infos)) return UV_ENOMEM; -@@ -232,7 +232,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { +@@ -237,7 +237,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { size = maxcpus * CPUSTATES * sizeof(long); @@ -302,10 +314,10 @@ index 658ff262d3738e95b24d8fb8992da905635170f7..6700ff6196245bdce7f14d9edd38607f uv__free(*cpu_infos); return UV_ENOMEM; diff --git a/src/unix/fs.c b/src/unix/fs.c -index 933c9c0dc2da40e5bbdc70d73d131f678cafd7fb..1a615244f50dc75e560821f5bfbf5af97e592cc7 100644 +index 6b051c124f2fd9b0f72b41d7d7ba9c715e9686e1..e25d02e54dbe93e4b9c22b0140108c99ae2cb4f7 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c -@@ -137,7 +137,7 @@ extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */ +@@ -140,7 +140,7 @@ extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */ size_t new_path_len; \ path_len = strlen(path) + 1; \ new_path_len = strlen(new_path) + 1; \ @@ -314,7 +326,7 @@ index 933c9c0dc2da40e5bbdc70d73d131f678cafd7fb..1a615244f50dc75e560821f5bfbf5af9 if (req->path == NULL) \ return UV_ENOMEM; \ req->new_path = req->path + path_len; \ -@@ -572,7 +572,7 @@ static ssize_t uv__fs_scandir(uv_fs_t* req) { +@@ -568,7 +568,7 @@ static ssize_t uv__fs_scandir(uv_fs_t* req) { static int uv__fs_opendir(uv_fs_t* req) { uv_dir_t* dir; @@ -323,7 +335,7 @@ index 933c9c0dc2da40e5bbdc70d73d131f678cafd7fb..1a615244f50dc75e560821f5bfbf5af9 if (dir == NULL) goto error; -@@ -596,7 +596,7 @@ static int uv__fs_readdir(uv_fs_t* req) { +@@ -592,7 +592,7 @@ static int uv__fs_readdir(uv_fs_t* req) { unsigned int dirent_idx; unsigned int i; @@ -332,7 +344,7 @@ index 933c9c0dc2da40e5bbdc70d73d131f678cafd7fb..1a615244f50dc75e560821f5bfbf5af9 dirent_idx = 0; while (dirent_idx < dir->nentries) { -@@ -638,7 +638,7 @@ error: +@@ -634,7 +634,7 @@ error: static int uv__fs_closedir(uv_fs_t* req) { uv_dir_t* dir; @@ -341,7 +353,7 @@ index 933c9c0dc2da40e5bbdc70d73d131f678cafd7fb..1a615244f50dc75e560821f5bfbf5af9 if (dir->dir != NULL) { closedir(dir->dir); -@@ -667,7 +667,7 @@ static int uv__fs_statfs(uv_fs_t* req) { +@@ -663,7 +663,7 @@ static int uv__fs_statfs(uv_fs_t* req) { #endif /* defined(__sun) */ return -1; @@ -350,7 +362,7 @@ index 933c9c0dc2da40e5bbdc70d73d131f678cafd7fb..1a615244f50dc75e560821f5bfbf5af9 if (stat_fs == NULL) { errno = ENOMEM; return -1; -@@ -731,7 +731,7 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) { +@@ -727,7 +727,7 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) { maxlen = uv__fs_pathmax_size(req->path); #endif @@ -359,7 +371,7 @@ index 933c9c0dc2da40e5bbdc70d73d131f678cafd7fb..1a615244f50dc75e560821f5bfbf5af9 if (buf == NULL) { errno = ENOMEM; -@@ -751,7 +751,7 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) { +@@ -747,7 +747,7 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) { /* Uncommon case: resize to make room for the trailing nul byte. */ if (len == maxlen) { @@ -368,7 +380,7 @@ index 933c9c0dc2da40e5bbdc70d73d131f678cafd7fb..1a615244f50dc75e560821f5bfbf5af9 if (buf == NULL) return -1; -@@ -774,7 +774,7 @@ static ssize_t uv__fs_realpath(uv_fs_t* req) { +@@ -770,7 +770,7 @@ static ssize_t uv__fs_realpath(uv_fs_t* req) { ssize_t len; len = uv__fs_pathmax_size(req->path); @@ -377,7 +389,7 @@ index 933c9c0dc2da40e5bbdc70d73d131f678cafd7fb..1a615244f50dc75e560821f5bfbf5af9 if (buf == NULL) { errno = ENOMEM; -@@ -2010,7 +2010,7 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, +@@ -1984,7 +1984,7 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, req->nbufs = nbufs; req->bufs = req->bufsml; if (nbufs > ARRAY_SIZE(req->bufsml)) @@ -386,7 +398,7 @@ index 933c9c0dc2da40e5bbdc70d73d131f678cafd7fb..1a615244f50dc75e560821f5bfbf5af9 if (req->bufs == NULL) return UV_ENOMEM; -@@ -2180,7 +2180,7 @@ int uv_fs_write(uv_loop_t* loop, +@@ -2171,7 +2171,7 @@ int uv_fs_write(uv_loop_t* loop, req->nbufs = nbufs; req->bufs = req->bufsml; if (nbufs > ARRAY_SIZE(req->bufsml)) @@ -396,10 +408,10 @@ index 933c9c0dc2da40e5bbdc70d73d131f678cafd7fb..1a615244f50dc75e560821f5bfbf5af9 if (req->bufs == NULL) return UV_ENOMEM; diff --git a/src/unix/fsevents.c b/src/unix/fsevents.c -index bf4f1f6a5180ab4f6ef6776bc3f854c0c9fe67cd..648c8a98b817cb9a8bd03e85bf9b2175bb53eb1a 100644 +index df703f3635fc95bab21debc9697dba06a2a44827..c31d08ba37cfd10672ab6a7a8fd38a1c79b952fe 100644 --- a/src/unix/fsevents.c +++ b/src/unix/fsevents.c -@@ -185,7 +185,7 @@ static void (*pFSEventStreamStop)(FSEventStreamRef); +@@ -183,7 +183,7 @@ static void (*pFSEventStreamStop)(FSEventStreamRef); static void uv__fsevents_cb(uv_async_t* cb) { uv_fs_event_t* handle; @@ -408,9 +420,9 @@ index bf4f1f6a5180ab4f6ef6776bc3f854c0c9fe67cd..648c8a98b817cb9a8bd03e85bf9b2175 UV__FSEVENTS_PROCESS(handle, { handle->cb(handle, event->path[0] ? event->path : NULL, event->events, 0); -@@ -233,10 +233,10 @@ static void uv__fsevents_event_cb(const FSEventStreamRef streamRef, +@@ -231,10 +231,10 @@ static void uv__fsevents_event_cb(const FSEventStreamRef streamRef, FSEventStreamEventFlags flags; - QUEUE head; + struct uv__queue head; - loop = info; - state = loop->cf_state; @@ -422,7 +434,7 @@ index bf4f1f6a5180ab4f6ef6776bc3f854c0c9fe67cd..648c8a98b817cb9a8bd03e85bf9b2175 /* For each handle */ uv_mutex_lock(&state->fsevent_mutex); -@@ -306,7 +306,7 @@ static void uv__fsevents_event_cb(const FSEventStreamRef streamRef, +@@ -304,7 +304,7 @@ static void uv__fsevents_event_cb(const FSEventStreamRef streamRef, continue; } @@ -431,34 +443,7 @@ index bf4f1f6a5180ab4f6ef6776bc3f854c0c9fe67cd..648c8a98b817cb9a8bd03e85bf9b2175 if (event == NULL) break; -@@ -373,7 +373,7 @@ static int uv__fsevents_create_stream(uv_loop_t* loop, CFArrayRef paths) { - flags); - assert(ref != NULL); - -- state = loop->cf_state; -+ state = (uv__cf_loop_state_t*)loop->cf_state; - pFSEventStreamScheduleWithRunLoop(ref, - state->loop, - *pkCFRunLoopDefaultMode); -@@ -392,7 +392,7 @@ static int uv__fsevents_create_stream(uv_loop_t* loop, CFArrayRef paths) { - static void uv__fsevents_destroy_stream(uv_loop_t* loop) { - uv__cf_loop_state_t* state; - -- state = loop->cf_state; -+ state = (uv__cf_loop_state_t*)loop->cf_state; - - if (state->fsevent_stream == NULL) - return; -@@ -419,7 +419,7 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle, - int err; - unsigned int path_count; - -- state = handle->loop->cf_state; -+ state = (uv__cf_loop_state_t*)handle->loop->cf_state; - paths = NULL; - cf_paths = NULL; - err = 0; -@@ -447,7 +447,7 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle, +@@ -438,7 +438,7 @@ static void uv__fsevents_reschedule(uv__cf_loop_state_t* state, uv_mutex_lock(&state->fsevent_mutex); path_count = state->fsevent_handle_count; if (path_count != 0) { @@ -467,7 +452,7 @@ index bf4f1f6a5180ab4f6ef6776bc3f854c0c9fe67cd..648c8a98b817cb9a8bd03e85bf9b2175 if (paths == NULL) { uv_mutex_unlock(&state->fsevent_mutex); goto final; -@@ -605,7 +605,7 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) { +@@ -594,7 +594,7 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) { if (err) return err; @@ -476,7 +461,7 @@ index bf4f1f6a5180ab4f6ef6776bc3f854c0c9fe67cd..648c8a98b817cb9a8bd03e85bf9b2175 if (state == NULL) return UV_ENOMEM; -@@ -707,7 +707,7 @@ void uv__fsevents_loop_delete(uv_loop_t* loop) { +@@ -696,7 +696,7 @@ void uv__fsevents_loop_delete(uv_loop_t* loop) { } /* Destroy state */ @@ -485,7 +470,7 @@ index bf4f1f6a5180ab4f6ef6776bc3f854c0c9fe67cd..648c8a98b817cb9a8bd03e85bf9b2175 uv_sem_destroy(&state->fsevent_sem); uv_mutex_destroy(&state->fsevent_mutex); pCFRelease(state->signal_source); -@@ -721,8 +721,8 @@ static void* uv__cf_loop_runner(void* arg) { +@@ -710,8 +710,8 @@ static void* uv__cf_loop_runner(void* arg) { uv_loop_t* loop; uv__cf_loop_state_t* state; @@ -496,8 +481,8 @@ index bf4f1f6a5180ab4f6ef6776bc3f854c0c9fe67cd..648c8a98b817cb9a8bd03e85bf9b2175 state->loop = pCFRunLoopGetCurrent(); pCFRunLoopAddSource(state->loop, -@@ -750,8 +750,8 @@ static void uv__cf_loop_cb(void* arg) { - QUEUE split_head; +@@ -739,8 +739,8 @@ static void uv__cf_loop_cb(void* arg) { + struct uv__queue split_head; uv__cf_loop_signal_t* s; - loop = arg; @@ -506,8 +491,8 @@ index bf4f1f6a5180ab4f6ef6776bc3f854c0c9fe67cd..648c8a98b817cb9a8bd03e85bf9b2175 + state = (uv__cf_loop_state_t*)loop->cf_state; uv_mutex_lock(&loop->cf_mutex); - QUEUE_MOVE(&loop->cf_signals, &split_head); -@@ -781,7 +781,7 @@ int uv__cf_loop_signal(uv_loop_t* loop, + uv__queue_move(&loop->cf_signals, &split_head); +@@ -770,7 +770,7 @@ int uv__cf_loop_signal(uv_loop_t* loop, uv__cf_loop_signal_t* item; uv__cf_loop_state_t* state; @@ -516,16 +501,16 @@ index bf4f1f6a5180ab4f6ef6776bc3f854c0c9fe67cd..648c8a98b817cb9a8bd03e85bf9b2175 if (item == NULL) return UV_ENOMEM; -@@ -791,7 +791,7 @@ int uv__cf_loop_signal(uv_loop_t* loop, +@@ -780,7 +780,7 @@ int uv__cf_loop_signal(uv_loop_t* loop, uv_mutex_lock(&loop->cf_mutex); - QUEUE_INSERT_TAIL(&loop->cf_signals, &item->member); + uv__queue_insert_tail(&loop->cf_signals, &item->member); - state = loop->cf_state; + state = (uv__cf_loop_state_t*)loop->cf_state; assert(state != NULL); pCFRunLoopSourceSignal(state->signal_source); pCFRunLoopWakeUp(state->loop); -@@ -825,7 +825,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) { +@@ -814,7 +814,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) { * Events will occur in other thread. * Initialize callback for getting them back into event loop's thread */ @@ -534,23 +519,23 @@ index bf4f1f6a5180ab4f6ef6776bc3f854c0c9fe67cd..648c8a98b817cb9a8bd03e85bf9b2175 if (handle->cf_cb == NULL) { err = UV_ENOMEM; goto fail_cf_cb_malloc; -@@ -841,7 +841,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) { +@@ -830,7 +830,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) { goto fail_cf_mutex_init; /* Insert handle into the list */ - state = handle->loop->cf_state; + state = (uv__cf_loop_state_t*)handle->loop->cf_state; uv_mutex_lock(&state->fsevent_mutex); - QUEUE_INSERT_TAIL(&state->fsevent_handles, &handle->cf_member); + uv__queue_insert_tail(&state->fsevent_handles, &handle->cf_member); state->fsevent_handle_count++; -@@ -881,7 +881,7 @@ int uv__fsevents_close(uv_fs_event_t* handle) { +@@ -870,7 +870,7 @@ int uv__fsevents_close(uv_fs_event_t* handle) { return UV_EINVAL; /* Remove handle from the list */ - state = handle->loop->cf_state; + state = (uv__cf_loop_state_t*)handle->loop->cf_state; uv_mutex_lock(&state->fsevent_mutex); - QUEUE_REMOVE(&handle->cf_member); + uv__queue_remove(&handle->cf_member); state->fsevent_handle_count--; diff --git a/src/unix/getaddrinfo.c b/src/unix/getaddrinfo.c index 77337ace9454e032a392c97cb9aa311f15518956..41dc3909969a643e129847ae3a3252d51feadb27 100644 @@ -587,10 +572,10 @@ index 77337ace9454e032a392c97cb9aa311f15518956..41dc3909969a643e129847ae3a3252d5 if (cb) { uv__work_submit(loop, diff --git a/src/unix/ibmi.c b/src/unix/ibmi.c -index 8c6ae636329e5b2e17742fc46b5094237381712a..56af31e979f34b0182aa82dbb3a04d1c5dd747cc 100644 +index 837bba6e2fef7b834a8d104d263bef47eaed0950..5e0fa98d104428534e5264a1c6358e3f68c58b82 100644 --- a/src/unix/ibmi.c +++ b/src/unix/ibmi.c -@@ -288,7 +288,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { +@@ -293,7 +293,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { numcpus = sysconf(_SC_NPROCESSORS_ONLN); @@ -600,10 +585,10 @@ index 8c6ae636329e5b2e17742fc46b5094237381712a..56af31e979f34b0182aa82dbb3a04d1c return UV_ENOMEM; } diff --git a/src/unix/kqueue.c b/src/unix/kqueue.c -index 5dac76ae753c6caf47e2795a715cae74e6e5930c..86eb529bcdaf69591850232084c1b3b2f526f838 100644 +index b78242d3be4e3cf6b7b998f56dc65213982d4bc7..28e55aae6c613576ede7024a5c73d746e134d865 100644 --- a/src/unix/kqueue.c +++ b/src/unix/kqueue.c -@@ -281,8 +281,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { +@@ -299,8 +299,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { nevents = 0; assert(loop->watchers != NULL); @@ -614,7 +599,7 @@ index 5dac76ae753c6caf47e2795a715cae74e6e5930c..86eb529bcdaf69591850232084c1b3b2 for (i = 0; i < nfds; i++) { ev = events + i; fd = ev->ident; -@@ -304,7 +304,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { +@@ -322,7 +322,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { /* Skip invalidated events, see uv__platform_invalidate_fd */ if (fd == -1) continue; @@ -622,29 +607,166 @@ index 5dac76ae753c6caf47e2795a715cae74e6e5930c..86eb529bcdaf69591850232084c1b3b2 + w = (uv__io_t*)loop->watchers[fd]; if (w == NULL) { - /* File descriptor that we've stopped watching, disarm it. -diff --git a/src/unix/linux-core.c b/src/unix/linux-core.c -index 23a7dafec814f6ecbd94e66d513fafe1cf8b3e80..85f3fc0170288577d2e39030dc728de9a694a752 100644 ---- a/src/unix/linux-core.c -+++ b/src/unix/linux-core.c -@@ -117,7 +117,6 @@ void uv__platform_loop_delete(uv_loop_t* loop) { - } + /* File descriptor that we've stopped watching, disarm it. */ +diff --git a/src/unix/linux.c b/src/unix/linux.c +index 48b9c2c43e104079d3ccb5d830d1d79f891fb1a3..9173850bd158eaf9c41deca38f9ba84762a027a1 100644 +--- a/src/unix/linux.c ++++ b/src/unix/linux.c +@@ -456,8 +456,8 @@ static void uv__iou_init(int epollfd, + char* sqe; + int ringfd; + +- sq = MAP_FAILED; +- sqe = MAP_FAILED; ++ sq = (char*)MAP_FAILED; ++ sqe = (char*)MAP_FAILED; + + if (!uv__use_io_uring()) + return; +@@ -496,14 +496,14 @@ static void uv__iou_init(int epollfd, + maxlen = sqlen < cqlen ? cqlen : sqlen; + sqelen = params.sq_entries * sizeof(struct uv__io_uring_sqe); + +- sq = mmap(0, ++ sq = (char*)mmap(0, + maxlen, + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_POPULATE, + ringfd, + 0); /* IORING_OFF_SQ_RING */ + +- sqe = mmap(0, ++ sqe = (char*)mmap(0, + sqelen, + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_POPULATE, +@@ -643,7 +643,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { + int i; + + lfields = uv__get_internal_fields(loop); +- inv = lfields->inv; ++ inv = (uv__invalidate*)lfields->inv; + + /* Invalidate events with same file descriptor */ + if (inv != NULL) +@@ -718,7 +718,7 @@ static struct uv__io_uring_sqe* uv__iou_get_sqe(struct uv__iou* iou, + return NULL; /* No room in ring buffer. TODO(bnoordhuis) maybe flush it? */ + + slot = tail & mask; +- sqe = iou->sqe; ++ sqe = (uv__io_uring_sqe*)iou->sqe; + sqe = &sqe[slot]; + memset(sqe, 0, sizeof(*sqe)); + sqe->user_data = (uintptr_t) req; +@@ -986,7 +986,7 @@ int uv__iou_fs_statx(uv_loop_t* loop, + struct uv__statx* statxbuf; + struct uv__iou* iou; + +- statxbuf = uv__malloc(sizeof(*statxbuf)); ++ statxbuf = (struct uv__statx*)uv__malloc(sizeof(*statxbuf)); + if (statxbuf == NULL) + return 0; +@@ -1050,7 +1050,7 @@ static void uv__iou_fs_statx_post(uv_fs_t* req) { + uv_stat_t* buf; -- - uint64_t uv__hrtime(uv_clocktype_t type) { - static clock_t fast_clock_id = -1; - struct timespec t; -@@ -283,7 +282,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { - goto out; + buf = &req->statbuf; +- statxbuf = req->ptr; ++ statxbuf = (struct uv__statx*)req->ptr; + req->ptr = NULL; - err = UV_ENOMEM; -- ci = uv__calloc(numcpus, sizeof(*ci)); -+ ci = (uv_cpu_info_t*)uv__calloc(numcpus, sizeof(*ci)); - if (ci == NULL) - goto out; + if (req->result == 0) { +@@ -1079,7 +1079,7 @@ static void uv__poll_io_uring(uv_loop_t* loop, struct uv__iou* iou) { + tail = atomic_load_explicit((_Atomic uint32_t*) iou->cqtail, + memory_order_acquire); + mask = iou->cqmask; +- cqe = iou->cqe; ++ cqe = (uv__io_uring_cqe*)iou->cqe; + nevents = 0; + + for (i = head; i != tail; i++) { +@@ -1170,7 +1170,7 @@ static void uv__epoll_ctl_prep(int epollfd, + pe = &(*events)[slot]; + *pe = *e; + +- sqe = ctl->sqe; ++ sqe = (uv__io_uring_sqe*)ctl->sqe; + sqe = &sqe[slot]; + + memset(sqe, 0, sizeof(*sqe)); +@@ -1226,7 +1226,7 @@ static void uv__epoll_ctl_flush(int epollfd, + while (*ctl->cqhead != *ctl->cqtail) { + slot = (*ctl->cqhead)++ & ctl->cqmask; + +- cqe = ctl->cqe; ++ cqe = (uv__io_uring_cqe*)ctl->cqe; + cqe = &cqe[slot]; + + if (cqe->res == 0) +@@ -1708,7 +1708,7 @@ int uv_cpu_info(uv_cpu_info_t** ci, int* count) { + snprintf(*models, sizeof(*models), "unknown"); + maxcpu = 0; + +- cpus = uv__calloc(ARRAY_SIZE(*cpus), sizeof(**cpus)); ++ cpus = (decltype(cpus))uv__calloc(ARRAY_SIZE(*cpus), sizeof(**cpus)); + if (cpus == NULL) + return UV_ENOMEM; -@@ -663,7 +662,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { +@@ -1764,9 +1764,9 @@ int uv_cpu_info(uv_cpu_info_t** ci, int* count) { + + /* arm64: translate CPU part code to model name. */ + if (*parts) { +- p = memmem(parts, sizeof(parts) - 1, p, n + 1); ++ p = (char*)memmem(parts, sizeof(parts) - 1, p, n + 1); + if (p == NULL) +- p = "unknown"; ++ p = const_cast("unknown"); + else + p += n + 1; + n = (int) strcspn(p, "\n"); +@@ -1815,7 +1815,7 @@ nocpuinfo: + } + + size = n * sizeof(**ci) + sizeof(models); +- *ci = uv__malloc(size); ++ *ci = (uv_cpu_info_t*)uv__malloc(size); + *count = 0; + + if (*ci == NULL) { +@@ -1824,7 +1824,7 @@ nocpuinfo: + } + + *count = n; +- p = memcpy(*ci + n, models, sizeof(models)); ++ p = (char*)memcpy(*ci + n, models, sizeof(models)); + + i = 0; + for (cpu = 0; cpu < maxcpu; cpu++) { +@@ -1833,19 +1833,19 @@ nocpuinfo: + + c = *cpus + cpu; + +- (*ci)[i++] = (uv_cpu_info_t) { ++ (*ci)[i++] = uv_cpu_info_t{ + .model = p + c->model * sizeof(*model), +- .speed = c->freq / 1000, ++ .speed = (int)(c->freq / 1000), + /* Note: sysconf(_SC_CLK_TCK) is fixed at 100 Hz, + * therefore the multiplier is always 1000/100 = 10. + */ +- .cpu_times = (struct uv_cpu_times_s) { ++ .cpu_times = { + .user = 10 * c->user, + .nice = 10 * c->nice, + .sys = 10 * c->sys, + .idle = 10 * c->idle, + .irq = 10 * c->irq, +- }, ++ } + }; + } + +@@ -1902,7 +1902,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { } /* Make sure the memory is initiallized to zero using calloc() */ @@ -653,11 +775,7 @@ index 23a7dafec814f6ecbd94e66d513fafe1cf8b3e80..85f3fc0170288577d2e39030dc728de9 if (!(*addresses)) { freeifaddrs(addrs); return UV_ENOMEM; -diff --git a/src/unix/linux-inotify.c b/src/unix/linux-inotify.c -index c1bd260e16e5e9fd023cd00cd673951347545d00..f5366e9626ff5eb063f89a63415a6df9eec75f53 100644 ---- a/src/unix/linux-inotify.c -+++ b/src/unix/linux-inotify.c -@@ -281,12 +281,12 @@ int uv_fs_event_start(uv_fs_event_t* handle, +@@ -2470,12 +2470,12 @@ int uv_fs_event_start(uv_fs_event_t* handle, goto no_insert; len = strlen(path) + 1; @@ -669,11 +787,11 @@ index c1bd260e16e5e9fd023cd00cd673951347545d00..f5366e9626ff5eb063f89a63415a6df9 w->wd = wd; - w->path = memcpy(w + 1, path, len); + w->path = (char*)memcpy(w + 1, path, len); - QUEUE_INIT(&w->watchers); + uv__queue_init(&w->watchers); w->iterating = 0; - RB_INSERT(watcher_root, CAST(&handle->loop->inotify_watchers), w); + RB_INSERT(watcher_root, uv__inotify_watchers(loop), w); diff --git a/src/unix/loop.c b/src/unix/loop.c -index a88e71c339351f2ebcdd6c3f933fc3b1122910ed..2e819cdda71f0da2aa957148d3e6df18e027e5c8 100644 +index a9468e8e19cbede795032980c47eb83aee1e0c68..3babe4d701949ebc69d74f7dedee33c777d89892 100644 --- a/src/unix/loop.c +++ b/src/unix/loop.c @@ -148,7 +148,7 @@ int uv_loop_fork(uv_loop_t* loop) { @@ -686,10 +804,10 @@ index a88e71c339351f2ebcdd6c3f933fc3b1122910ed..2e819cdda71f0da2aa957148d3e6df18 continue; diff --git a/src/unix/netbsd.c b/src/unix/netbsd.c -index c66333f522c5d43bdb6a2aea4e29d0baa278579f..b6886a1ce5ad2e04c64e0bde4e5709c3dac5a219 100644 +index fa21e98e41aec8b7d8bc46c299c4c20a7a0c3f0c..4c6d5a24fe896d89e3b2f1db1dc2b1dd7d010aec 100644 --- a/src/unix/netbsd.c +++ b/src/unix/netbsd.c -@@ -206,14 +206,14 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { +@@ -211,14 +211,14 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { cpuspeed = 0; size = numcpus * CPUSTATES * sizeof(*cp_times); @@ -707,7 +825,7 @@ index c66333f522c5d43bdb6a2aea4e29d0baa278579f..b6886a1ce5ad2e04c64e0bde4e5709c3 uv__free(cp_times); uv__free(*cpu_infos); diff --git a/src/unix/openbsd.c b/src/unix/openbsd.c -index f32a94df38765fb54e7176efe0d172a5a88bccb4..62740f7349889833689d091e8cdd8010c404c28c 100644 +index 9c863b6c90dad9864cb8341c2b6203c1390a9487..2aa61e2ee3321d91ba84887c7ed6dcfa23d00ccf 100644 --- a/src/unix/openbsd.c +++ b/src/unix/openbsd.c @@ -72,7 +72,7 @@ int uv_exepath(char* buffer, size_t* size) { @@ -719,7 +837,7 @@ index f32a94df38765fb54e7176efe0d172a5a88bccb4..62740f7349889833689d091e8cdd8010 if (argsbuf == NULL) goto out; mib[0] = CTL_KERN; -@@ -197,7 +197,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { +@@ -202,7 +202,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { if (sysctl(which, ARRAY_SIZE(which), &numcpus, &size, NULL, 0)) return UV__ERR(errno); @@ -729,10 +847,10 @@ index f32a94df38765fb54e7176efe0d172a5a88bccb4..62740f7349889833689d091e8cdd8010 return UV_ENOMEM; diff --git a/src/unix/pipe.c b/src/unix/pipe.c -index e8cfa1481c3648928eeebceeebb642d358f2a0a8..c8ba31daf847fc206b392327ebf6cd4a5501b2d5 100644 +index d332f3518303d6ef1dee1d835c392bb60b935bad..a60b1a0e442bb3c482575da117f30e9f119f55d3 100644 --- a/src/unix/pipe.c +++ b/src/unix/pipe.c -@@ -309,7 +309,7 @@ int uv_pipe_pending_count(uv_pipe_t* handle) { +@@ -377,7 +377,7 @@ int uv_pipe_pending_count(uv_pipe_t* handle) { if (handle->queued_fds == NULL) return 1; @@ -741,7 +859,7 @@ index e8cfa1481c3648928eeebceeebb642d358f2a0a8..c8ba31daf847fc206b392327ebf6cd4a return queued_fds->offset + 1; } -@@ -346,7 +346,7 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) { +@@ -414,7 +414,7 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) { if (r != UV_ENOBUFS) return r; @@ -751,7 +869,7 @@ index e8cfa1481c3648928eeebceeebb642d358f2a0a8..c8ba31daf847fc206b392327ebf6cd4a return UV_ENOMEM; diff --git a/src/unix/poll.c b/src/unix/poll.c -index 7a12e2d1488a9d48712439e62c6637b9e1161f69..7364731757599d647bedc8e44d3930a32b743f5d 100644 +index 7a12e2d1488a9d48712439e62c6637b9e1161f69..c21722b2e8eef4d16c523f7319fb57c3167d8dd9 100644 --- a/src/unix/poll.c +++ b/src/unix/poll.c @@ -117,7 +117,7 @@ int uv_poll_stop(uv_poll_t* handle) { @@ -763,8 +881,17 @@ index 7a12e2d1488a9d48712439e62c6637b9e1161f69..7364731757599d647bedc8e44d3930a3 uv__io_t* w; int events; +@@ -125,7 +125,7 @@ int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) { + UV_PRIORITIZED)) == 0); + assert(!uv__is_closing(handle)); + +- watchers = handle->loop->watchers; ++ watchers = (void**)handle->loop->watchers; + w = &handle->io_watcher; + + if (uv__fd_exists(handle->loop, w->fd)) diff --git a/src/unix/posix-poll.c b/src/unix/posix-poll.c -index 0f4bf93874be89f2c4deb71e7eeca0416e3bd9ff..8da038d1da6dd893a141b14a593a9cc84b7fbf2f 100644 +index 2e016c2fbaed2eeccd78080969a86aff821a4251..b71eee3f01a3f30b3b5efef539194139f258009a 100644 --- a/src/unix/posix-poll.c +++ b/src/unix/posix-poll.c @@ -61,7 +61,7 @@ static void uv__pollfds_maybe_resize(uv_loop_t* loop) { @@ -777,10 +904,10 @@ index 0f4bf93874be89f2c4deb71e7eeca0416e3bd9ff..8da038d1da6dd893a141b14a593a9cc8 abort(); diff --git a/src/unix/process.c b/src/unix/process.c -index f84153687f799a201e55e465da998ea0b690da0f..0916aa458d4df07fb3b4e9e83f80b9e43c1f82a0 100644 +index dd58c18d9b9359fca1a924698c39bd6390dafbe0..2d622c956de6d7b6f8a04be3ecd311f39602b241 100644 --- a/src/unix/process.c +++ b/src/unix/process.c -@@ -403,7 +403,7 @@ static int posix_spawn_can_use_setsid; +@@ -423,7 +423,7 @@ static int posix_spawn_can_use_setsid; static void uv__spawn_init_posix_spawn_fncs(void) { /* Try to locate all non-portable functions at runtime */ posix_spawn_fncs.file_actions.addchdir_np = @@ -789,7 +916,7 @@ index f84153687f799a201e55e465da998ea0b690da0f..0916aa458d4df07fb3b4e9e83f80b9e4 } -@@ -967,7 +967,7 @@ int uv_spawn(uv_loop_t* loop, +@@ -988,7 +988,7 @@ int uv_spawn(uv_loop_t* loop, err = UV_ENOMEM; pipes = pipes_storage; if (stdio_count > (int) ARRAY_SIZE(pipes_storage)) @@ -825,10 +952,10 @@ index 66ba8d74ec22b72d318b91d82365f5b9693feb3c..9ef18df01a51aa6a26ae6d1d9660a819 while (p < pe) { diff --git a/src/unix/stream.c b/src/unix/stream.c -index b1f6359e0de2c520ed71bd689956de971006bb21..c6cc50e709989f30f4393b509d859663717d1770 100644 +index 28c4d5463c4622725a433b8807e5e7bde580dadd..265ddade7aec129eb9dbf07cde2a16a0e341d1a7 100644 --- a/src/unix/stream.c +++ b/src/unix/stream.c -@@ -113,7 +113,7 @@ static void uv__stream_osx_interrupt_select(uv_stream_t* stream) { +@@ -123,7 +123,7 @@ static void uv__stream_osx_interrupt_select(uv_stream_t* stream) { uv__stream_select_t* s; int r; @@ -837,7 +964,7 @@ index b1f6359e0de2c520ed71bd689956de971006bb21..c6cc50e709989f30f4393b509d859663 if (s == NULL) return; -@@ -142,8 +142,8 @@ static void uv__stream_osx_select(void* arg) { +@@ -152,8 +152,8 @@ static void uv__stream_osx_select(void* arg) { int r; int max_fd; @@ -848,7 +975,7 @@ index b1f6359e0de2c520ed71bd689956de971006bb21..c6cc50e709989f30f4393b509d859663 fd = s->fd; if (fd > s->int_fd) -@@ -320,7 +320,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) { +@@ -330,7 +330,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) { sread_sz = ROUND_UP(max_fd + 1, sizeof(uint32_t) * NBBY) / NBBY; swrite_sz = sread_sz; @@ -857,7 +984,7 @@ index b1f6359e0de2c520ed71bd689956de971006bb21..c6cc50e709989f30f4393b509d859663 if (s == NULL) { err = UV_ENOMEM; goto failed_malloc; -@@ -605,7 +605,7 @@ done: +@@ -573,7 +573,7 @@ done: if (server->queued_fds != NULL) { uv__stream_queued_fds_t* queued_fds; @@ -866,16 +993,7 @@ index b1f6359e0de2c520ed71bd689956de971006bb21..c6cc50e709989f30f4393b509d859663 /* Read first */ server->accepted_fd = queued_fds->fds[0]; -@@ -844,7 +844,7 @@ static int uv__try_write(uv_stream_t* stream, - /* silence aliasing warning */ - { - void* pv = CMSG_DATA(cmsg); -- int* pi = pv; -+ int* pi = (int*)pv; - *pi = fd_to_send; - } - -@@ -975,11 +975,12 @@ static int uv__stream_queue_fd(uv_stream_t* stream, int fd) { +@@ -942,11 +942,12 @@ static int uv__stream_queue_fd(uv_stream_t* stream, int fd) { uv__stream_queued_fds_t* queued_fds; unsigned int queue_size; @@ -891,7 +1009,7 @@ index b1f6359e0de2c520ed71bd689956de971006bb21..c6cc50e709989f30f4393b509d859663 if (queued_fds == NULL) return UV_ENOMEM; queued_fds->size = queue_size; -@@ -989,9 +990,9 @@ static int uv__stream_queue_fd(uv_stream_t* stream, int fd) { +@@ -956,9 +957,9 @@ static int uv__stream_queue_fd(uv_stream_t* stream, int fd) { /* Grow */ } else if (queued_fds->size == queued_fds->offset) { queue_size = queued_fds->size + 8; @@ -904,16 +1022,7 @@ index b1f6359e0de2c520ed71bd689956de971006bb21..c6cc50e709989f30f4393b509d859663 /* * Allocation failure, report back. -@@ -1039,7 +1040,7 @@ static int uv__stream_recv_cmsg(uv_stream_t* stream, struct msghdr* msg) { - - /* silence aliasing warning */ - pv = CMSG_DATA(cmsg); -- pi = pv; -+ pi = (int*)pv; - - /* Count available fds */ - start = (char*) cmsg; -@@ -1423,7 +1424,7 @@ int uv_write2(uv_write_t* req, +@@ -1356,7 +1357,7 @@ int uv_write2(uv_write_t* req, req->bufs = req->bufsml; if (nbufs > ARRAY_SIZE(req->bufsml)) @@ -922,7 +1031,7 @@ index b1f6359e0de2c520ed71bd689956de971006bb21..c6cc50e709989f30f4393b509d859663 if (req->bufs == NULL) return UV_ENOMEM; -@@ -1557,7 +1558,7 @@ int uv___stream_fd(const uv_stream_t* handle) { +@@ -1490,7 +1491,7 @@ int uv___stream_fd(const uv_stream_t* handle) { handle->type == UV_TTY || handle->type == UV_NAMED_PIPE); @@ -931,7 +1040,7 @@ index b1f6359e0de2c520ed71bd689956de971006bb21..c6cc50e709989f30f4393b509d859663 if (s != NULL) return s->fd; -@@ -1575,7 +1576,7 @@ void uv__stream_close(uv_stream_t* handle) { +@@ -1508,7 +1509,7 @@ void uv__stream_close(uv_stream_t* handle) { if (handle->select != NULL) { uv__stream_select_t* s; @@ -940,7 +1049,7 @@ index b1f6359e0de2c520ed71bd689956de971006bb21..c6cc50e709989f30f4393b509d859663 uv_sem_post(&s->close_sem); uv_sem_post(&s->async_sem); -@@ -1610,7 +1611,7 @@ void uv__stream_close(uv_stream_t* handle) { +@@ -1543,7 +1544,7 @@ void uv__stream_close(uv_stream_t* handle) { /* Close all queued fds */ if (handle->queued_fds != NULL) { @@ -950,19 +1059,10 @@ index b1f6359e0de2c520ed71bd689956de971006bb21..c6cc50e709989f30f4393b509d859663 uv__close(queued_fds->fds[i]); uv__free(handle->queued_fds); diff --git a/src/unix/thread.c b/src/unix/thread.c -index d89e5cd13ba0ad73913b74f5e5fe4b5f139eb650..759cd0c28518928127837ba82cbf8e761c6223d3 100644 +index 4d6f4b8232ec6dc0bd27258a1315340e3e272ae9..531c6211bb4321e5f11031a0644b4e3ab9174396 100644 --- a/src/unix/thread.c +++ b/src/unix/thread.c -@@ -59,7 +59,7 @@ int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { - if (barrier == NULL || count == 0) - return UV_EINVAL; - -- b = uv__malloc(sizeof(*b)); -+ b = (_uv_barrier*)uv__malloc(sizeof(*b)); - if (b == NULL) - return UV_ENOMEM; - -@@ -275,8 +275,7 @@ int uv_thread_create_ex(uv_thread_t* tid, +@@ -168,8 +168,7 @@ int uv_thread_create_ex(uv_thread_t* tid, abort(); } @@ -972,7 +1072,7 @@ index d89e5cd13ba0ad73913b74f5e5fe4b5f139eb650..759cd0c28518928127837ba82cbf8e76 if (attr != NULL) pthread_attr_destroy(attr); -@@ -547,7 +546,7 @@ static int uv__custom_sem_init(uv_sem_t* sem_, unsigned int value) { +@@ -540,7 +539,7 @@ static int uv__custom_sem_init(uv_sem_t* sem_, unsigned int value) { int err; uv_semaphore_t* sem; @@ -982,10 +1082,10 @@ index d89e5cd13ba0ad73913b74f5e5fe4b5f139eb650..759cd0c28518928127837ba82cbf8e76 return UV_ENOMEM; diff --git a/src/unix/udp.c b/src/unix/udp.c -index 4d985b88ba9304d57aea42d9c1b4a9a9e924ddc5..a130aeaa59581176147d5f060156b57ef5ad658a 100644 +index c2814512a5f507ceb9e764cdb7c6ff3d36e77974..cbee16b22a36b1c82e74f6a81c3811052e9b8482 100644 --- a/src/unix/udp.c +++ b/src/unix/udp.c -@@ -227,11 +227,11 @@ static int uv__udp_recvmmsg(uv_udp_t* handle, uv_buf_t* buf) { +@@ -191,11 +191,11 @@ static int uv__udp_recvmmsg(uv_udp_t* handle, uv_buf_t* buf) { if (msgs[k].msg_hdr.msg_flags & MSG_TRUNC) flags |= UV_UDP_PARTIAL; @@ -999,7 +1099,7 @@ index 4d985b88ba9304d57aea42d9c1b4a9a9e924ddc5..a130aeaa59581176147d5f060156b57e flags); } -@@ -281,7 +281,7 @@ static void uv__udp_recvmsg(uv_udp_t* handle) { +@@ -245,7 +245,7 @@ static void uv__udp_recvmsg(uv_udp_t* handle) { memset(&peer, 0, sizeof(peer)); h.msg_name = &peer; h.msg_namelen = sizeof(peer); @@ -1008,7 +1108,7 @@ index 4d985b88ba9304d57aea42d9c1b4a9a9e924ddc5..a130aeaa59581176147d5f060156b57e h.msg_iovlen = 1; do { -@@ -765,7 +765,7 @@ int uv__udp_send(uv_udp_send_t* req, +@@ -719,7 +719,7 @@ int uv__udp_send(uv_udp_send_t* req, req->bufs = req->bufsml; if (nbufs > ARRAY_SIZE(req->bufsml)) @@ -1018,7 +1118,7 @@ index 4d985b88ba9304d57aea42d9c1b4a9a9e924ddc5..a130aeaa59581176147d5f060156b57e if (req->bufs == NULL) { uv__req_unregister(handle->loop, req); diff --git a/src/uv-common.c b/src/uv-common.c -index efc9eb50ee3b9ee204f9f16827dc800200f3d094..dfb606e3e842ccb3b2d9327e2b3048c4cfdd0314 100644 +index 916f3f4e00664ab47f94d2a6ee7c6a9ef0461389..c04f93596ab1f730576256d86e216ccb7f258b72 100644 --- a/src/uv-common.c +++ b/src/uv-common.c @@ -54,10 +54,10 @@ static uv__allocator_t uv__allocator = { @@ -1048,16 +1148,16 @@ index efc9eb50ee3b9ee204f9f16827dc800200f3d094..dfb606e3e842ccb3b2d9327e2b3048c4 } void* uv__malloc(size_t size) { -@@ -653,7 +653,7 @@ void uv__fs_scandir_cleanup(uv_fs_t* req) { +@@ -688,7 +688,7 @@ void uv__fs_scandir_cleanup(uv_fs_t* req) { + unsigned int n; - unsigned int* nbufs = uv__get_nbufs(req); + if (req->result >= 0) { +- dents = req->ptr; ++ dents = (uv__dirent_t**)(req->ptr); + nbufs = uv__get_nbufs(req); -- dents = req->ptr; -+ dents = (uv__dirent_t**)(req->ptr); - if (*nbufs > 0 && *nbufs != (unsigned int) req->result) - (*nbufs)--; - for (; *nbufs < (unsigned int) req->result; (*nbufs)++) -@@ -680,7 +680,7 @@ int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) { + i = 0; +@@ -721,7 +721,7 @@ int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) { nbufs = uv__get_nbufs(req); assert(nbufs); @@ -1066,7 +1166,7 @@ index efc9eb50ee3b9ee204f9f16827dc800200f3d094..dfb606e3e842ccb3b2d9327e2b3048c4 /* Free previous entity */ if (*nbufs > 0) -@@ -745,7 +745,7 @@ void uv__fs_readdir_cleanup(uv_fs_t* req) { +@@ -786,7 +786,7 @@ void uv__fs_readdir_cleanup(uv_fs_t* req) { if (req->ptr == NULL) return; @@ -1075,7 +1175,7 @@ index efc9eb50ee3b9ee204f9f16827dc800200f3d094..dfb606e3e842ccb3b2d9327e2b3048c4 dirents = dir->dirents; req->ptr = NULL; -@@ -791,7 +791,7 @@ uv_loop_t* uv_default_loop(void) { +@@ -832,7 +832,7 @@ uv_loop_t* uv_default_loop(void) { uv_loop_t* uv_loop_new(void) { uv_loop_t* loop; @@ -1085,7 +1185,7 @@ index efc9eb50ee3b9ee204f9f16827dc800200f3d094..dfb606e3e842ccb3b2d9327e2b3048c4 return NULL; diff --git a/src/win/core.c b/src/win/core.c -index 67af93e6571ed4324d80b6dfb2ff93db7b9cd9b1..0752edff3ebdf61e056157ef21109538f6e4b358 100644 +index e9885a0f1ff3890a8d957c8793e22b01cedc0e97..87ade7ad65243ee3ff940320f84e1960390300e1 100644 --- a/src/win/core.c +++ b/src/win/core.c @@ -98,7 +98,8 @@ static int uv__loops_add(uv_loop_t* loop) { @@ -1108,7 +1208,7 @@ index 67af93e6571ed4324d80b6dfb2ff93db7b9cd9b1..0752edff3ebdf61e056157ef21109538 if (!new_loops) goto loop_removed; uv__loops = new_loops; -@@ -261,7 +263,7 @@ int uv_loop_init(uv_loop_t* loop) { +@@ -264,7 +266,7 @@ int uv_loop_init(uv_loop_t* loop) { loop->endgame_handles = NULL; @@ -1153,19 +1253,28 @@ index 0b532af12d4371c2311bd50a66913287a0716f43..703a8d8f87de1089ac8b18bd817d416d uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); } diff --git a/src/win/fs.c b/src/win/fs.c -index 792307995f60c8ac34b44c6c255102cd227354b7..8374012f0e9ee094eed5db19e5f7d12286052d70 100644 +index fc209c54f470edaa031009979061cff071cbf66d..328c8f2e0513562b53c948ffea59d0841e14b264 100644 --- a/src/win/fs.c +++ b/src/win/fs.c -@@ -285,7 +285,7 @@ static int fs__wide_to_utf8(WCHAR* w_source_ptr, +@@ -258,7 +258,7 @@ INLINE static int fs__capture_path(uv_fs_t* req, const char* path, return 0; } -- target = uv__malloc(target_len + 1); -+ target = (char*)uv__malloc(target_len + 1); - if (target == NULL) { - SetLastError(ERROR_OUTOFMEMORY); - return -1; -@@ -1464,7 +1464,7 @@ void fs__scandir(uv_fs_t* req) { +- buf = uv__malloc(buf_sz); ++ buf = (WCHAR *)uv__malloc(buf_sz); + if (buf == NULL) { + return ERROR_OUTOFMEMORY; + } +@@ -376,7 +376,7 @@ static int fs__wide_to_wtf8(WCHAR* w_source_ptr, + return 0; + + if (*target_ptr == NULL) { +- target = uv__malloc(target_len + 1); ++ target = (char *)uv__malloc(target_len + 1); + if (target == NULL) { + SetLastError(ERROR_OUTOFMEMORY); + return -1; +@@ -1575,7 +1575,7 @@ void fs__scandir(uv_fs_t* req) { if (dirents_used >= dirents_size) { size_t new_dirents_size = dirents_size == 0 ? dirents_initial_size : dirents_size << 1; @@ -1174,16 +1283,16 @@ index 792307995f60c8ac34b44c6c255102cd227354b7..8374012f0e9ee094eed5db19e5f7d122 uv__realloc(dirents, new_dirents_size * sizeof *dirents); if (new_dirents == NULL) -@@ -1478,7 +1478,7 @@ void fs__scandir(uv_fs_t* req) { +@@ -1589,7 +1589,7 @@ void fs__scandir(uv_fs_t* req) { * includes room for the first character of the filename, but `utf8_len` * doesn't count the NULL terminator at this point. */ -- dirent = uv__malloc(sizeof *dirent + utf8_len); -+ dirent = (uv__dirent_t*)uv__malloc(sizeof *dirent + utf8_len); +- dirent = uv__malloc(sizeof *dirent + wtf8_len); ++ dirent = (uv__dirent_t*)uv__malloc(sizeof *dirent + wtf8_len); if (dirent == NULL) goto out_of_memory_error; -@@ -1589,7 +1589,7 @@ void fs__opendir(uv_fs_t* req) { +@@ -1691,7 +1691,7 @@ void fs__opendir(uv_fs_t* req) { goto error; } @@ -1192,7 +1301,7 @@ index 792307995f60c8ac34b44c6c255102cd227354b7..8374012f0e9ee094eed5db19e5f7d122 if (dir == NULL) { SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); goto error; -@@ -1604,7 +1604,7 @@ void fs__opendir(uv_fs_t* req) { +@@ -1706,7 +1706,7 @@ void fs__opendir(uv_fs_t* req) { else fmt = L"%s\\*"; @@ -1201,7 +1310,7 @@ index 792307995f60c8ac34b44c6c255102cd227354b7..8374012f0e9ee094eed5db19e5f7d122 if (find_path == NULL) { SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); goto error; -@@ -1641,7 +1641,7 @@ void fs__readdir(uv_fs_t* req) { +@@ -1743,7 +1743,7 @@ void fs__readdir(uv_fs_t* req) { int r; req->flags |= UV_FS_FREE_PTR; @@ -1210,7 +1319,7 @@ index 792307995f60c8ac34b44c6c255102cd227354b7..8374012f0e9ee094eed5db19e5f7d122 dirents = dir->dirents; memset(dirents, 0, dir->nentries * sizeof(*dir->dirents)); find_data = &dir->find_data; -@@ -1698,7 +1698,7 @@ error: +@@ -1800,7 +1800,7 @@ error: void fs__closedir(uv_fs_t* req) { uv_dir_t* dir; @@ -1219,7 +1328,7 @@ index 792307995f60c8ac34b44c6c255102cd227354b7..8374012f0e9ee094eed5db19e5f7d122 FindClose(dir->dir_handle); uv__free(req->ptr); SET_REQ_RESULT(req, 0); -@@ -2627,7 +2627,7 @@ static ssize_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) { +@@ -2791,7 +2791,7 @@ static ssize_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) { return -1; } @@ -1228,7 +1337,7 @@ index 792307995f60c8ac34b44c6c255102cd227354b7..8374012f0e9ee094eed5db19e5f7d122 if (w_realpath_buf == NULL) { SetLastError(ERROR_OUTOFMEMORY); return -1; -@@ -2738,7 +2738,7 @@ retry_get_disk_free_space: +@@ -2904,7 +2904,7 @@ retry_get_disk_free_space: } len = MAX_PATH + 1; @@ -1237,7 +1346,7 @@ index 792307995f60c8ac34b44c6c255102cd227354b7..8374012f0e9ee094eed5db19e5f7d122 if (pathw == NULL) { SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); return; -@@ -2754,7 +2754,7 @@ retry_get_full_path_name: +@@ -2920,7 +2920,7 @@ retry_get_full_path_name: return; } else if (ret > len) { len = ret; @@ -1246,7 +1355,7 @@ index 792307995f60c8ac34b44c6c255102cd227354b7..8374012f0e9ee094eed5db19e5f7d122 if (pathw == NULL) { SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); return; -@@ -2770,7 +2770,7 @@ retry_get_full_path_name: +@@ -2936,7 +2936,7 @@ retry_get_full_path_name: uv__free(pathw); } @@ -1255,7 +1364,7 @@ index 792307995f60c8ac34b44c6c255102cd227354b7..8374012f0e9ee094eed5db19e5f7d122 if (stat_fs == NULL) { SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); return; -@@ -2929,7 +2929,7 @@ int uv_fs_read(uv_loop_t* loop, +@@ -3095,7 +3095,7 @@ int uv_fs_read(uv_loop_t* loop, req->fs.info.nbufs = nbufs; req->fs.info.bufs = req->fs.info.bufsml; if (nbufs > ARRAY_SIZE(req->fs.info.bufsml)) @@ -1264,7 +1373,7 @@ index 792307995f60c8ac34b44c6c255102cd227354b7..8374012f0e9ee094eed5db19e5f7d122 if (req->fs.info.bufs == NULL) { SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); -@@ -2962,7 +2962,7 @@ int uv_fs_write(uv_loop_t* loop, +@@ -3128,7 +3128,7 @@ int uv_fs_write(uv_loop_t* loop, req->fs.info.nbufs = nbufs; req->fs.info.bufs = req->fs.info.bufsml; if (nbufs > ARRAY_SIZE(req->fs.info.bufsml)) @@ -1274,10 +1383,10 @@ index 792307995f60c8ac34b44c6c255102cd227354b7..8374012f0e9ee094eed5db19e5f7d122 if (req->fs.info.bufs == NULL) { SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); diff --git a/src/win/pipe.c b/src/win/pipe.c -index 998461811fb87fafa8ffd43bb9c9f5d88f00c6f9..cd77061a079094b11350a01ddd364e15fa3078bc 100644 +index f0cac3822564e14052feb5e1934f54c57c78160d..c1739efe82b8755999145860b4da6b50c73518a2 100644 --- a/src/win/pipe.c +++ b/src/win/pipe.c -@@ -728,7 +728,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { +@@ -756,7 +756,7 @@ int uv_pipe_bind2(uv_pipe_t* handle, /* Convert name to UTF16. */ nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR); @@ -1286,7 +1395,7 @@ index 998461811fb87fafa8ffd43bb9c9f5d88f00c6f9..cd77061a079094b11350a01ddd364e15 if (!handle->name) { uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); } -@@ -841,7 +841,7 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, +@@ -906,7 +906,7 @@ int uv_pipe_connect2(uv_connect_t* req, /* Convert name to UTF16. */ nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR); @@ -1295,7 +1404,16 @@ index 998461811fb87fafa8ffd43bb9c9f5d88f00c6f9..cd77061a079094b11350a01ddd364e15 if (!handle->name) { uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); } -@@ -1453,7 +1453,7 @@ static int uv__build_coalesced_write_req(uv_write_t* user_req, +@@ -924,7 +924,7 @@ int uv_pipe_connect2(uv_connect_t* req, + pipeHandle = open_named_pipe(handle->name, &duplex_flags); + if (pipeHandle == INVALID_HANDLE_VALUE) { + if (GetLastError() == ERROR_PIPE_BUSY) { +- req->u.connect.name = uv__malloc(nameSize); ++ req->u.connect.name = (WCHAR *)uv__malloc(nameSize); + if (!req->u.connect.name) { + uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); + } +@@ -1528,7 +1528,7 @@ static int uv__build_coalesced_write_req(uv_write_t* user_req, data_length; /* (c) */ /* Allocate buffer. */ @@ -1304,7 +1422,7 @@ index 998461811fb87fafa8ffd43bb9c9f5d88f00c6f9..cd77061a079094b11350a01ddd364e15 if (heap_buffer == NULL) return ERROR_NOT_ENOUGH_MEMORY; /* Maps to UV_ENOMEM. */ -@@ -1698,7 +1698,7 @@ int uv__pipe_write_ipc(uv_loop_t* loop, +@@ -1777,7 +1777,7 @@ int uv__pipe_write_ipc(uv_loop_t* loop, bufs = stack_bufs; } else { /* Use heap-allocated buffer array. */ @@ -1313,7 +1431,7 @@ index 998461811fb87fafa8ffd43bb9c9f5d88f00c6f9..cd77061a079094b11350a01ddd364e15 if (bufs == NULL) return ERROR_NOT_ENOUGH_MEMORY; /* Maps to UV_ENOMEM. */ } -@@ -2430,7 +2430,7 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) +@@ -2514,7 +2514,7 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) FileNameInformation); if (nt_status == STATUS_BUFFER_OVERFLOW) { name_size = sizeof(*name_info) + tmp_name_info.FileNameLength; @@ -1323,10 +1441,10 @@ index 998461811fb87fafa8ffd43bb9c9f5d88f00c6f9..cd77061a079094b11350a01ddd364e15 *size = 0; err = UV_ENOMEM; diff --git a/src/win/process.c b/src/win/process.c -index 24c633393fd15dcf87726b174d6b027a969e0f0d..e857db3e98eb24f8de12e6b6d90ae3905cc49ce7 100644 +index 3e451e2291d6ed200ec258e874becbbea22bbc27..44072b05e5858884e7f648a145cd15a2b574116d 100644 --- a/src/win/process.c +++ b/src/win/process.c -@@ -616,8 +616,8 @@ error: +@@ -618,8 +618,8 @@ error: int env_strncmp(const wchar_t* a, int na, const wchar_t* b) { @@ -1337,7 +1455,7 @@ index 24c633393fd15dcf87726b174d6b027a969e0f0d..e857db3e98eb24f8de12e6b6d90ae390 wchar_t* A; wchar_t* B; int nb; -@@ -634,8 +634,8 @@ int env_strncmp(const wchar_t* a, int na, const wchar_t* b) { +@@ -636,8 +636,8 @@ int env_strncmp(const wchar_t* a, int na, const wchar_t* b) { assert(b_eq); nb = b_eq - b; @@ -1348,7 +1466,7 @@ index 24c633393fd15dcf87726b174d6b027a969e0f0d..e857db3e98eb24f8de12e6b6d90ae390 r = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, a, na, A, na); assert(r==na); -@@ -718,7 +718,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) { +@@ -720,7 +720,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) { if (dst_copy == NULL && env_len > 0) { return ERROR_OUTOFMEMORY; } @@ -1357,7 +1475,7 @@ index 24c633393fd15dcf87726b174d6b027a969e0f0d..e857db3e98eb24f8de12e6b6d90ae390 ptr = dst_copy; ptr_copy = env_copy; -@@ -772,7 +772,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) { +@@ -774,7 +774,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) { } /* final pass: copy, in sort order, and inserting required variables */ @@ -1366,11 +1484,29 @@ index 24c633393fd15dcf87726b174d6b027a969e0f0d..e857db3e98eb24f8de12e6b6d90ae390 if (!dst) { uv__free(dst_copy); return ERROR_OUTOFMEMORY; +@@ -1236,7 +1236,7 @@ static int uv__kill(HANDLE process_handle, int signum) { + if (ret != ERROR_SUCCESS) { + /* Default value for `dump_folder` is `%LOCALAPPDATA%\CrashDumps`. */ + WCHAR* localappdata; +- SHGetKnownFolderPath(&FOLDERID_LocalAppData, 0, NULL, &localappdata); ++ SHGetKnownFolderPath(*((const KNOWNFOLDERID*)&FOLDERID_LocalAppData), 0, NULL, &localappdata); + _snwprintf_s(dump_folder, + sizeof(dump_folder), + _TRUNCATE, +@@ -1292,7 +1292,7 @@ static int uv__kill(HANDLE process_handle, int signum) { + if (MiniDumpWriteDump(process_handle, + pid, + hDumpFile, +- dump_options, ++ (MINIDUMP_TYPE)dump_options, + NULL, + NULL, + NULL)) { diff --git a/src/win/tcp.c b/src/win/tcp.c -index b6aa4c512050e012bdfa1395f0011a5371b11768..4cccee429223cbd6f7b876341982816e4998dc10 100644 +index 187f36e2a61c870b0d16e17e9d4a9e1161ba8851..d8da4d941a51b0625fc0c072342ec4edf74c0ea3 100644 --- a/src/win/tcp.c +++ b/src/win/tcp.c -@@ -612,7 +612,7 @@ int uv__tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { +@@ -585,7 +585,7 @@ int uv__tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { if (handle->tcp.serv.accept_reqs == NULL) { handle->tcp.serv.accept_reqs = @@ -1380,7 +1516,7 @@ index b6aa4c512050e012bdfa1395f0011a5371b11768..4cccee429223cbd6f7b876341982816e uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); } diff --git a/src/win/thread.c b/src/win/thread.c -index d3b1c96b6199a7ff034d8646b76a6a21712702d8..9ad60c9164c8ff26223309a9aa388fa5e4621914 100644 +index 57c25e8f5a861c9d8a4c402c260d3ac235200423..57f1698f595e2410a51044f7f228b5a235206819 100644 --- a/src/win/thread.c +++ b/src/win/thread.c @@ -98,7 +98,7 @@ static UINT __stdcall uv__thread_start(void* arg) { @@ -1402,19 +1538,19 @@ index d3b1c96b6199a7ff034d8646b76a6a21712702d8..9ad60c9164c8ff26223309a9aa388fa5 return UV_ENOMEM; diff --git a/src/win/util.c b/src/win/util.c -index 99432053cc3b242e514268b7aba2e2d83a9e64f2..c655f532dbcc6c63516027caf1453ca4ef817cff 100644 +index f6ec79cd57b5010ed5fd6829d952bcdacc8b7671..1cfd7b2caf0d4ad1a6a66df9406c21f4e2b69b04 100644 --- a/src/win/util.c +++ b/src/win/util.c -@@ -164,7 +164,7 @@ int uv_cwd(char* buffer, size_t* size) { - if (utf16_len == 0) { - return uv_translate_sys_error(GetLastError()); - } -- utf16_buffer = uv__malloc(utf16_len * sizeof(WCHAR)); -+ utf16_buffer = (WCHAR*)uv__malloc(utf16_len * sizeof(WCHAR)); - if (utf16_buffer == NULL) { - return UV_ENOMEM; - } -@@ -242,7 +242,7 @@ int uv_chdir(const char* dir) { +@@ -160,7 +160,7 @@ static int uv__cwd(WCHAR** buf, DWORD *len) { + return uv_translate_sys_error(GetLastError()); + + /* |t| is the size of the buffer _including_ nul. */ +- p = uv__malloc(t * sizeof(*p)); ++ p = (WCHAR *)uv__malloc(t * sizeof(*p)); + if (p == NULL) + return UV_ENOMEM; + +@@ -265,7 +265,7 @@ int uv_chdir(const char* dir) { if (utf16_len == 0) { return uv_translate_sys_error(GetLastError()); } @@ -1423,16 +1559,7 @@ index 99432053cc3b242e514268b7aba2e2d83a9e64f2..c655f532dbcc6c63516027caf1453ca4 if (utf16_buffer == NULL) { return UV_ENOMEM; } -@@ -268,7 +268,7 @@ int uv_chdir(const char* dir) { - new_utf16_len = GetCurrentDirectoryW(utf16_len, utf16_buffer); - if (new_utf16_len > utf16_len ) { - uv__free(utf16_buffer); -- utf16_buffer = uv__malloc(new_utf16_len * sizeof(WCHAR)); -+ utf16_buffer = (WCHAR*)uv__malloc(new_utf16_len * sizeof(WCHAR)); - if (utf16_buffer == NULL) { - /* When updating the environment variable fails, return UV_OK anyway. - * We did successfully change current working directory, only updating -@@ -573,14 +573,14 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) { +@@ -623,14 +623,14 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) { GetSystemInfo(&system_info); cpu_count = system_info.dwNumberOfProcessors; @@ -1449,7 +1576,7 @@ index 99432053cc3b242e514268b7aba2e2d83a9e64f2..c655f532dbcc6c63516027caf1453ca4 if (sppi == NULL) { err = ERROR_OUTOFMEMORY; goto error; -@@ -802,7 +802,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, +@@ -774,7 +774,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, case ERROR_BUFFER_OVERFLOW: /* This happens when win_address_buf is NULL or too small to hold all * adapters. */ @@ -1459,7 +1586,7 @@ index 99432053cc3b242e514268b7aba2e2d83a9e64f2..c655f532dbcc6c63516027caf1453ca4 if (win_address_buf == NULL) return UV_ENOMEM; -@@ -810,7 +811,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, +@@ -782,7 +783,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, case ERROR_NO_DATA: { /* No adapters were found. */ @@ -1468,7 +1595,7 @@ index 99432053cc3b242e514268b7aba2e2d83a9e64f2..c655f532dbcc6c63516027caf1453ca4 if (uv_address_buf == NULL) return UV_ENOMEM; -@@ -887,7 +888,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, +@@ -859,7 +860,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, } /* Allocate space to store interface data plus adapter names. */ @@ -1477,7 +1604,7 @@ index 99432053cc3b242e514268b7aba2e2d83a9e64f2..c655f532dbcc6c63516027caf1453ca4 if (uv_address_buf == NULL) { uv__free(win_address_buf); return UV_ENOMEM; -@@ -1131,7 +1132,7 @@ int uv_os_tmpdir(char* buffer, size_t* size) { +@@ -1074,7 +1075,7 @@ int uv_os_tmpdir(char* buffer, size_t* size) { } /* Include space for terminating null char. */ len += 1; @@ -1486,7 +1613,7 @@ index 99432053cc3b242e514268b7aba2e2d83a9e64f2..c655f532dbcc6c63516027caf1453ca4 if (path == NULL) { return UV_ENOMEM; } -@@ -1221,7 +1222,7 @@ int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8) { +@@ -1153,7 +1154,7 @@ int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8) { /* Allocate the destination buffer adding an extra byte for the terminating * NULL. If utf16len is not -1 WideCharToMultiByte will not add it, so * we do it ourselves always, just in case. */ @@ -1495,7 +1622,7 @@ index 99432053cc3b242e514268b7aba2e2d83a9e64f2..c655f532dbcc6c63516027caf1453ca4 if (*utf8 == NULL) return UV_ENOMEM; -@@ -1269,7 +1270,7 @@ int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16) { +@@ -1201,7 +1202,7 @@ int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16) { /* Allocate the destination buffer adding an extra byte for the terminating * NULL. If utf8len is not -1 MultiByteToWideChar will not add it, so * we do it ourselves always, just in case. */ @@ -1504,7 +1631,7 @@ index 99432053cc3b242e514268b7aba2e2d83a9e64f2..c655f532dbcc6c63516027caf1453ca4 if (*utf16 == NULL) return UV_ENOMEM; -@@ -1310,7 +1311,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) { +@@ -1242,7 +1243,7 @@ static int uv__getpwuid_r(uv_passwd_t* pwd) { return uv_translate_sys_error(r); } @@ -1513,7 +1640,7 @@ index 99432053cc3b242e514268b7aba2e2d83a9e64f2..c655f532dbcc6c63516027caf1453ca4 if (path == NULL) { CloseHandle(token); return UV_ENOMEM; -@@ -1381,7 +1382,7 @@ int uv_os_environ(uv_env_item_t** envitems, int* count) { +@@ -1323,7 +1324,7 @@ int uv_os_environ(uv_env_item_t** envitems, int* count) { for (penv = env, i = 0; *penv != L'\0'; penv += wcslen(penv) + 1, i++); @@ -1522,7 +1649,7 @@ index 99432053cc3b242e514268b7aba2e2d83a9e64f2..c655f532dbcc6c63516027caf1453ca4 if (*envitems == NULL) { FreeEnvironmentStringsW(env); return UV_ENOMEM; -@@ -1471,7 +1472,7 @@ int uv_os_getenv(const char* name, char* buffer, size_t* size) { +@@ -1413,7 +1414,7 @@ int uv_os_getenv(const char* name, char* buffer, size_t* size) { uv__free(var); varlen = 1 + len; diff --git a/upstream_utils/libuv_patches/0002-Fix-warnings.patch b/upstream_utils/libuv_patches/0002-Fix-warnings.patch index 15f628fb467..0c9a4949fee 100644 --- a/upstream_utils/libuv_patches/0002-Fix-warnings.patch +++ b/upstream_utils/libuv_patches/0002-Fix-warnings.patch @@ -1,30 +1,31 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: PJ Reiniger Date: Tue, 26 Apr 2022 15:09:43 -0400 -Subject: [PATCH 02/10] Fix warnings +Subject: [PATCH 2/9] Fix warnings --- - include/uv/win.h | 5 +++ - src/idna.c | 2 +- - src/inet.c | 4 ++ - src/threadpool.c | 4 ++ - src/unix/core.c | 12 ++++- - src/unix/darwin.c | 106 +++++++++++++++++++++++--------------------- - src/unix/internal.h | 4 +- - src/unix/thread.c | 6 --- - src/uv-common.c | 8 ++++ - src/win/fs-event.c | 2 + - src/win/fs.c | 2 + - src/win/pipe.c | 2 + - src/win/process.c | 2 + - src/win/tty.c | 2 + - 14 files changed, 99 insertions(+), 62 deletions(-) + include/uv/win.h | 5 +++++ + src/idna.c | 2 +- + src/inet.c | 4 ++++ + src/threadpool.c | 4 ++++ + src/unix/core.c | 12 ++++++++++-- + src/unix/internal.h | 4 ++-- + src/unix/linux.c | 15 ++++++++++++--- + src/unix/thread.c | 6 ------ + src/uv-common.c | 8 ++++++++ + src/win/fs-event.c | 2 ++ + src/win/fs.c | 2 ++ + src/win/pipe.c | 2 ++ + src/win/process.c | 2 ++ + src/win/thread.c | 4 ++-- + src/win/tty.c | 2 ++ + 15 files changed, 58 insertions(+), 16 deletions(-) diff --git a/include/uv/win.h b/include/uv/win.h -index 56a4cf1151cd9262062d79c3676b83a287757426..10d5e8f169b04e9d48c87e3760320dba5cd310ce 100644 +index 6f8c47298e407bcb0151cf383a8370b71074f03e..c5473c2b82614c916f64ffd979d6dd7272221e3e 100644 --- a/include/uv/win.h +++ b/include/uv/win.h -@@ -201,11 +201,16 @@ typedef int (WSAAPI* LPFN_WSARECVFROM) +@@ -202,11 +202,16 @@ typedef int (WSAAPI* LPFN_WSARECVFROM) LPWSAOVERLAPPED overlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine); @@ -55,10 +56,10 @@ index 93d982ca018f2d39d9c0ffab07998c2c637029eb..36a39a089019fb4c2a35ec84516658c3 unsigned k; unsigned n; diff --git a/src/inet.c b/src/inet.c -index ca8b6ac8b69779655f69da758aa63d810332c800..1b190255ed5f4813428dbb3ba81a50cfd26c5bf1 100644 +index dd94bea3886ca37945fcad7909d765e3700e3c21..71c9e5b774d64d505e6c6d6ed2637178b8532d4d 100644 --- a/src/inet.c +++ b/src/inet.c -@@ -27,6 +27,10 @@ +@@ -22,6 +22,10 @@ #include "uv.h" #include "uv-common.h" @@ -70,7 +71,7 @@ index ca8b6ac8b69779655f69da758aa63d810332c800..1b190255ed5f4813428dbb3ba81a50cf #define UV__INET6_ADDRSTRLEN 46 diff --git a/src/threadpool.c b/src/threadpool.c -index 1241ace1cc304c14bf1b79cc2a588c1a50ef4507..718972c33b968ad123e6c8afac230f17282830a8 100644 +index f572de5aaf1a1b150e58c7b989949441cac279c4..aa282af468935b680140295a175e503ca82d8fa4 100644 --- a/src/threadpool.c +++ b/src/threadpool.c @@ -27,6 +27,10 @@ @@ -85,10 +86,10 @@ index 1241ace1cc304c14bf1b79cc2a588c1a50ef4507..718972c33b968ad123e6c8afac230f17 static uv_once_t once = UV_ONCE_INIT; diff --git a/src/unix/core.c b/src/unix/core.c -index 6353b0e3cc9448aa35dc2ccc9b259277b3fae9a5..223c55131b1ca01696792d9305ab33f0d21af73c 100644 +index 28c036f94f3e76717afa651451969f128c5a573c..268fc9652f437eb0d0cda2a9e0b06b9e91eb9742 100644 --- a/src/unix/core.c +++ b/src/unix/core.c -@@ -544,6 +544,16 @@ int uv__accept(int sockfd) { +@@ -575,6 +575,16 @@ int uv__accept(int sockfd) { return peerfd; } @@ -105,7 +106,7 @@ index 6353b0e3cc9448aa35dc2ccc9b259277b3fae9a5..223c55131b1ca01696792d9305ab33f0 /* 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. -@@ -558,10 +568,8 @@ int uv__close_nocancel(int fd) { +@@ -589,10 +599,8 @@ int uv__close_nocancel(int fd) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension" #if defined(__LP64__) || TARGET_OS_IPHONE @@ -116,135 +117,11 @@ index 6353b0e3cc9448aa35dc2ccc9b259277b3fae9a5..223c55131b1ca01696792d9305ab33f0 return close$NOCANCEL$UNIX2003(fd); #endif #pragma GCC diagnostic pop -diff --git a/src/unix/darwin.c b/src/unix/darwin.c -index 5fbf734218fa17cc61c03402c8b1dd6b66110ecb..eeb35720f55bf26363a064443bd02fb9aae682a4 100644 ---- a/src/unix/darwin.c -+++ b/src/unix/darwin.c -@@ -253,64 +253,68 @@ static int uv__get_cpu_speed(uint64_t* speed) { - - #define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8) - -- kr = pIOMasterPort(MACH_PORT_NULL, &mach_port); -- assert(kr == KERN_SUCCESS); -- CFMutableDictionaryRef classes_to_match -- = pIOServiceMatching("IOPlatformDevice"); -- kr = pIOServiceGetMatchingServices(mach_port, classes_to_match, &it); -- assert(kr == KERN_SUCCESS); -- service = pIOIteratorNext(it); -- -- CFStringRef device_type_str = S("device_type"); -- CFStringRef clock_frequency_str = S("clock-frequency"); -- -- while (service != 0) { -- CFDataRef data; -- data = pIORegistryEntryCreateCFProperty(service, -- device_type_str, -- NULL, -- 0); -- if (data) { -- const UInt8* raw = pCFDataGetBytePtr(data); -- if (strncmp((char*)raw, "cpu", 3) == 0 || -- strncmp((char*)raw, "processor", 9) == 0) { -- CFDataRef freq_ref; -- freq_ref = pIORegistryEntryCreateCFProperty(service, -- clock_frequency_str, -- NULL, -- 0); -- if (freq_ref) { -- const UInt8* freq_ref_ptr = pCFDataGetBytePtr(freq_ref); -- CFIndex len = pCFDataGetLength(freq_ref); -- if (len == 8) -- memcpy(speed, freq_ref_ptr, 8); -- else if (len == 4) { -- uint32_t v; -- memcpy(&v, freq_ref_ptr, 4); -- *speed = v; -- } else { -- *speed = 0; -- } -+ // Braces ensure goto doesn't jump into device_type_str's and -+ // clock_frequency_str's lifetimes after their initialization -+ { -+ kr = pIOMasterPort(MACH_PORT_NULL, &mach_port); -+ assert(kr == KERN_SUCCESS); -+ CFMutableDictionaryRef classes_to_match -+ = pIOServiceMatching("IOPlatformDevice"); -+ kr = pIOServiceGetMatchingServices(mach_port, classes_to_match, &it); -+ assert(kr == KERN_SUCCESS); -+ service = pIOIteratorNext(it); - -- pCFRelease(freq_ref); -- pCFRelease(data); -- break; -+ CFStringRef device_type_str = S("device_type"); -+ CFStringRef clock_frequency_str = S("clock-frequency"); -+ -+ while (service != 0) { -+ CFDataRef data; -+ data = pIORegistryEntryCreateCFProperty(service, -+ device_type_str, -+ NULL, -+ 0); -+ if (data) { -+ const UInt8* raw = pCFDataGetBytePtr(data); -+ if (strncmp((char*)raw, "cpu", 3) == 0 || -+ strncmp((char*)raw, "processor", 9) == 0) { -+ CFDataRef freq_ref; -+ freq_ref = pIORegistryEntryCreateCFProperty(service, -+ clock_frequency_str, -+ NULL, -+ 0); -+ if (freq_ref) { -+ const UInt8* freq_ref_ptr = pCFDataGetBytePtr(freq_ref); -+ CFIndex len = pCFDataGetLength(freq_ref); -+ if (len == 8) -+ memcpy(speed, freq_ref_ptr, 8); -+ else if (len == 4) { -+ uint32_t v; -+ memcpy(&v, freq_ref_ptr, 4); -+ *speed = v; -+ } else { -+ *speed = 0; -+ } -+ -+ pCFRelease(freq_ref); -+ pCFRelease(data); -+ break; -+ } - } -+ pCFRelease(data); - } -- pCFRelease(data); -- } - -- service = pIOIteratorNext(it); -- } -+ service = pIOIteratorNext(it); -+ } - -- pIOObjectRelease(it); -+ pIOObjectRelease(it); - -- err = 0; -+ err = 0; - -- if (device_type_str != NULL) -- pCFRelease(device_type_str); -- if (clock_frequency_str != NULL) -- pCFRelease(clock_frequency_str); -+ if (device_type_str != NULL) -+ pCFRelease(device_type_str); -+ if (clock_frequency_str != NULL) -+ pCFRelease(clock_frequency_str); -+ } - - out: - if (core_foundation_handle != NULL) diff --git a/src/unix/internal.h b/src/unix/internal.h -index cee35c2106aed2990e28ab7d32335061fe7d6d47..f9d1666d8b2104b7437f11c4e0d9c4ae82ff0e31 100644 +index fe5885136039d5332623467b86bf52cd4b32ca0f..98c437dcadec5b5106d697e82d5394d459f55e47 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h -@@ -312,8 +312,8 @@ UV_UNUSED(static void uv__update_time(uv_loop_t* loop)) { +@@ -384,8 +384,8 @@ UV_UNUSED(static void uv__update_time(uv_loop_t* loop)) { loop->time = uv__hrtime(UV_CLOCK_FAST) / 1000000; } @@ -255,11 +132,51 @@ index cee35c2106aed2990e28ab7d32335061fe7d6d47..f9d1666d8b2104b7437f11c4e0d9c4ae s = strrchr(path, '/'); if (s == NULL) +diff --git a/src/unix/linux.c b/src/unix/linux.c +index 9173850bd158eaf9c41deca38f9ba84762a027a1..157443792f1216c83b4221c3810d17c81c5913c4 100644 +--- a/src/unix/linux.c ++++ b/src/unix/linux.c +@@ -1718,7 +1718,11 @@ int uv_cpu_info(uv_cpu_info_t** ci, int* count) { + return UV__ERR(errno); + } + +- fgets(buf, sizeof(buf), fp); /* Skip first line. */ ++ /* Skip first line. */ ++ if (!fgets(buf, sizeof(buf), fp)) { ++ uv__free(cpus); ++ return UV__ERR(errno); ++ } + + for (;;) { + memset(&t, 0, sizeof(t)); +@@ -1729,7 +1733,10 @@ int uv_cpu_info(uv_cpu_info_t** ci, int* count) { + if (n != 7) + break; + +- fgets(buf, sizeof(buf), fp); /* Skip rest of line. */ ++ /* Skip rest of line. */ ++ if (!fgets(buf, sizeof(buf), fp)) { ++ break; ++ } + + if (cpu >= ARRAY_SIZE(*cpus)) + continue; +@@ -1809,7 +1816,9 @@ nocpuinfo: + if (fp == NULL) + continue; + +- fscanf(fp, "%llu", &(*cpus)[cpu].freq); ++ if (0 > fscanf(fp, "%llu", &(*cpus)[cpu].freq)) { ++ (*cpus)[cpu].freq = 0llu; ++ } + fclose(fp); + fp = NULL; + } diff --git a/src/unix/thread.c b/src/unix/thread.c -index 759cd0c28518928127837ba82cbf8e761c6223d3..64726bd618b930e1aa7e1de3cbceb8aa712ff617 100644 +index 531c6211bb4321e5f11031a0644b4e3ab9174396..f8600947e3e7df015c4302af4feee740707b2c46 100644 --- a/src/unix/thread.c +++ b/src/unix/thread.c -@@ -244,12 +244,6 @@ int uv_thread_create_ex(uv_thread_t* tid, +@@ -137,12 +137,6 @@ int uv_thread_create_ex(uv_thread_t* tid, size_t stack_size; size_t min_stack_size; @@ -273,10 +190,10 @@ index 759cd0c28518928127837ba82cbf8e761c6223d3..64726bd618b930e1aa7e1de3cbceb8aa params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0; diff --git a/src/uv-common.c b/src/uv-common.c -index dfb606e3e842ccb3b2d9327e2b3048c4cfdd0314..49026c03c53a0779a051b8f6bd5809961f5c54e2 100644 +index c04f93596ab1f730576256d86e216ccb7f258b72..cd10b36b4a393e325ea03b93eb9897193ca9800b 100644 --- a/src/uv-common.c +++ b/src/uv-common.c -@@ -758,6 +758,10 @@ void uv__fs_readdir_cleanup(uv_fs_t* req) { +@@ -799,6 +799,10 @@ void uv__fs_readdir_cleanup(uv_fs_t* req) { } } @@ -287,7 +204,7 @@ index dfb606e3e842ccb3b2d9327e2b3048c4cfdd0314..49026c03c53a0779a051b8f6bd580996 int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) { va_list ap; -@@ -771,6 +775,10 @@ int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) { +@@ -812,6 +816,10 @@ int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) { return err; } @@ -312,7 +229,7 @@ index 150467313d576bfe2966b55f3d8cffa23cbb8ea3..3244a4e4320d7ce98f226b49b2634c65 #include #include diff --git a/src/win/fs.c b/src/win/fs.c -index 8374012f0e9ee094eed5db19e5f7d12286052d70..f71b3c04487a949690fdfd8a6975fd8648acc793 100644 +index 328c8f2e0513562b53c948ffea59d0841e14b264..565c05fff13c2e6e74091c1da7b31636d7fd370d 100644 --- a/src/win/fs.c +++ b/src/win/fs.c @@ -19,6 +19,8 @@ @@ -325,7 +242,7 @@ index 8374012f0e9ee094eed5db19e5f7d12286052d70..f71b3c04487a949690fdfd8a6975fd86 #include #include diff --git a/src/win/pipe.c b/src/win/pipe.c -index cd77061a079094b11350a01ddd364e15fa3078bc..f413a72dab5c9d58bfbc768152314dc347f7469d 100644 +index c1739efe82b8755999145860b4da6b50c73518a2..258d6a684c67f154096a25e7226f1a7d08b93d5b 100644 --- a/src/win/pipe.c +++ b/src/win/pipe.c @@ -19,6 +19,8 @@ @@ -338,7 +255,7 @@ index cd77061a079094b11350a01ddd364e15fa3078bc..f413a72dab5c9d58bfbc768152314dc3 #include #include diff --git a/src/win/process.c b/src/win/process.c -index e857db3e98eb24f8de12e6b6d90ae3905cc49ce7..a49016f65601c0127b4c0ba5b538e2556314eb46 100644 +index 44072b05e5858884e7f648a145cd15a2b574116d..9a884c2fe864f84ad7012ef2df3e2a4b1e11e6ee 100644 --- a/src/win/process.c +++ b/src/win/process.c @@ -19,6 +19,8 @@ @@ -350,8 +267,23 @@ index e857db3e98eb24f8de12e6b6d90ae3905cc49ce7..a49016f65601c0127b4c0ba5b538e255 #include #include #include +diff --git a/src/win/thread.c b/src/win/thread.c +index 57f1698f595e2410a51044f7f228b5a235206819..03b33e9b4de6fe2532095d717a8639e8df454cce 100644 +--- a/src/win/thread.c ++++ b/src/win/thread.c +@@ -204,8 +204,8 @@ int uv_thread_setaffinity(uv_thread_t* tid, + threadmask = 0; + for (i = 0; i < cpumasksize; i++) { + if (cpumask[i]) { +- if (procmask & (1 << i)) +- threadmask |= 1 << i; ++ if (procmask & (1LL << i)) ++ threadmask |= 1LL << i; + else + return UV_EINVAL; + } diff --git a/src/win/tty.c b/src/win/tty.c -index 267ca64519963ff87b2404f08a60c111e25b89c2..d75226681c2653dc2a5118756b72e0b601cf9701 100644 +index 7e1f15544b177382a774300f832bc982d85bd62b..abbe1315883257d6825b794344dcd4cba9514097 100644 --- a/src/win/tty.c +++ b/src/win/tty.c @@ -19,6 +19,8 @@ diff --git a/upstream_utils/libuv_patches/0003-Preprocessor-cleanup.patch b/upstream_utils/libuv_patches/0003-Preprocessor-cleanup.patch index dd550103919..f5e0328d3fa 100644 --- a/upstream_utils/libuv_patches/0003-Preprocessor-cleanup.patch +++ b/upstream_utils/libuv_patches/0003-Preprocessor-cleanup.patch @@ -1,21 +1,20 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: PJ Reiniger Date: Tue, 26 Apr 2022 15:19:14 -0400 -Subject: [PATCH 03/10] Preprocessor cleanup +Subject: [PATCH 3/9] Preprocessor cleanup --- - include/uv.h | 18 +----------------- + include/uv.h | 12 ------------ include/uv/unix.h | 8 -------- - include/uv/win.h | 6 +----- src/unix/internal.h | 2 ++ src/win/fs.c | 1 + src/win/tty.c | 2 ++ src/win/util.c | 8 ++++++++ src/win/winsock.c | 1 + - 8 files changed, 16 insertions(+), 30 deletions(-) + 7 files changed, 14 insertions(+), 20 deletions(-) diff --git a/include/uv.h b/include/uv.h -index ee1c94ccd389915ea7572cce044256a7788025ad..dbaeb1e9dcca2f5170221b14494dba18c6425f6d 100644 +index 02397dd0fdd43d51f86c0dde9a62046702f12bdb..d5342b0d52232bbf83825948cc6bc09e5d74a4c7 100644 --- a/include/uv.h +++ b/include/uv.h @@ -23,9 +23,6 @@ @@ -28,20 +27,7 @@ index ee1c94ccd389915ea7572cce044256a7788025ad..dbaeb1e9dcca2f5170221b14494dba18 #if defined(BUILDING_UV_SHARED) && defined(USING_UV_SHARED) #error "Define either BUILDING_UV_SHARED or USING_UV_SHARED, not both." -@@ -56,11 +53,7 @@ extern "C" { - #include - #include - --#if defined(_MSC_VER) && _MSC_VER < 1600 --# include "uv/stdint-msvc2008.h" --#else --# include --#endif -+#include - - #if defined(_WIN32) - # include "uv/win.h" -@@ -767,16 +760,10 @@ UV_EXTERN int uv_tty_get_winsize(uv_tty_t*, int* width, int* height); +@@ -796,16 +793,10 @@ UV_EXTERN int uv_tty_get_winsize(uv_tty_t*, int* width, int* height); UV_EXTERN void uv_tty_set_vterm_state(uv_tty_vtermstate_t state); UV_EXTERN int uv_tty_get_vterm_state(uv_tty_vtermstate_t* state); @@ -57,8 +43,8 @@ index ee1c94ccd389915ea7572cce044256a7788025ad..dbaeb1e9dcca2f5170221b14494dba18 - UV_EXTERN uv_handle_type uv_guess_handle(uv_file file); - /* -@@ -1844,7 +1831,4 @@ UV_EXTERN void uv_loop_set_data(uv_loop_t*, void* data); + enum { +@@ -1906,7 +1897,4 @@ UV_EXTERN void uv_loop_set_data(uv_loop_t*, void* data); #undef UV_LOOP_PRIVATE_PLATFORM_FIELDS #undef UV__ERR @@ -67,7 +53,7 @@ index ee1c94ccd389915ea7572cce044256a7788025ad..dbaeb1e9dcca2f5170221b14494dba18 -#endif #endif /* UV_H */ diff --git a/include/uv/unix.h b/include/uv/unix.h -index 420be86c6f9984486c6420ff710c9dbcad09e411..256fef37692da6c5dc9f7bb7d21c576b41a36b8c 100644 +index 09f88a5674280d762c094d956e5dec6971c6a33e..e334cabe0280ef94bacbb1171049c71f17bf56ff 100644 --- a/include/uv/unix.h +++ b/include/uv/unix.h @@ -47,14 +47,6 @@ @@ -85,28 +71,11 @@ index 420be86c6f9984486c6420ff710c9dbcad09e411..256fef37692da6c5dc9f7bb7d21c576b #elif defined(__APPLE__) # include "uv/darwin.h" #elif defined(__DragonFly__) || \ -diff --git a/include/uv/win.h b/include/uv/win.h -index 10d5e8f169b04e9d48c87e3760320dba5cd310ce..0a33366f3f4b51dbf70691623efe1343ee6b2547 100644 ---- a/include/uv/win.h -+++ b/include/uv/win.h -@@ -60,11 +60,7 @@ typedef struct pollfd { - #include - #include - --#if defined(_MSC_VER) && _MSC_VER < 1600 --# include "uv/stdint-msvc2008.h" --#else --# include --#endif -+#include - - #include "uv/tree.h" - #include "uv/threadpool.h" diff --git a/src/unix/internal.h b/src/unix/internal.h -index f9d1666d8b2104b7437f11c4e0d9c4ae82ff0e31..2b6541576bdc977e3b5a15dca4d3ad4410b4a54f 100644 +index 98c437dcadec5b5106d697e82d5394d459f55e47..854d98a16a74c45e0b6cb92b17782de6803f6e28 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h -@@ -192,6 +192,8 @@ struct uv__stream_queued_fds_s { +@@ -233,6 +233,8 @@ struct uv__statx { #if defined(__linux__) && O_NDELAY != O_NONBLOCK #undef uv__nonblock #define uv__nonblock uv__nonblock_fcntl @@ -116,22 +85,22 @@ index f9d1666d8b2104b7437f11c4e0d9c4ae82ff0e31..2b6541576bdc977e3b5a15dca4d3ad44 /* core */ diff --git a/src/win/fs.c b/src/win/fs.c -index f71b3c04487a949690fdfd8a6975fd8648acc793..71c9b1693bb17e168fb04192c8939c25e03a617d 100644 +index 565c05fff13c2e6e74091c1da7b31636d7fd370d..f415ddc2c39d09eea317fc857777acce1ce7d13e 100644 --- a/src/win/fs.c +++ b/src/win/fs.c -@@ -38,6 +38,7 @@ - #include "handle-inl.h" - #include "fs-fd-hash-inl.h" +@@ -40,6 +40,7 @@ + + #include +#pragma comment(lib, "Advapi32.lib") #define UV_FS_FREE_PATHS 0x0002 #define UV_FS_FREE_PTR 0x0008 diff --git a/src/win/tty.c b/src/win/tty.c -index d75226681c2653dc2a5118756b72e0b601cf9701..9753784dc0118a12ef45060bf9af673bfaa838d0 100644 +index abbe1315883257d6825b794344dcd4cba9514097..9bb3d9e830c901122da5e521e0c6b032dfd5044c 100644 --- a/src/win/tty.c +++ b/src/win/tty.c -@@ -42,6 +42,8 @@ +@@ -37,6 +37,8 @@ #include "stream-inl.h" #include "req-inl.h" @@ -141,10 +110,10 @@ index d75226681c2653dc2a5118756b72e0b601cf9701..9753784dc0118a12ef45060bf9af673b # define InterlockedOr _InterlockedOr #endif diff --git a/src/win/util.c b/src/win/util.c -index c655f532dbcc6c63516027caf1453ca4ef817cff..7a5dd2ef99ba335a146635b61f8d3eba7ff5ef75 100644 +index 1cfd7b2caf0d4ad1a6a66df9406c21f4e2b69b04..af18cfa6c106c5de0996e4fff9b4127aaa3b576b 100644 --- a/src/win/util.c +++ b/src/win/util.c -@@ -63,12 +63,20 @@ +@@ -64,12 +64,20 @@ /* A RtlGenRandom() by any other name... */ diff --git a/upstream_utils/libuv_patches/0004-Cleanup-problematic-language.patch b/upstream_utils/libuv_patches/0004-Cleanup-problematic-language.patch index 10fac00d069..6c8cfaf98f3 100644 --- a/upstream_utils/libuv_patches/0004-Cleanup-problematic-language.patch +++ b/upstream_utils/libuv_patches/0004-Cleanup-problematic-language.patch @@ -1,14 +1,14 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: PJ Reiniger Date: Tue, 26 Apr 2022 15:24:47 -0400 -Subject: [PATCH 04/10] Cleanup problematic language +Subject: [PATCH 4/9] Cleanup problematic language --- src/unix/tty.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/unix/tty.c b/src/unix/tty.c -index b41505258ff822ef31c62f4a44438b5525a02065..ed81e26a8dcbad52bc31fbd1964ab6de4ea85d13 100644 +index d099bdb3b677212d21e06ac7bb1031c8e5386499..1bd217b5a15eed13a8349c479b53471dd36ca216 100644 --- a/src/unix/tty.c +++ b/src/unix/tty.c @@ -79,7 +79,7 @@ int uv__tcsetattr(int fd, int how, const struct termios *term) { @@ -18,7 +18,7 @@ index b41505258ff822ef31c62f4a44438b5525a02065..ed81e26a8dcbad52bc31fbd1964ab6de -static int uv__tty_is_slave(const int fd) { +static int uv__tty_is_peripheral(const int fd) { int result; - #if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + #if defined(__linux__) || defined(__FreeBSD__) int dummy; @@ -91,15 +91,16 @@ static int uv__tty_is_slave(const int fd) { result = ioctl(fd, TIOCPTYGNAME, &dummy) != 0; diff --git a/upstream_utils/libuv_patches/0006-Style-comments-cleanup.patch b/upstream_utils/libuv_patches/0005-Style-comments-cleanup.patch similarity index 54% rename from upstream_utils/libuv_patches/0006-Style-comments-cleanup.patch rename to upstream_utils/libuv_patches/0005-Style-comments-cleanup.patch index a472b220059..1d6fcaef8d7 100644 --- a/upstream_utils/libuv_patches/0006-Style-comments-cleanup.patch +++ b/upstream_utils/libuv_patches/0005-Style-comments-cleanup.patch @@ -1,16 +1,15 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: PJ Reiniger Date: Tue, 26 Apr 2022 15:28:52 -0400 -Subject: [PATCH 06/10] Style / comments cleanup +Subject: [PATCH 5/9] Style / comments cleanup --- src/fs-poll.c | 1 + src/unix/core.c | 1 + - src/unix/thread.c | 3 +-- src/uv-common.c | 1 + src/win/process.c | 1 - src/win/winsock.c | 1 + - 6 files changed, 5 insertions(+), 3 deletions(-) + 5 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/fs-poll.c b/src/fs-poll.c index 5a39daed095502b2db34f23fcaf0ab04f31f96ff..1a7ca70d62c71f6eaef2b9985796cc46a6438869 100644 @@ -25,10 +24,10 @@ index 5a39daed095502b2db34f23fcaf0ab04f31f96ff..1a7ca70d62c71f6eaef2b9985796cc46 uv_fs_poll_t* parent_handle; int busy_polling; diff --git a/src/unix/core.c b/src/unix/core.c -index 223c55131b1ca01696792d9305ab33f0d21af73c..4c23f608c842bdcb09d621374a0ccb0bda79166e 100644 +index 268fc9652f437eb0d0cda2a9e0b06b9e91eb9742..f53adc156a7c454c492abaeac29d90be436785fc 100644 --- a/src/unix/core.c +++ b/src/unix/core.c -@@ -544,6 +544,7 @@ int uv__accept(int sockfd) { +@@ -575,6 +575,7 @@ int uv__accept(int sockfd) { return peerfd; } @@ -36,39 +35,11 @@ index 223c55131b1ca01696792d9305ab33f0d21af73c..4c23f608c842bdcb09d621374a0ccb0b #if defined(__APPLE__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension" -diff --git a/src/unix/thread.c b/src/unix/thread.c -index 64726bd618b930e1aa7e1de3cbceb8aa712ff617..392a0715a85074576ba89d2a415ca55037edf347 100644 ---- a/src/unix/thread.c -+++ b/src/unix/thread.c -@@ -85,7 +85,6 @@ error2: - return rc; - } - -- - int uv_barrier_wait(uv_barrier_t* barrier) { - struct _uv_barrier* b; - int last; -@@ -94,6 +93,7 @@ int uv_barrier_wait(uv_barrier_t* barrier) { - return UV_EINVAL; - - b = barrier->b; -+ /* Lock the mutex*/ - uv_mutex_lock(&b->mutex); - - if (++b->in == b->threshold) { -@@ -113,7 +113,6 @@ int uv_barrier_wait(uv_barrier_t* barrier) { - return last; - } - -- - void uv_barrier_destroy(uv_barrier_t* barrier) { - struct _uv_barrier* b; - diff --git a/src/uv-common.c b/src/uv-common.c -index 49026c03c53a0779a051b8f6bd5809961f5c54e2..c9a32c0336777aa3a41cac7cb7a4c23ad3f677da 100644 +index cd10b36b4a393e325ea03b93eb9897193ca9800b..bfcc3ef10f4fd7763221638947da6e02e7a17c33 100644 --- a/src/uv-common.c +++ b/src/uv-common.c -@@ -758,6 +758,7 @@ void uv__fs_readdir_cleanup(uv_fs_t* req) { +@@ -799,6 +799,7 @@ void uv__fs_readdir_cleanup(uv_fs_t* req) { } } @@ -77,12 +48,12 @@ index 49026c03c53a0779a051b8f6bd5809961f5c54e2..c9a32c0336777aa3a41cac7cb7a4c23a # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wvarargs" diff --git a/src/win/process.c b/src/win/process.c -index a49016f65601c0127b4c0ba5b538e2556314eb46..8e7835a5e90f9fae89fc9a9be2f6945e2814dfa7 100644 +index 9a884c2fe864f84ad7012ef2df3e2a4b1e11e6ee..a0f55aba0037c71af04dc5a29ced412b8d3d3268 100644 --- a/src/win/process.c +++ b/src/win/process.c -@@ -35,7 +35,6 @@ - #include "handle-inl.h" - #include "req-inl.h" +@@ -38,7 +38,6 @@ + #include + #include /* GetModuleBaseNameW */ - #define SIGKILL 9 diff --git a/upstream_utils/libuv_patches/0005-Use-roborio-time.patch b/upstream_utils/libuv_patches/0005-Use-roborio-time.patch deleted file mode 100644 index c4b27885412..00000000000 --- a/upstream_utils/libuv_patches/0005-Use-roborio-time.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: PJ Reiniger -Date: Tue, 26 Apr 2022 15:26:03 -0400 -Subject: [PATCH 05/10] Use roborio time - ---- - src/unix/linux-core.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/src/unix/linux-core.c b/src/unix/linux-core.c -index 85f3fc0170288577d2e39030dc728de9a694a752..12ed7ff1129ebeb1c11beeca584bd0519c1e1fe6 100644 ---- a/src/unix/linux-core.c -+++ b/src/unix/linux-core.c -@@ -67,6 +67,10 @@ - # define CLOCK_MONOTONIC_COARSE 6 - #endif - -+#ifdef __FRC_ROBORIO__ -+#include "wpi/timestamp.h" -+#endif -+ - /* This is rather annoying: CLOCK_BOOTTIME lives in but we can't - * include that file because it conflicts with . We'll just have to - * define it ourselves. -@@ -118,6 +122,9 @@ void uv__platform_loop_delete(uv_loop_t* loop) { - - - uint64_t uv__hrtime(uv_clocktype_t type) { -+#ifdef __FRC_ROBORIO__ -+ return wpi::Now() * 1000u; -+#else - static clock_t fast_clock_id = -1; - struct timespec t; - clock_t clock_id; -@@ -151,6 +158,7 @@ done: - return 0; /* Not really possible. */ - - return t.tv_sec * (uint64_t) 1e9 + t.tv_nsec; -+#endif - } - - diff --git a/upstream_utils/libuv_patches/0008-Fix-Win32-warning-suppression-pragma.patch b/upstream_utils/libuv_patches/0006-Fix-Win32-warning-suppression-pragma.patch similarity index 72% rename from upstream_utils/libuv_patches/0008-Fix-Win32-warning-suppression-pragma.patch rename to upstream_utils/libuv_patches/0006-Fix-Win32-warning-suppression-pragma.patch index 2484f969f7e..a810160316b 100644 --- a/upstream_utils/libuv_patches/0008-Fix-Win32-warning-suppression-pragma.patch +++ b/upstream_utils/libuv_patches/0006-Fix-Win32-warning-suppression-pragma.patch @@ -1,17 +1,17 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Tyler Veness Date: Sat, 21 May 2022 22:58:06 -0700 -Subject: [PATCH 08/10] Fix Win32 warning suppression pragma +Subject: [PATCH 6/9] Fix Win32 warning suppression pragma --- src/win/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win/util.c b/src/win/util.c -index 7a5dd2ef99ba335a146635b61f8d3eba7ff5ef75..d9888aec7959de4ec49377a71b0dc931e89e5f4e 100644 +index af18cfa6c106c5de0996e4fff9b4127aaa3b576b..9324992ec521cc3496e3e9304e600963a3f20897 100644 --- a/src/win/util.c +++ b/src/win/util.c -@@ -1750,7 +1750,7 @@ int uv_os_uname(uv_utsname_t* buffer) { +@@ -1692,7 +1692,7 @@ int uv_os_uname(uv_utsname_t* buffer) { } else { /* Silence GetVersionEx() deprecation warning. */ #ifdef _MSC_VER diff --git a/upstream_utils/libuv_patches/0007-Squelch-GCC-warnings-we-don-t-know-how-to-fix.patch b/upstream_utils/libuv_patches/0007-Squelch-GCC-warnings-we-don-t-know-how-to-fix.patch deleted file mode 100644 index b0ca81cf5ca..00000000000 --- a/upstream_utils/libuv_patches/0007-Squelch-GCC-warnings-we-don-t-know-how-to-fix.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tyler Veness -Date: Tue, 17 May 2022 21:36:57 -0700 -Subject: [PATCH 07/10] Squelch GCC warnings we don't know how to fix - ---- - src/queue.h | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - -diff --git a/src/queue.h b/src/queue.h -index ff3540a0a51c840d7ff5e6a3cea95f24c27b0812..c0d5efc187c78f7d60776447be492a9310c3b36c 100644 ---- a/src/queue.h -+++ b/src/queue.h -@@ -58,6 +58,7 @@ typedef void *QUEUE[2]; - } \ - while (0) - -+#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 12 - #define QUEUE_SPLIT(h, q, n) \ - do { \ - QUEUE_PREV(n) = QUEUE_PREV(h); \ -@@ -65,9 +66,24 @@ typedef void *QUEUE[2]; - QUEUE_NEXT(n) = (q); \ - QUEUE_PREV(h) = QUEUE_PREV(q); \ - QUEUE_PREV_NEXT(h) = (h); \ -+ _Pragma("GCC diagnostic push") \ -+ _Pragma("GCC diagnostic ignored \"-Wdangling-pointer=\"") \ - QUEUE_PREV(q) = (n); \ -+ _Pragma("GCC diagnostic pop") \ - } \ - while (0) -+#else -+#define QUEUE_SPLIT(h, q, n) \ -+ do { \ -+ QUEUE_PREV(n) = QUEUE_PREV(h); \ -+ QUEUE_PREV_NEXT(n) = (n); \ -+ QUEUE_NEXT(n) = (q); \ -+ QUEUE_PREV(h) = QUEUE_PREV(q); \ -+ QUEUE_PREV_NEXT(h) = (h); \ -+ QUEUE_PREV(q) = (n); \ -+ } \ -+ while (0) -+#endif // defined(__GNUC__) && !defined(__clang__) - - #define QUEUE_MOVE(h, n) \ - do { \ diff --git a/upstream_utils/libuv_patches/0007-Use-C-atomics.patch b/upstream_utils/libuv_patches/0007-Use-C-atomics.patch new file mode 100644 index 00000000000..41400fe2630 --- /dev/null +++ b/upstream_utils/libuv_patches/0007-Use-C-atomics.patch @@ -0,0 +1,531 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tyler Veness +Date: Thu, 13 Jul 2023 22:13:47 -0700 +Subject: [PATCH 7/9] Use C++ atomics + +--- + src/unix/async.c | 25 +++++++++++++------------ + src/unix/core.c | 3 ++- + src/unix/fs.c | 32 +++++++++++++++++--------------- + src/unix/kqueue.c | 10 ++++++---- + src/unix/linux.c | 45 +++++++++++++++++++++++---------------------- + src/unix/tty.c | 5 +++-- + src/uv-common.c | 2 +- + src/uv-common.h | 8 +++----- + 8 files changed, 68 insertions(+), 62 deletions(-) + +diff --git a/src/unix/async.c b/src/unix/async.c +index 0ff2669e30a628dbb2df9e28ba14b38cf14114e5..fef4ae93343edc0341179a1c4739dcd831ef6e26 100644 +--- a/src/unix/async.c ++++ b/src/unix/async.c +@@ -26,7 +26,6 @@ + #include "internal.h" + + #include +-#include + #include /* snprintf() */ + #include + #include +@@ -38,6 +37,8 @@ + #include + #endif + ++#include ++ + static void uv__async_send(uv_loop_t* loop); + static int uv__async_start(uv_loop_t* loop); + static void uv__cpu_relax(void); +@@ -63,14 +64,14 @@ int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) { + + + int uv_async_send(uv_async_t* handle) { +- _Atomic int* pending; +- _Atomic int* busy; ++ std::atomic* pending; ++ std::atomic* busy; + +- pending = (_Atomic int*) &handle->pending; +- busy = (_Atomic int*) &handle->u.fd; ++ pending = (std::atomic*) &handle->pending; ++ busy = (std::atomic*) &handle->u.fd; + + /* Do a cheap read first. */ +- if (atomic_load_explicit(pending, memory_order_relaxed) != 0) ++ if (atomic_load_explicit(pending, std::memory_order_relaxed) != 0) + return 0; + + /* Set the loop to busy. */ +@@ -90,12 +91,12 @@ int uv_async_send(uv_async_t* handle) { + /* Wait for the busy flag to clear before closing. + * Only call this from the event loop thread. */ + static void uv__async_spin(uv_async_t* handle) { +- _Atomic int* pending; +- _Atomic int* busy; ++ std::atomic* pending; ++ std::atomic* busy; + int i; + +- pending = (_Atomic int*) &handle->pending; +- busy = (_Atomic int*) &handle->u.fd; ++ pending = (std::atomic*) &handle->pending; ++ busy = (std::atomic*) &handle->u.fd; + + /* Set the pending flag first, so no new events will be added by other + * threads after this function returns. */ +@@ -135,7 +136,7 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { + struct uv__queue queue; + struct uv__queue* q; + uv_async_t* h; +- _Atomic int *pending; ++ std::atomic *pending; + + assert(w == &loop->async_io_watcher); + +@@ -166,7 +167,7 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { + uv__queue_insert_tail(&loop->async_handles, q); + + /* Atomically fetch and clear pending flag */ +- pending = (_Atomic int*) &h->pending; ++ pending = (std::atomic*) &h->pending; + if (atomic_exchange(pending, 0) == 0) + continue; + +diff --git a/src/unix/core.c b/src/unix/core.c +index f53adc156a7c454c492abaeac29d90be436785fc..ce7fd2cdfdd53410dc694450bd56dffc26ff4792 100644 +--- a/src/unix/core.c ++++ b/src/unix/core.c +@@ -45,6 +45,7 @@ + #include + #include + #include /* clock_gettime */ ++#include + + #ifdef __sun + # include +@@ -263,7 +264,7 @@ int uv__getiovmax(void) { + #if defined(IOV_MAX) + return IOV_MAX; + #elif defined(_SC_IOV_MAX) +- static _Atomic int iovmax_cached = -1; ++ static std::atomic iovmax_cached = -1; + int iovmax; + + iovmax = atomic_load_explicit(&iovmax_cached, memory_order_relaxed); +diff --git a/src/unix/fs.c b/src/unix/fs.c +index e25d02e54dbe93e4b9c22b0140108c99ae2cb4f7..aba190a9c0240fba0128fb7fbc5d92d7fa86214b 100644 +--- a/src/unix/fs.c ++++ b/src/unix/fs.c +@@ -46,6 +46,8 @@ + #include + #include + ++#include ++ + #if defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__OpenBSD__) || \ +@@ -313,7 +315,7 @@ static int uv__fs_mkstemp(uv_fs_t* req) { + static uv_once_t once = UV_ONCE_INIT; + int r; + #ifdef O_CLOEXEC +- static _Atomic int no_cloexec_support; ++ static std::atomic no_cloexec_support; + #endif + static const char pattern[] = "XXXXXX"; + static const size_t pattern_size = sizeof(pattern) - 1; +@@ -338,7 +340,7 @@ static int uv__fs_mkstemp(uv_fs_t* req) { + uv_once(&once, uv__mkostemp_initonce); + + #ifdef O_CLOEXEC +- if (atomic_load_explicit(&no_cloexec_support, memory_order_relaxed) == 0 && ++ if (atomic_load_explicit(&no_cloexec_support, std::memory_order_relaxed) == 0 && + uv__mkostemp != NULL) { + r = uv__mkostemp(path, O_CLOEXEC); + +@@ -352,7 +354,7 @@ static int uv__fs_mkstemp(uv_fs_t* req) { + + /* We set the static variable so that next calls don't even + try to use mkostemp. */ +- atomic_store_explicit(&no_cloexec_support, 1, memory_order_relaxed); ++ atomic_store_explicit(&no_cloexec_support, 1, std::memory_order_relaxed); + } + #endif /* O_CLOEXEC */ + +@@ -462,7 +464,7 @@ static ssize_t uv__fs_preadv(uv_file fd, + + static ssize_t uv__fs_read(uv_fs_t* req) { + #if TRY_PREADV +- static _Atomic int no_preadv; ++ static std::atomic no_preadv; + #endif + unsigned int iovmax; + ssize_t result; +@@ -486,7 +488,7 @@ static ssize_t uv__fs_read(uv_fs_t* req) { + result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off); + #else + # if TRY_PREADV +- if (atomic_load_explicit(&no_preadv, memory_order_relaxed)) retry: ++ if (atomic_load_explicit(&no_preadv, std::memory_order_relaxed)) retry: + # endif + { + result = uv__fs_preadv(req->file, req->bufs, req->nbufs, req->off); +@@ -498,7 +500,7 @@ static ssize_t uv__fs_read(uv_fs_t* req) { + req->nbufs, + req->off); + if (result == -1 && errno == ENOSYS) { +- atomic_store_explicit(&no_preadv, 1, memory_order_relaxed); ++ atomic_store_explicit(&no_preadv, 1, std::memory_order_relaxed); + goto retry; + } + } +@@ -939,10 +941,10 @@ static int uv__is_cifs_or_smb(int fd) { + + static ssize_t uv__fs_try_copy_file_range(int in_fd, off_t* off, + int out_fd, size_t len) { +- static _Atomic int no_copy_file_range_support; ++ static std::atomic no_copy_file_range_support; + ssize_t r; + +- if (atomic_load_explicit(&no_copy_file_range_support, memory_order_relaxed)) { ++ if (atomic_load_explicit(&no_copy_file_range_support, std::memory_order_relaxed)) { + errno = ENOSYS; + return -1; + } +@@ -961,7 +963,7 @@ static ssize_t uv__fs_try_copy_file_range(int in_fd, off_t* off, + errno = ENOSYS; /* Use fallback. */ + break; + case ENOSYS: +- atomic_store_explicit(&no_copy_file_range_support, 1, memory_order_relaxed); ++ atomic_store_explicit(&no_copy_file_range_support, 1, std::memory_order_relaxed); + break; + case EPERM: + /* It's been reported that CIFS spuriously fails. +@@ -1162,7 +1164,7 @@ static ssize_t uv__fs_lutime(uv_fs_t* req) { + + static ssize_t uv__fs_write(uv_fs_t* req) { + #if TRY_PREADV +- static _Atomic int no_pwritev; ++ static std::atomic no_pwritev; + #endif + ssize_t r; + +@@ -1191,7 +1193,7 @@ static ssize_t uv__fs_write(uv_fs_t* req) { + r = pwritev(req->file, (struct iovec*) req->bufs, req->nbufs, req->off); + #else + # if TRY_PREADV +- if (atomic_load_explicit(&no_pwritev, memory_order_relaxed)) retry: ++ if (atomic_load_explicit(&no_pwritev, std::memory_order_relaxed)) retry: + # endif + { + r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off); +@@ -1203,7 +1205,7 @@ static ssize_t uv__fs_write(uv_fs_t* req) { + req->nbufs, + req->off); + if (r == -1 && errno == ENOSYS) { +- atomic_store_explicit(&no_pwritev, 1, memory_order_relaxed); ++ atomic_store_explicit(&no_pwritev, 1, std::memory_order_relaxed); + goto retry; + } + } +@@ -1483,14 +1485,14 @@ static int uv__fs_statx(int fd, + uv_stat_t* buf) { + STATIC_ASSERT(UV_ENOSYS != -1); + #ifdef __linux__ +- static _Atomic int no_statx; ++ static std::atomic no_statx; + struct uv__statx statxbuf; + int dirfd; + int flags; + int mode; + int rc; + +- if (atomic_load_explicit(&no_statx, memory_order_relaxed)) ++ if (atomic_load_explicit(&no_statx, std::memory_order_relaxed)) + return UV_ENOSYS; + + dirfd = AT_FDCWD; +@@ -1524,7 +1526,7 @@ static int uv__fs_statx(int fd, + * implemented, rc might return 1 with 0 set as the error code in which + * case we return ENOSYS. + */ +- atomic_store_explicit(&no_statx, 1, memory_order_relaxed); ++ atomic_store_explicit(&no_statx, 1, std::memory_order_relaxed); + return UV_ENOSYS; + } + +diff --git a/src/unix/kqueue.c b/src/unix/kqueue.c +index 28e55aae6c613576ede7024a5c73d746e134d865..ffe0f9191cc7b0c233447db358077d8814e0217e 100644 +--- a/src/unix/kqueue.c ++++ b/src/unix/kqueue.c +@@ -34,6 +34,8 @@ + #include + #include + ++#include ++ + /* + * Required on + * - Until at least FreeBSD 11.0 +@@ -60,7 +62,7 @@ int uv__kqueue_init(uv_loop_t* loop) { + + + #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 +-static _Atomic int uv__has_forked_with_cfrunloop; ++static std::atomic uv__has_forked_with_cfrunloop; + #endif + + int uv__io_fork(uv_loop_t* loop) { +@@ -84,7 +86,7 @@ int uv__io_fork(uv_loop_t* loop) { + */ + atomic_store_explicit(&uv__has_forked_with_cfrunloop, + 1, +- memory_order_relaxed); ++ std::memory_order_relaxed); + uv__free(loop->cf_state); + loop->cf_state = NULL; + } +@@ -541,7 +543,7 @@ int uv_fs_event_start(uv_fs_event_t* handle, + goto fallback; + + if (0 == atomic_load_explicit(&uv__has_forked_with_cfrunloop, +- memory_order_relaxed)) { ++ std::memory_order_relaxed)) { + int r; + /* The fallback fd is no longer needed */ + uv__close_nocheckstdio(fd); +@@ -577,7 +579,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) { + + #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + if (0 == atomic_load_explicit(&uv__has_forked_with_cfrunloop, +- memory_order_relaxed)) ++ std::memory_order_relaxed)) + if (handle->cf_cb != NULL) + r = uv__fsevents_close(handle); + #endif +diff --git a/src/unix/linux.c b/src/unix/linux.c +index 157443792f1216c83b4221c3810d17c81c5913c4..e3dfb186dc531e5c8197a81681c00d693e0913c6 100644 +--- a/src/unix/linux.c ++++ b/src/unix/linux.c +@@ -27,7 +27,6 @@ + #include "internal.h" + + #include +-#include + #include /* offsetof */ + #include + #include +@@ -133,6 +132,8 @@ + # include + #endif /* HAVE_IFADDRS_H */ + ++#include ++ + enum { + UV__IORING_SETUP_SQPOLL = 2u, + }; +@@ -311,14 +312,14 @@ static struct watcher_root* uv__inotify_watchers(uv_loop_t* loop) { + + + unsigned uv__kernel_version(void) { +- static _Atomic unsigned cached_version; ++ static std::atomic cached_version; + struct utsname u; + unsigned version; + unsigned major; + unsigned minor; + unsigned patch; + +- version = atomic_load_explicit(&cached_version, memory_order_relaxed); ++ version = std::atomic_load_explicit(&cached_version, std::memory_order_relaxed); + if (version != 0) + return version; + +@@ -329,7 +330,7 @@ unsigned uv__kernel_version(void) { + return 0; + + version = major * 65536 + minor * 256 + patch; +- atomic_store_explicit(&cached_version, version, memory_order_relaxed); ++ std::atomic_store_explicit(&cached_version, version, std::memory_order_relaxed); + + return version; + } +@@ -424,16 +425,16 @@ static int uv__use_io_uring(void) { + return 0; /* Possibly available but blocked by seccomp. */ + #else + /* Ternary: unknown=0, yes=1, no=-1 */ +- static _Atomic int use_io_uring; ++ static std::atomic use_io_uring; + char* val; + int use; + +- use = atomic_load_explicit(&use_io_uring, memory_order_relaxed); ++ use = std::atomic_load_explicit(&use_io_uring, std::memory_order_relaxed); + + if (use == 0) { + val = getenv("UV_USE_IO_URING"); + use = val == NULL || atoi(val) ? 1 : -1; +- atomic_store_explicit(&use_io_uring, use, memory_order_relaxed); ++ std::atomic_store_explicit(&use_io_uring, use, std::memory_order_relaxed); + } + + return use > 0; +@@ -709,8 +710,8 @@ static struct uv__io_uring_sqe* uv__iou_get_sqe(struct uv__iou* iou, + if (iou->ringfd == -1) + return NULL; + +- head = atomic_load_explicit((_Atomic uint32_t*) iou->sqhead, +- memory_order_acquire); ++ head = std::atomic_load_explicit((std::atomic*) iou->sqhead, ++ std::memory_order_acquire); + tail = *iou->sqtail; + mask = iou->sqmask; + +@@ -739,12 +740,12 @@ static struct uv__io_uring_sqe* uv__iou_get_sqe(struct uv__iou* iou, + static void uv__iou_submit(struct uv__iou* iou) { + uint32_t flags; + +- atomic_store_explicit((_Atomic uint32_t*) iou->sqtail, ++ std::atomic_store_explicit((std::atomic*) iou->sqtail, + *iou->sqtail + 1, +- memory_order_release); ++ std::memory_order_release); + +- flags = atomic_load_explicit((_Atomic uint32_t*) iou->sqflags, +- memory_order_acquire); ++ flags = std::atomic_load_explicit((std::atomic*) iou->sqflags, ++ std::memory_order_acquire); + + if (flags & UV__IORING_SQ_NEED_WAKEUP) + if (uv__io_uring_enter(iou->ringfd, 0, 0, UV__IORING_ENTER_SQ_WAKEUP)) +@@ -1076,8 +1077,8 @@ static void uv__poll_io_uring(uv_loop_t* loop, struct uv__iou* iou) { + int rc; + + head = *iou->cqhead; +- tail = atomic_load_explicit((_Atomic uint32_t*) iou->cqtail, +- memory_order_acquire); ++ tail = std::atomic_load_explicit((std::atomic*) iou->cqtail, ++ std::memory_order_acquire); + mask = iou->cqmask; + cqe = (uv__io_uring_cqe*)iou->cqe; + nevents = 0; +@@ -1109,15 +1110,15 @@ static void uv__poll_io_uring(uv_loop_t* loop, struct uv__iou* iou) { + nevents++; + } + +- atomic_store_explicit((_Atomic uint32_t*) iou->cqhead, ++ std::atomic_store_explicit((std::atomic*) iou->cqhead, + tail, +- memory_order_release); ++ std::memory_order_release); + + /* Check whether CQE's overflowed, if so enter the kernel to make them + * available. Don't grab them immediately but in the next loop iteration to + * avoid loop starvation. */ +- flags = atomic_load_explicit((_Atomic uint32_t*) iou->sqflags, +- memory_order_acquire); ++ flags = std::atomic_load_explicit((std::atomic*) iou->sqflags, ++ std::memory_order_acquire); + + if (flags & UV__IORING_SQ_CQ_OVERFLOW) { + do +@@ -1531,7 +1532,7 @@ update_timeout: + } + + uint64_t uv__hrtime(uv_clocktype_t type) { +- static _Atomic clock_t fast_clock_id = -1; ++ static std::atomic fast_clock_id = -1; + struct timespec t; + clock_t clock_id; + +@@ -1547,7 +1548,7 @@ uint64_t uv__hrtime(uv_clocktype_t type) { + if (type != UV_CLOCK_FAST) + goto done; + +- clock_id = atomic_load_explicit(&fast_clock_id, memory_order_relaxed); ++ clock_id = std::atomic_load_explicit(&fast_clock_id, std::memory_order_relaxed); + if (clock_id != -1) + goto done; + +@@ -1556,7 +1557,7 @@ uint64_t uv__hrtime(uv_clocktype_t type) { + if (t.tv_nsec <= 1 * 1000 * 1000) + clock_id = CLOCK_MONOTONIC_COARSE; + +- atomic_store_explicit(&fast_clock_id, clock_id, memory_order_relaxed); ++ std::atomic_store_explicit(&fast_clock_id, clock_id, std::memory_order_relaxed); + + done: + +diff --git a/src/unix/tty.c b/src/unix/tty.c +index 1bd217b5a15eed13a8349c479b53471dd36ca216..1304c6d8685cfd122cffea066dc668d1dfc9ae02 100644 +--- a/src/unix/tty.c ++++ b/src/unix/tty.c +@@ -22,7 +22,6 @@ + #include "uv.h" + #include "internal.h" + +-#include + #include + #include + #include +@@ -30,6 +29,8 @@ + #include + #include + ++#include ++ + #if defined(__MVS__) && !defined(IMAXBEL) + #define IMAXBEL 0 + #endif +@@ -64,7 +65,7 @@ static int isreallyatty(int file) { + + static int orig_termios_fd = -1; + static struct termios orig_termios; +-static _Atomic int termios_spinlock; ++static std::atomic termios_spinlock; + + int uv__tcsetattr(int fd, int how, const struct termios *term) { + int rc; +diff --git a/src/uv-common.c b/src/uv-common.c +index bfcc3ef10f4fd7763221638947da6e02e7a17c33..5c6d84155408ae4f7c3c6ff9b48bd09ccd16a92e 100644 +--- a/src/uv-common.c ++++ b/src/uv-common.c +@@ -951,7 +951,7 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { + __attribute__((destructor)) + #endif + void uv_library_shutdown(void) { +- static int was_shutdown; ++ static std::atomic was_shutdown; + + if (uv__exchange_int_relaxed(&was_shutdown, 1)) + return; +diff --git a/src/uv-common.h b/src/uv-common.h +index cd57e5a35153d0557351b60cce0c5be7a4468b60..5dce8eaf2705b47935b218181f6dd69af0d5b61b 100644 +--- a/src/uv-common.h ++++ b/src/uv-common.h +@@ -32,15 +32,13 @@ + #include + #include + ++#include ++ + #include "uv.h" + #include "uv/tree.h" + #include "queue.h" + #include "strscpy.h" + +-#ifndef _MSC_VER +-# include +-#endif +- + #if EDOM > 0 + # define UV__ERR(x) (-(x)) + #else +@@ -70,7 +68,7 @@ extern int snprintf(char*, size_t, const char*, ...); + InterlockedExchangeNoFence((LONG volatile*)(p), v) + #else + #define uv__exchange_int_relaxed(p, v) \ +- atomic_exchange_explicit((_Atomic int*)(p), v, memory_order_relaxed) ++ std::atomic_exchange_explicit((std::atomic*)(p), v, std::memory_order_relaxed) + #endif + + #define UV__UDP_DGRAM_MAXSIZE (64 * 1024) diff --git a/upstream_utils/libuv_patches/0008-Remove-static-from-array-indices.patch b/upstream_utils/libuv_patches/0008-Remove-static-from-array-indices.patch new file mode 100644 index 00000000000..7fddff8389d --- /dev/null +++ b/upstream_utils/libuv_patches/0008-Remove-static-from-array-indices.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tyler Veness +Date: Thu, 13 Jul 2023 23:30:58 -0700 +Subject: [PATCH 8/9] Remove static from array indices + +--- + src/unix/linux.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/src/unix/linux.c b/src/unix/linux.c +index e3dfb186dc531e5c8197a81681c00d693e0913c6..d365b623a0a25228f0c6acf1fa14a5c7a9f1efbf 100644 +--- a/src/unix/linux.c ++++ b/src/unix/linux.c +@@ -2060,7 +2060,7 @@ static uint64_t uv__read_uint64(const char* filename) { + * finds the location and length of the memory controller mount path. + * This disregards the leading / for easy concatenation of paths. + * Returns NULL if the memory controller wasn't found. */ +-static char* uv__cgroup1_find_memory_controller(char buf[static 1024], ++static char* uv__cgroup1_find_memory_controller(char buf[1024], + int* n) { + char* p; + +@@ -2081,7 +2081,7 @@ static char* uv__cgroup1_find_memory_controller(char buf[static 1024], + return p; + } + +-static void uv__get_cgroup1_memory_limits(char buf[static 1024], uint64_t* high, ++static void uv__get_cgroup1_memory_limits(char buf[1024], uint64_t* high, + uint64_t* max) { + char filename[4097]; + char* p; +@@ -2121,7 +2121,7 @@ update_limits: + *max = UINT64_MAX; + } + +-static void uv__get_cgroup2_memory_limits(char buf[static 1024], uint64_t* high, ++static void uv__get_cgroup2_memory_limits(char buf[1024], uint64_t* high, + uint64_t* max) { + char filename[4097]; + char* p; +@@ -2138,7 +2138,7 @@ static void uv__get_cgroup2_memory_limits(char buf[static 1024], uint64_t* high, + *high = uv__read_uint64(filename); + } + +-static uint64_t uv__get_cgroup_constrained_memory(char buf[static 1024]) { ++static uint64_t uv__get_cgroup_constrained_memory(char buf[1024]) { + uint64_t high; + uint64_t max; + +@@ -2164,7 +2164,7 @@ uint64_t uv_get_constrained_memory(void) { + } + + +-static uint64_t uv__get_cgroup1_current_memory(char buf[static 1024]) { ++static uint64_t uv__get_cgroup1_current_memory(char buf[1024]) { + char filename[4097]; + uint64_t current; + char* p; +@@ -2188,7 +2188,7 @@ static uint64_t uv__get_cgroup1_current_memory(char buf[static 1024]) { + return uv__read_uint64("/sys/fs/cgroup/memory/memory.usage_in_bytes"); + } + +-static uint64_t uv__get_cgroup2_current_memory(char buf[static 1024]) { ++static uint64_t uv__get_cgroup2_current_memory(char buf[1024]) { + char filename[4097]; + char* p; + int n; diff --git a/upstream_utils/libuv_patches/0009-Avoid-unused-variable-warning-on-Mac.patch b/upstream_utils/libuv_patches/0009-Avoid-unused-variable-warning-on-Mac.patch deleted file mode 100644 index 5d2b8ddb3c5..00000000000 --- a/upstream_utils/libuv_patches/0009-Avoid-unused-variable-warning-on-Mac.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Johnson -Date: Sun, 5 Jun 2022 15:40:35 -0700 -Subject: [PATCH 09/10] Avoid unused variable warning on Mac - ---- - src/unix/darwin.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/unix/darwin.c b/src/unix/darwin.c -index eeb35720f55bf26363a064443bd02fb9aae682a4..ed51a6ad61ca70b06c5e3c5b3a12f1109ac47083 100644 ---- a/src/unix/darwin.c -+++ b/src/unix/darwin.c -@@ -257,6 +257,7 @@ static int uv__get_cpu_speed(uint64_t* speed) { - // clock_frequency_str's lifetimes after their initialization - { - kr = pIOMasterPort(MACH_PORT_NULL, &mach_port); -+ (void) kr; - assert(kr == KERN_SUCCESS); - CFMutableDictionaryRef classes_to_match - = pIOServiceMatching("IOPlatformDevice"); diff --git a/upstream_utils/libuv_patches/0009-Fix-undefined-GetSystemTimePreciseAsFileTime-Win32-f.patch b/upstream_utils/libuv_patches/0009-Fix-undefined-GetSystemTimePreciseAsFileTime-Win32-f.patch new file mode 100644 index 00000000000..24cac3ecb31 --- /dev/null +++ b/upstream_utils/libuv_patches/0009-Fix-undefined-GetSystemTimePreciseAsFileTime-Win32-f.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Tyler Veness +Date: Fri, 14 Jul 2023 15:05:50 -0700 +Subject: [PATCH 9/9] Fix undefined GetSystemTimePreciseAsFileTime() Win32 + function + +--- + src/win/util.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/win/util.c b/src/win/util.c +index 9324992ec521cc3496e3e9304e600963a3f20897..55ca35d31694c512201a50129df54b8eb48364ef 100644 +--- a/src/win/util.c ++++ b/src/win/util.c +@@ -31,7 +31,6 @@ + #include "internal.h" + + /* clang-format off */ +-#include + #include + #include + #include diff --git a/upstream_utils/libuv_patches/0010-Squelch-Apple-Clang-sprintf-deprecation-warning.patch b/upstream_utils/libuv_patches/0010-Squelch-Apple-Clang-sprintf-deprecation-warning.patch deleted file mode 100644 index a6e437746d5..00000000000 --- a/upstream_utils/libuv_patches/0010-Squelch-Apple-Clang-sprintf-deprecation-warning.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tyler Veness -Date: Wed, 7 Jun 2023 21:04:19 -0700 -Subject: [PATCH 10/10] Squelch Apple Clang sprintf deprecation warning - ---- - src/inet.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/src/inet.c b/src/inet.c -index 1b190255ed5f4813428dbb3ba81a50cfd26c5bf1..57e5c042ef8adb880279f94bcccc70f78df338fc 100644 ---- a/src/inet.c -+++ b/src/inet.c -@@ -139,7 +139,14 @@ static int inet_ntop6(const unsigned char *src, char *dst, size_t size) { - tp += strlen(tp); - break; - } -+#if defined(__APPLE__) && defined(__clang__) -+#pragma clang diagnostic push -+#pragma clang diagnostic ignored "-Wdeprecated-declarations" -+#endif // defined(__APPLE__) && defined(__clang__) - tp += sprintf(tp, "%x", words[i]); -+#if defined(__APPLE__) && defined(__clang__) -+#pragma clang diagnostic pop -+#endif // defined(__APPLE__) && defined(__clang__) - } - /* Was it a trailing run of 0x00's? */ - if (best.base != -1 && (best.base + best.len) == ARRAY_SIZE(words)) diff --git a/upstream_utils/update_libuv.py b/upstream_utils/update_libuv.py index 68e132da796..8dbaf9f160c 100755 --- a/upstream_utils/update_libuv.py +++ b/upstream_utils/update_libuv.py @@ -13,7 +13,7 @@ def main(): - upstream_root = clone_repo("https://github.com/libuv/libuv", "v1.44.2") + upstream_root = clone_repo("https://github.com/libuv/libuv", "v1.46.0") wpilib_root = get_repo_root() wpinet = os.path.join(wpilib_root, "wpinet") @@ -24,12 +24,11 @@ def main(): "0002-Fix-warnings.patch", "0003-Preprocessor-cleanup.patch", "0004-Cleanup-problematic-language.patch", - "0005-Use-roborio-time.patch", - "0006-Style-comments-cleanup.patch", - "0007-Squelch-GCC-warnings-we-don-t-know-how-to-fix.patch", - "0008-Fix-Win32-warning-suppression-pragma.patch", - "0009-Avoid-unused-variable-warning-on-Mac.patch", - "0010-Squelch-Apple-Clang-sprintf-deprecation-warning.patch", + "0005-Style-comments-cleanup.patch", + "0006-Fix-Win32-warning-suppression-pragma.patch", + "0007-Use-C-atomics.patch", + "0008-Remove-static-from-array-indices.patch", + "0009-Fix-undefined-GetSystemTimePreciseAsFileTime-Win32-f.patch", ]: git_am(os.path.join(wpilib_root, "upstream_utils/libuv_patches", f)) diff --git a/wpinet/CMakeLists.txt b/wpinet/CMakeLists.txt index 3da7bf0c512..2e7cda574d5 100644 --- a/wpinet/CMakeLists.txt +++ b/wpinet/CMakeLists.txt @@ -108,10 +108,7 @@ set(uv_darwin_src ) set(uv_linux_src - src/main/native/thirdparty/libuv/src/unix/epoll.cpp - src/main/native/thirdparty/libuv/src/unix/linux-core.cpp - src/main/native/thirdparty/libuv/src/unix/linux-inotify.cpp - src/main/native/thirdparty/libuv/src/unix/linux-syscalls.cpp + src/main/native/thirdparty/libuv/src/unix/linux.cpp src/main/native/thirdparty/libuv/src/unix/procfs-exepath.cpp src/main/native/thirdparty/libuv/src/unix/proctitle.cpp src/main/native/thirdparty/libuv/src/unix/random-sysctl-linux.cpp diff --git a/wpinet/build.gradle b/wpinet/build.gradle index b1496756618..d79d3590782 100644 --- a/wpinet/build.gradle +++ b/wpinet/build.gradle @@ -147,10 +147,7 @@ ext { source { srcDirs 'src/main/native/thirdparty/libuv/src/unix' includes = [ - 'epoll.cpp', - 'linux-core.cpp', - 'linux-inotify.cpp', - 'linux-syscalls.cpp', + 'linux.cpp', 'procfs-exepath.cpp', 'proctitle.cpp', 'random-sysctl-linux.cpp', diff --git a/wpinet/src/main/native/thirdparty/libuv/include/uv.h b/wpinet/src/main/native/thirdparty/libuv/include/uv.h index dbaeb1e9dcc..d5342b0d522 100644 --- a/wpinet/src/main/native/thirdparty/libuv/include/uv.h +++ b/wpinet/src/main/native/thirdparty/libuv/include/uv.h @@ -28,6 +28,7 @@ #error "Define either BUILDING_UV_SHARED or USING_UV_SHARED, not both." #endif +#ifndef UV_EXTERN #ifdef _WIN32 /* Windows - set up dll import/export decorators. */ # if defined(BUILDING_UV_SHARED) @@ -47,14 +48,20 @@ #else # define UV_EXTERN /* nothing */ #endif +#endif /* UV_EXTERN */ #include "uv/errno.h" #include "uv/version.h" #include #include - #include +/* Internal type, do not use. */ +struct uv__queue { + struct uv__queue* next; + struct uv__queue* prev; +}; + #if defined(_WIN32) # include "uv/win.h" #else @@ -145,6 +152,8 @@ XX(EFTYPE, "inappropriate file type or format") \ XX(EILSEQ, "illegal byte sequence") \ XX(ESOCKTNOSUPPORT, "socket type not supported") \ + XX(ENODATA, "no data available") \ + XX(EUNATCH, "protocol driver not attached") \ #define UV_HANDLE_TYPE_MAP(XX) \ XX(ASYNC, async) \ @@ -240,9 +249,12 @@ typedef struct uv_cpu_info_s uv_cpu_info_t; typedef struct uv_interface_address_s uv_interface_address_t; typedef struct uv_dirent_s uv_dirent_t; typedef struct uv_passwd_s uv_passwd_t; +typedef struct uv_group_s uv_group_t; typedef struct uv_utsname_s uv_utsname_t; typedef struct uv_statfs_s uv_statfs_t; +typedef struct uv_metrics_s uv_metrics_t; + typedef enum { UV_LOOP_BLOCK_SIGNAL = 0, UV_METRICS_IDLE_TIME @@ -275,13 +287,13 @@ 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 + * This function is DEPRECATED, users should * allocate the loop manually and use uv_loop_init instead. */ UV_EXTERN uv_loop_t* uv_loop_new(void); /* * NOTE: - * This function is DEPRECATED (to be removed after 0.12). Users should use + * This function is DEPRECATED. Users should use * uv_loop_close and free the memory manually instead. */ UV_EXTERN void uv_loop_delete(uv_loop_t*); @@ -337,11 +349,32 @@ typedef void (*uv_random_cb)(uv_random_t* req, void* buf, size_t buflen); +typedef enum { + UV_CLOCK_MONOTONIC, + UV_CLOCK_REALTIME +} uv_clock_id; + +/* XXX(bnoordhuis) not 2038-proof, https://github.com/libuv/libuv/issues/3864 */ typedef struct { long tv_sec; long tv_nsec; } uv_timespec_t; +typedef struct { + int64_t tv_sec; + int32_t tv_nsec; +} uv_timespec64_t; + +/* XXX(bnoordhuis) not 2038-proof, https://github.com/libuv/libuv/issues/3864 */ +typedef struct { + long tv_sec; + long tv_usec; +} uv_timeval_t; + +typedef struct { + int64_t tv_sec; + int32_t tv_usec; +} uv_timeval64_t; typedef struct { uint64_t st_dev; @@ -430,7 +463,7 @@ struct uv_shutdown_s { uv_handle_type type; \ /* private */ \ uv_close_cb close_cb; \ - void* handle_queue[2]; \ + struct uv__queue handle_queue; \ union { \ int fd; \ void* reserved[4]; \ @@ -766,6 +799,10 @@ inline int uv_tty_set_mode(uv_tty_t* handle, int mode) { UV_EXTERN uv_handle_type uv_guess_handle(uv_file file); +enum { + UV_PIPE_NO_TRUNCATE = 1u << 0 +}; + /* * uv_pipe_t is a subclass of uv_stream_t. * @@ -782,10 +819,20 @@ struct uv_pipe_s { UV_EXTERN int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc); UV_EXTERN int uv_pipe_open(uv_pipe_t*, uv_file file); UV_EXTERN int uv_pipe_bind(uv_pipe_t* handle, const char* name); +UV_EXTERN int uv_pipe_bind2(uv_pipe_t* handle, + const char* name, + size_t namelen, + unsigned int flags); UV_EXTERN void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb); +UV_EXTERN int uv_pipe_connect2(uv_connect_t* req, + uv_pipe_t* handle, + const char* name, + size_t namelen, + unsigned int flags, + uv_connect_cb cb); UV_EXTERN int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size); @@ -1126,6 +1173,12 @@ struct uv_passwd_s { char* homedir; }; +struct uv_group_s { + char* groupname; + unsigned long gid; + char** members; +}; + struct uv_utsname_s { char sysname[256]; char release[256]; @@ -1171,16 +1224,6 @@ UV_EXTERN int uv_uptime(double* uptime); UV_EXTERN uv_os_fd_t uv_get_osfhandle(int fd); UV_EXTERN int uv_open_osfhandle(uv_os_fd_t os_fd); -typedef struct { - long tv_sec; - long tv_usec; -} uv_timeval_t; - -typedef struct { - int64_t tv_sec; - int32_t tv_usec; -} uv_timeval64_t; - typedef struct { uv_timeval_t ru_utime; /* user CPU time used */ uv_timeval_t ru_stime; /* system CPU time used */ @@ -1206,6 +1249,9 @@ UV_EXTERN int uv_os_homedir(char* buffer, size_t* size); UV_EXTERN int uv_os_tmpdir(char* buffer, size_t* size); UV_EXTERN int uv_os_get_passwd(uv_passwd_t* pwd); UV_EXTERN void uv_os_free_passwd(uv_passwd_t* pwd); +UV_EXTERN int uv_os_get_passwd2(uv_passwd_t* pwd, uv_uid_t uid); +UV_EXTERN int uv_os_get_group(uv_group_t* grp, uv_uid_t gid); +UV_EXTERN void uv_os_free_group(uv_group_t* grp); UV_EXTERN uv_pid_t uv_os_getpid(void); UV_EXTERN uv_pid_t uv_os_getppid(void); @@ -1232,6 +1278,7 @@ UV_EXTERN int uv_os_setpriority(uv_pid_t pid, int priority); UV_EXTERN unsigned int uv_available_parallelism(void); UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count); UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count); +UV_EXTERN int uv_cpumask_size(void); UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses, int* count); @@ -1264,6 +1311,15 @@ UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size); UV_EXTERN int uv_os_uname(uv_utsname_t* buffer); +struct uv_metrics_s { + uint64_t loop_count; + uint64_t events; + uint64_t events_waiting; + /* private */ + uint64_t* reserved[13]; +}; + +UV_EXTERN int uv_metrics_info(uv_loop_t* loop, uv_metrics_t* metrics); UV_EXTERN uint64_t uv_metrics_idle_time(uv_loop_t* loop); typedef enum { @@ -1697,7 +1753,9 @@ UV_EXTERN int uv_chdir(const char* dir); UV_EXTERN uint64_t uv_get_free_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_get_available_memory(void); +UV_EXTERN int uv_clock_gettime(uv_clock_id clock_id, uv_timespec64_t* ts); UV_EXTERN uint64_t uv_hrtime(void); UV_EXTERN void uv_sleep(unsigned int msec); @@ -1774,6 +1832,14 @@ 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 int uv_thread_setaffinity(uv_thread_t* tid, + char* cpumask, + char* oldmask, + size_t mask_size); +UV_EXTERN int uv_thread_getaffinity(uv_thread_t* tid, + char* cpumask, + size_t mask_size); +UV_EXTERN int uv_thread_getcpu(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_equal(const uv_thread_t* t1, const uv_thread_t* t2); @@ -1795,7 +1861,7 @@ struct uv_loop_s { void* data; /* Loop reference counting. */ unsigned int active_handles; - void* handle_queue[2]; + struct uv__queue handle_queue; union { void* unused; unsigned int count; diff --git a/wpinet/src/main/native/thirdparty/libuv/include/uv/darwin.h b/wpinet/src/main/native/thirdparty/libuv/include/uv/darwin.h index d226415820b..06962bfda80 100644 --- a/wpinet/src/main/native/thirdparty/libuv/include/uv/darwin.h +++ b/wpinet/src/main/native/thirdparty/libuv/include/uv/darwin.h @@ -40,7 +40,7 @@ void* cf_state; \ uv_mutex_t cf_mutex; \ uv_sem_t cf_sem; \ - void* cf_signals[2]; \ + struct uv__queue cf_signals; \ #define UV_PLATFORM_FS_EVENT_FIELDS \ uv__io_t event_watcher; \ @@ -48,8 +48,8 @@ int realpath_len; \ int cf_flags; \ uv_async_t* cf_cb; \ - void* cf_events[2]; \ - void* cf_member[2]; \ + struct uv__queue cf_events; \ + struct uv__queue cf_member; \ int cf_error; \ uv_mutex_t cf_mutex; \ diff --git a/wpinet/src/main/native/thirdparty/libuv/include/uv/errno.h b/wpinet/src/main/native/thirdparty/libuv/include/uv/errno.h index 71906b3f5e6..127278ef916 100644 --- a/wpinet/src/main/native/thirdparty/libuv/include/uv/errno.h +++ b/wpinet/src/main/native/thirdparty/libuv/include/uv/errno.h @@ -413,7 +413,6 @@ #elif defined(__APPLE__) || \ defined(__DragonFly__) || \ defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || \ defined(__NetBSD__) || \ defined(__OpenBSD__) # define UV__EHOSTDOWN (-64) @@ -457,4 +456,22 @@ # define UV__ESOCKTNOSUPPORT (-4025) #endif +/* FreeBSD defines ENODATA in /usr/include/c++/v1/errno.h which is only visible + * if C++ is being used. Define it directly to avoid problems when integrating + * libuv in a C++ project. + */ +#if defined(ENODATA) && !defined(_WIN32) +# define UV__ENODATA UV__ERR(ENODATA) +#elif defined(__FreeBSD__) +# define UV__ENODATA (-9919) +#else +# define UV__ENODATA (-4024) +#endif + +#if defined(EUNATCH) && !defined(_WIN32) +# define UV__EUNATCH UV__ERR(EUNATCH) +#else +# define UV__EUNATCH (-4023) +#endif + #endif /* UV_ERRNO_H_ */ diff --git a/wpinet/src/main/native/thirdparty/libuv/include/uv/linux.h b/wpinet/src/main/native/thirdparty/libuv/include/uv/linux.h index 9b38405a190..9f22f8cf726 100644 --- a/wpinet/src/main/native/thirdparty/libuv/include/uv/linux.h +++ b/wpinet/src/main/native/thirdparty/libuv/include/uv/linux.h @@ -28,7 +28,7 @@ int inotify_fd; \ #define UV_PLATFORM_FS_EVENT_FIELDS \ - void* watchers[2]; \ + struct uv__queue watchers; \ int wd; \ #endif /* UV_LINUX_H */ diff --git a/wpinet/src/main/native/thirdparty/libuv/include/uv/threadpool.h b/wpinet/src/main/native/thirdparty/libuv/include/uv/threadpool.h index 9708ebdd530..24ce916fda4 100644 --- a/wpinet/src/main/native/thirdparty/libuv/include/uv/threadpool.h +++ b/wpinet/src/main/native/thirdparty/libuv/include/uv/threadpool.h @@ -31,7 +31,7 @@ struct uv__work { void (*work)(struct uv__work *w); void (*done)(struct uv__work *w, int status); struct uv_loop_s* loop; - void* wq[2]; + struct uv__queue wq; }; #endif /* UV_THREADPOOL_H_ */ diff --git a/wpinet/src/main/native/thirdparty/libuv/include/uv/unix.h b/wpinet/src/main/native/thirdparty/libuv/include/uv/unix.h index 256fef37692..e334cabe028 100644 --- a/wpinet/src/main/native/thirdparty/libuv/include/uv/unix.h +++ b/wpinet/src/main/native/thirdparty/libuv/include/uv/unix.h @@ -51,7 +51,6 @@ # include "uv/darwin.h" #elif defined(__DragonFly__) || \ defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || \ defined(__OpenBSD__) || \ defined(__NetBSD__) # include "uv/bsd.h" @@ -85,8 +84,8 @@ typedef struct uv__io_s uv__io_t; struct uv__io_s { uv__io_cb cb; - void* pending_queue[2]; - void* watcher_queue[2]; + struct uv__queue pending_queue; + struct uv__queue watcher_queue; unsigned int pevents; /* Pending event mask i.e. mask at next tick. */ unsigned int events; /* Current event mask. */ int fd; @@ -213,21 +212,21 @@ typedef struct { #define UV_LOOP_PRIVATE_FIELDS \ unsigned long flags; \ int backend_fd; \ - void* pending_queue[2]; \ - void* watcher_queue[2]; \ - void** watchers; \ + struct uv__queue pending_queue; \ + struct uv__queue watcher_queue; \ + uv__io_t** watchers; \ unsigned int nwatchers; \ unsigned int nfds; \ - void* wq[2]; \ + struct uv__queue wq; \ uv_mutex_t wq_mutex; \ uv_async_t wq_async; \ uv_rwlock_t cloexec_lock; \ uv_handle_t* closing_handles; \ - void* process_handles[2]; \ - void* prepare_handles[2]; \ - void* check_handles[2]; \ - void* idle_handles[2]; \ - void* async_handles[2]; \ + struct uv__queue process_handles; \ + struct uv__queue prepare_handles; \ + struct uv__queue check_handles; \ + struct uv__queue idle_handles; \ + struct uv__queue async_handles; \ void (*async_unused)(void); /* TODO(bnoordhuis) Remove in libuv v2. */ \ uv__io_t async_io_watcher; \ int async_wfd; \ @@ -250,7 +249,7 @@ typedef struct { #define UV_PRIVATE_REQ_TYPES /* empty */ #define UV_WRITE_PRIVATE_FIELDS \ - void* queue[2]; \ + struct uv__queue queue; \ unsigned int write_index; \ uv_buf_t* bufs; \ unsigned int nbufs; \ @@ -258,12 +257,12 @@ typedef struct { uv_buf_t bufsml[4]; \ #define UV_CONNECT_PRIVATE_FIELDS \ - void* queue[2]; \ + struct uv__queue queue; \ #define UV_SHUTDOWN_PRIVATE_FIELDS /* empty */ #define UV_UDP_SEND_PRIVATE_FIELDS \ - void* queue[2]; \ + struct uv__queue queue; \ struct sockaddr_storage addr; \ unsigned int nbufs; \ uv_buf_t* bufs; \ @@ -279,8 +278,8 @@ typedef struct { uv_connect_t *connect_req; \ uv_shutdown_t *shutdown_req; \ uv__io_t io_watcher; \ - void* write_queue[2]; \ - void* write_completed_queue[2]; \ + struct uv__queue write_queue; \ + struct uv__queue write_completed_queue; \ uv_connection_cb connection_cb; \ int delayed_error; \ int accepted_fd; \ @@ -293,30 +292,30 @@ typedef struct { uv_alloc_cb alloc_cb; \ uv_udp_recv_cb recv_cb; \ uv__io_t io_watcher; \ - void* write_queue[2]; \ - void* write_completed_queue[2]; \ + struct uv__queue write_queue; \ + struct uv__queue write_completed_queue; \ #define UV_PIPE_PRIVATE_FIELDS \ - const char* pipe_fname; /* strdup'ed */ + const char* pipe_fname; /* NULL or strdup'ed */ #define UV_POLL_PRIVATE_FIELDS \ uv__io_t io_watcher; #define UV_PREPARE_PRIVATE_FIELDS \ uv_prepare_cb prepare_cb; \ - void* queue[2]; \ + struct uv__queue queue; \ #define UV_CHECK_PRIVATE_FIELDS \ uv_check_cb check_cb; \ - void* queue[2]; \ + struct uv__queue queue; \ #define UV_IDLE_PRIVATE_FIELDS \ uv_idle_cb idle_cb; \ - void* queue[2]; \ + struct uv__queue queue; \ #define UV_ASYNC_PRIVATE_FIELDS \ uv_async_cb async_cb; \ - void* queue[2]; \ + struct uv__queue queue; \ int pending; \ #define UV_TIMER_PRIVATE_FIELDS \ @@ -345,7 +344,7 @@ typedef struct { int retcode; #define UV_PROCESS_PRIVATE_FIELDS \ - void* queue[2]; \ + struct uv__queue queue; \ int status; \ #define UV_FS_PRIVATE_FIELDS \ @@ -410,6 +409,8 @@ typedef struct { # define UV_FS_O_DIRECT 0x04000 #elif defined(__linux__) && defined(__x86_64__) # define UV_FS_O_DIRECT 0x04000 +#elif defined(__linux__) && defined(__loongarch__) +# define UV_FS_O_DIRECT 0x04000 #elif defined(O_DIRECT) # define UV_FS_O_DIRECT O_DIRECT #else diff --git a/wpinet/src/main/native/thirdparty/libuv/include/uv/version.h b/wpinet/src/main/native/thirdparty/libuv/include/uv/version.h index 9c9d292f695..24fac8d8aa7 100644 --- a/wpinet/src/main/native/thirdparty/libuv/include/uv/version.h +++ b/wpinet/src/main/native/thirdparty/libuv/include/uv/version.h @@ -31,8 +31,8 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 44 -#define UV_VERSION_PATCH 2 +#define UV_VERSION_MINOR 46 +#define UV_VERSION_PATCH 0 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/wpinet/src/main/native/thirdparty/libuv/include/uv/win.h b/wpinet/src/main/native/thirdparty/libuv/include/uv/win.h index 0a33366f3f4..c5473c2b826 100644 --- a/wpinet/src/main/native/thirdparty/libuv/include/uv/win.h +++ b/wpinet/src/main/native/thirdparty/libuv/include/uv/win.h @@ -59,7 +59,6 @@ typedef struct pollfd { #include #include #include - #include #include "uv/tree.h" @@ -71,6 +70,11 @@ typedef struct pollfd { # define S_IFLNK 0xA000 #endif +// Define missing in Windows Kit Include\{VERSION}\ucrt\sys\stat.h +#if defined(_CRT_INTERNAL_NONSTDC_NAMES) && _CRT_INTERNAL_NONSTDC_NAMES && !defined(S_IFIFO) +# define S_IFIFO _S_IFIFO +#endif + /* Additional signals supported by uv_signal and or uv_kill. The CRT defines * the following signals already: * @@ -87,6 +91,7 @@ typedef struct pollfd { * variants (Linux and Darwin) */ #define SIGHUP 1 +#define SIGQUIT 3 #define SIGKILL 9 #define SIGWINCH 28 @@ -275,11 +280,12 @@ typedef struct { } uv_rwlock_t; typedef struct { - unsigned int n; - unsigned int count; + unsigned threshold; + unsigned in; uv_mutex_t mutex; - uv_sem_t turnstile1; - uv_sem_t turnstile2; + /* TODO: in v2 make this a uv_cond_t, without unused_ */ + CONDITION_VARIABLE cond; + unsigned out; } uv_barrier_t; typedef struct { @@ -349,14 +355,14 @@ typedef struct { uv_idle_t* next_idle_handle; \ /* This handle holds the peer sockets for the fast variant of uv_poll_t */ \ SOCKET poll_peer_sockets[UV_MSAFD_PROVIDER_COUNT]; \ - /* Counter to keep track of active tcp streams */ \ + /* No longer used. */ \ unsigned int active_tcp_streams; \ - /* Counter to keep track of active udp streams */ \ + /* No longer used. */ \ unsigned int active_udp_streams; \ /* Counter to started timer */ \ uint64_t timer_counter; \ /* Threadpool */ \ - void* wq[2]; \ + struct uv__queue wq; \ uv_mutex_t wq_mutex; \ uv_async_t wq_async; @@ -383,6 +389,7 @@ typedef struct { ULONG_PTR result; /* overlapped.Internal is reused to hold the result */\ HANDLE pipeHandle; \ DWORD duplex_flags; \ + WCHAR* name; \ } connect; \ } u; \ struct uv_req_s* next_req; @@ -484,7 +491,7 @@ typedef struct { uint32_t payload_remaining; \ uint64_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \ } ipc_data_frame; \ - void* ipc_xfer_queue[2]; \ + struct uv__queue ipc_xfer_queue; \ int ipc_xfer_queue_length; \ uv_write_t* non_overlapped_writes_tail; \ CRITICAL_SECTION readfile_thread_lock; \ @@ -498,7 +505,7 @@ typedef struct { struct { uv_pipe_connection_fields } conn; \ } pipe; -/* TODO: put the parser states in an union - TTY handles are always half-duplex +/* TODO: put the parser states in a union - TTY handles are always half-duplex * so read-state can safely overlap write-state. */ #define UV_TTY_PRIVATE_FIELDS \ HANDLE handle; \ @@ -606,7 +613,7 @@ typedef struct { struct uv_process_exit_s { \ UV_REQ_FIELDS \ } exit_req; \ - BYTE* child_stdio_buffer; \ + void* unused; /* TODO: retained for ABI compat; remove this in v2.x. */ \ int exit_signal; \ HANDLE wait_handle; \ HANDLE process_handle; \ diff --git a/wpinet/src/main/native/thirdparty/libuv/src/inet.cpp b/wpinet/src/main/native/thirdparty/libuv/src/inet.cpp index 57e5c042ef8..71c9e5b774d 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/inet.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/inet.cpp @@ -17,12 +17,7 @@ #include #include - -#if defined(_MSC_VER) && _MSC_VER < 1600 -# include "uv/stdint-msvc2008.h" -#else -# include -#endif +#include #include "uv.h" #include "uv-common.h" @@ -139,14 +134,7 @@ static int inet_ntop6(const unsigned char *src, char *dst, size_t size) { tp += strlen(tp); break; } -#if defined(__APPLE__) && defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" -#endif // defined(__APPLE__) && defined(__clang__) - tp += sprintf(tp, "%x", words[i]); -#if defined(__APPLE__) && defined(__clang__) -#pragma clang diagnostic pop -#endif // defined(__APPLE__) && defined(__clang__) + tp += snprintf(tp, sizeof tmp - (tp - tmp), "%x", words[i]); } /* Was it a trailing run of 0x00's? */ if (best.base != -1 && (best.base + best.len) == ARRAY_SIZE(words)) diff --git a/wpinet/src/main/native/thirdparty/libuv/src/queue.h b/wpinet/src/main/native/thirdparty/libuv/src/queue.h index c0d5efc187c..5f8489e9bc5 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/queue.h +++ b/wpinet/src/main/native/thirdparty/libuv/src/queue.h @@ -18,107 +18,73 @@ #include -typedef void *QUEUE[2]; - -/* Private macros. */ -#define QUEUE_NEXT(q) (*(QUEUE **) &((*(q))[0])) -#define QUEUE_PREV(q) (*(QUEUE **) &((*(q))[1])) -#define QUEUE_PREV_NEXT(q) (QUEUE_NEXT(QUEUE_PREV(q))) -#define QUEUE_NEXT_PREV(q) (QUEUE_PREV(QUEUE_NEXT(q))) - -/* Public macros. */ -#define QUEUE_DATA(ptr, type, field) \ - ((type *) ((char *) (ptr) - offsetof(type, field))) - -/* Important note: mutating the list while QUEUE_FOREACH is - * iterating over its elements results in undefined behavior. - */ -#define QUEUE_FOREACH(q, h) \ - for ((q) = QUEUE_NEXT(h); (q) != (h); (q) = QUEUE_NEXT(q)) - -#define QUEUE_EMPTY(q) \ - ((const QUEUE *) (q) == (const QUEUE *) QUEUE_NEXT(q)) - -#define QUEUE_HEAD(q) \ - (QUEUE_NEXT(q)) - -#define QUEUE_INIT(q) \ - do { \ - QUEUE_NEXT(q) = (q); \ - QUEUE_PREV(q) = (q); \ - } \ - while (0) - -#define QUEUE_ADD(h, n) \ - do { \ - QUEUE_PREV_NEXT(h) = QUEUE_NEXT(n); \ - QUEUE_NEXT_PREV(n) = QUEUE_PREV(h); \ - QUEUE_PREV(h) = QUEUE_PREV(n); \ - QUEUE_PREV_NEXT(h) = (h); \ - } \ - while (0) - -#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 12 -#define QUEUE_SPLIT(h, q, n) \ - do { \ - QUEUE_PREV(n) = QUEUE_PREV(h); \ - QUEUE_PREV_NEXT(n) = (n); \ - QUEUE_NEXT(n) = (q); \ - QUEUE_PREV(h) = QUEUE_PREV(q); \ - QUEUE_PREV_NEXT(h) = (h); \ - _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored \"-Wdangling-pointer=\"") \ - QUEUE_PREV(q) = (n); \ - _Pragma("GCC diagnostic pop") \ - } \ - while (0) -#else -#define QUEUE_SPLIT(h, q, n) \ - do { \ - QUEUE_PREV(n) = QUEUE_PREV(h); \ - QUEUE_PREV_NEXT(n) = (n); \ - QUEUE_NEXT(n) = (q); \ - QUEUE_PREV(h) = QUEUE_PREV(q); \ - QUEUE_PREV_NEXT(h) = (h); \ - QUEUE_PREV(q) = (n); \ - } \ - while (0) -#endif // defined(__GNUC__) && !defined(__clang__) - -#define QUEUE_MOVE(h, n) \ - do { \ - if (QUEUE_EMPTY(h)) \ - QUEUE_INIT(n); \ - else { \ - QUEUE* q = QUEUE_HEAD(h); \ - QUEUE_SPLIT(h, q, n); \ - } \ - } \ - while (0) - -#define QUEUE_INSERT_HEAD(h, q) \ - do { \ - QUEUE_NEXT(q) = QUEUE_NEXT(h); \ - QUEUE_PREV(q) = (h); \ - QUEUE_NEXT_PREV(q) = (q); \ - QUEUE_NEXT(h) = (q); \ - } \ - while (0) - -#define QUEUE_INSERT_TAIL(h, q) \ - do { \ - QUEUE_NEXT(q) = (h); \ - QUEUE_PREV(q) = QUEUE_PREV(h); \ - QUEUE_PREV_NEXT(q) = (q); \ - QUEUE_PREV(h) = (q); \ - } \ - while (0) - -#define QUEUE_REMOVE(q) \ - do { \ - QUEUE_PREV_NEXT(q) = QUEUE_NEXT(q); \ - QUEUE_NEXT_PREV(q) = QUEUE_PREV(q); \ - } \ - while (0) +#define uv__queue_data(pointer, type, field) \ + ((type*) ((char*) (pointer) - offsetof(type, field))) + +#define uv__queue_foreach(q, h) \ + for ((q) = (h)->next; (q) != (h); (q) = (q)->next) + +static inline void uv__queue_init(struct uv__queue* q) { + q->next = q; + q->prev = q; +} + +static inline int uv__queue_empty(const struct uv__queue* q) { + return q == q->next; +} + +static inline struct uv__queue* uv__queue_head(const struct uv__queue* q) { + return q->next; +} + +static inline struct uv__queue* uv__queue_next(const struct uv__queue* q) { + return q->next; +} + +static inline void uv__queue_add(struct uv__queue* h, struct uv__queue* n) { + h->prev->next = n->next; + n->next->prev = h->prev; + h->prev = n->prev; + h->prev->next = h; +} + +static inline void uv__queue_split(struct uv__queue* h, + struct uv__queue* q, + struct uv__queue* n) { + n->prev = h->prev; + n->prev->next = n; + n->next = q; + h->prev = q->prev; + h->prev->next = h; + q->prev = n; +} + +static inline void uv__queue_move(struct uv__queue* h, struct uv__queue* n) { + if (uv__queue_empty(h)) + uv__queue_init(n); + else + uv__queue_split(h, h->next, n); +} + +static inline void uv__queue_insert_head(struct uv__queue* h, + struct uv__queue* q) { + q->next = h->next; + q->prev = h; + q->next->prev = q; + h->next = q; +} + +static inline void uv__queue_insert_tail(struct uv__queue* h, + struct uv__queue* q) { + q->next = h; + q->prev = h->prev; + q->prev->next = q; + h->prev = q; +} + +static inline void uv__queue_remove(struct uv__queue* q) { + q->prev->next = q->next; + q->next->prev = q->prev; +} #endif /* QUEUE_H_ */ diff --git a/wpinet/src/main/native/thirdparty/libuv/src/thread-common.cpp b/wpinet/src/main/native/thirdparty/libuv/src/thread-common.cpp new file mode 100644 index 00000000000..c0e39b543df --- /dev/null +++ b/wpinet/src/main/native/thirdparty/libuv/src/thread-common.cpp @@ -0,0 +1,175 @@ +/* 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 "uv-common.h" + +#include +#ifndef _WIN32 +#include +#endif + +#if defined(PTHREAD_BARRIER_SERIAL_THREAD) +STATIC_ASSERT(sizeof(uv_barrier_t) == sizeof(pthread_barrier_t)); +#endif + +/* Note: guard clauses should match uv_barrier_t's in include/uv/unix.h. */ +#if defined(_AIX) || \ + defined(__OpenBSD__) || \ + !defined(PTHREAD_BARRIER_SERIAL_THREAD) +int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { + int rc; +#ifdef _WIN32 + uv_barrier_t* b; + b = barrier; + + if (barrier == NULL || count == 0) + return UV_EINVAL; +#else + struct _uv_barrier* b; + + if (barrier == NULL || count == 0) + return UV_EINVAL; + + b = (struct _uv_barrier *)uv__malloc(sizeof(*b)); + if (b == NULL) + return UV_ENOMEM; +#endif + + b->in = 0; + b->out = 0; + b->threshold = count; + + rc = uv_mutex_init(&b->mutex); + if (rc != 0) + goto error2; + + /* TODO(vjnash): remove these uv_cond_t casts in v2. */ + rc = uv_cond_init((uv_cond_t*) &b->cond); + if (rc != 0) + goto error; + +#ifndef _WIN32 + barrier->b = b; +#endif + return 0; + +error: + uv_mutex_destroy(&b->mutex); +error2: +#ifndef _WIN32 + uv__free(b); +#endif + return rc; +} + + +int uv_barrier_wait(uv_barrier_t* barrier) { + int last; +#ifdef _WIN32 + uv_barrier_t* b; + b = barrier; +#else + struct _uv_barrier* b; + + if (barrier == NULL || barrier->b == NULL) + return UV_EINVAL; + + b = barrier->b; +#endif + + uv_mutex_lock(&b->mutex); + + while (b->out != 0) + uv_cond_wait((uv_cond_t*) &b->cond, &b->mutex); + + if (++b->in == b->threshold) { + b->in = 0; + b->out = b->threshold; + uv_cond_broadcast((uv_cond_t*) &b->cond); + } else { + do + uv_cond_wait((uv_cond_t*) &b->cond, &b->mutex); + while (b->in != 0); + } + + last = (--b->out == 0); + if (last) + uv_cond_broadcast((uv_cond_t*) &b->cond); + + uv_mutex_unlock(&b->mutex); + return last; +} + + +void uv_barrier_destroy(uv_barrier_t* barrier) { +#ifdef _WIN32 + uv_barrier_t* b; + b = barrier; +#else + struct _uv_barrier* b; + b = barrier->b; +#endif + + uv_mutex_lock(&b->mutex); + + assert(b->in == 0); + while (b->out != 0) + uv_cond_wait((uv_cond_t*) &b->cond, &b->mutex); + + if (b->in != 0) + abort(); + + uv_mutex_unlock(&b->mutex); + uv_mutex_destroy(&b->mutex); + uv_cond_destroy((uv_cond_t*) &b->cond); + +#ifndef _WIN32 + uv__free(barrier->b); + barrier->b = NULL; +#endif +} + +#else + +int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { + return UV__ERR(pthread_barrier_init(barrier, NULL, count)); +} + + +int uv_barrier_wait(uv_barrier_t* barrier) { + int rc; + + rc = pthread_barrier_wait(barrier); + if (rc != 0) + if (rc != PTHREAD_BARRIER_SERIAL_THREAD) + abort(); + + return rc == PTHREAD_BARRIER_SERIAL_THREAD; +} + + +void uv_barrier_destroy(uv_barrier_t* barrier) { + if (pthread_barrier_destroy(barrier)) + abort(); +} + +#endif diff --git a/wpinet/src/main/native/thirdparty/libuv/src/threadpool.cpp b/wpinet/src/main/native/thirdparty/libuv/src/threadpool.cpp index 718972c33b9..aa282af4689 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/threadpool.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/threadpool.cpp @@ -41,10 +41,10 @@ static unsigned int slow_io_work_running; static unsigned int nthreads; static uv_thread_t* threads; static uv_thread_t default_threads[4]; -static QUEUE exit_message; -static QUEUE wq; -static QUEUE run_slow_work_message; -static QUEUE slow_io_pending_wq; +static struct uv__queue exit_message; +static struct uv__queue wq; +static struct uv__queue run_slow_work_message; +static struct uv__queue slow_io_pending_wq; static unsigned int slow_work_thread_threshold(void) { return (nthreads + 1) / 2; @@ -60,7 +60,7 @@ static void uv__cancelled(struct uv__work* w) { */ static void worker(void* arg) { struct uv__work* w; - QUEUE* q; + struct uv__queue* q; int is_slow_work; uv_sem_post((uv_sem_t*) arg); @@ -72,49 +72,49 @@ static void worker(void* arg) { /* Keep waiting while either no work is present or only slow I/O and we're at the threshold for that. */ - while (QUEUE_EMPTY(&wq) || - (QUEUE_HEAD(&wq) == &run_slow_work_message && - QUEUE_NEXT(&run_slow_work_message) == &wq && + while (uv__queue_empty(&wq) || + (uv__queue_head(&wq) == &run_slow_work_message && + uv__queue_next(&run_slow_work_message) == &wq && slow_io_work_running >= slow_work_thread_threshold())) { idle_threads += 1; uv_cond_wait(&cond, &mutex); idle_threads -= 1; } - q = QUEUE_HEAD(&wq); + q = uv__queue_head(&wq); if (q == &exit_message) { uv_cond_signal(&cond); uv_mutex_unlock(&mutex); break; } - QUEUE_REMOVE(q); - QUEUE_INIT(q); /* Signal uv_cancel() that the work req is executing. */ + uv__queue_remove(q); + uv__queue_init(q); /* Signal uv_cancel() that the work req is executing. */ is_slow_work = 0; if (q == &run_slow_work_message) { /* If we're at the slow I/O threshold, re-schedule until after all other work in the queue is done. */ if (slow_io_work_running >= slow_work_thread_threshold()) { - QUEUE_INSERT_TAIL(&wq, q); + uv__queue_insert_tail(&wq, q); continue; } /* If we encountered a request to run slow I/O work but there is none to run, that means it's cancelled => Start over. */ - if (QUEUE_EMPTY(&slow_io_pending_wq)) + if (uv__queue_empty(&slow_io_pending_wq)) continue; is_slow_work = 1; slow_io_work_running++; - q = QUEUE_HEAD(&slow_io_pending_wq); - QUEUE_REMOVE(q); - QUEUE_INIT(q); + q = uv__queue_head(&slow_io_pending_wq); + uv__queue_remove(q); + uv__queue_init(q); /* If there is more slow I/O work, schedule it to be run as well. */ - if (!QUEUE_EMPTY(&slow_io_pending_wq)) { - QUEUE_INSERT_TAIL(&wq, &run_slow_work_message); + if (!uv__queue_empty(&slow_io_pending_wq)) { + uv__queue_insert_tail(&wq, &run_slow_work_message); if (idle_threads > 0) uv_cond_signal(&cond); } @@ -122,13 +122,13 @@ static void worker(void* arg) { uv_mutex_unlock(&mutex); - w = QUEUE_DATA(q, struct uv__work, wq); + w = uv__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__queue_insert_tail(&w->loop->wq, &w->wq); uv_async_send(&w->loop->wq_async); uv_mutex_unlock(&w->loop->wq_mutex); @@ -143,12 +143,12 @@ static void worker(void* arg) { } -static void post(QUEUE* q, enum uv__work_kind kind) { +static void post(struct uv__queue* q, enum uv__work_kind kind) { uv_mutex_lock(&mutex); if (kind == UV__WORK_SLOW_IO) { /* Insert into a separate queue. */ - QUEUE_INSERT_TAIL(&slow_io_pending_wq, q); - if (!QUEUE_EMPTY(&run_slow_work_message)) { + uv__queue_insert_tail(&slow_io_pending_wq, q); + if (!uv__queue_empty(&run_slow_work_message)) { /* Running slow I/O tasks is already scheduled => Nothing to do here. The worker that runs said other task will schedule this one as well. */ uv_mutex_unlock(&mutex); @@ -157,7 +157,7 @@ static void post(QUEUE* q, enum uv__work_kind kind) { q = &run_slow_work_message; } - QUEUE_INSERT_TAIL(&wq, q); + uv__queue_insert_tail(&wq, q); if (idle_threads > 0) uv_cond_signal(&cond); uv_mutex_unlock(&mutex); @@ -195,6 +195,7 @@ void uv__threadpool_cleanup(void) { static void init_threads(void) { + uv_thread_options_t config; unsigned int i; const char* val; uv_sem_t sem; @@ -223,15 +224,18 @@ static void init_threads(void) { if (uv_mutex_init(&mutex)) abort(); - QUEUE_INIT(&wq); - QUEUE_INIT(&slow_io_pending_wq); - QUEUE_INIT(&run_slow_work_message); + uv__queue_init(&wq); + uv__queue_init(&slow_io_pending_wq); + uv__queue_init(&run_slow_work_message); if (uv_sem_init(&sem, 0)) abort(); + config.flags = UV_THREAD_HAS_STACK_SIZE; + config.stack_size = 8u << 20; /* 8 MB */ + for (i = 0; i < nthreads; i++) - if (uv_thread_create(threads + i, worker, &sem)) + if (uv_thread_create_ex(threads + i, &config, worker, &sem)) abort(); for (i = 0; i < nthreads; i++) @@ -275,15 +279,19 @@ void uv__work_submit(uv_loop_t* loop, } +/* TODO(bnoordhuis) teach libuv how to cancel file operations + * that go through io_uring instead of the thread pool. + */ static int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) { int cancelled; + uv_once(&once, init_once); /* Ensure |mutex| is initialized. */ uv_mutex_lock(&mutex); uv_mutex_lock(&w->loop->wq_mutex); - cancelled = !QUEUE_EMPTY(&w->wq) && w->work != NULL; + cancelled = !uv__queue_empty(&w->wq) && w->work != NULL; if (cancelled) - QUEUE_REMOVE(&w->wq); + uv__queue_remove(&w->wq); uv_mutex_unlock(&w->loop->wq_mutex); uv_mutex_unlock(&mutex); @@ -293,7 +301,7 @@ static int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) { w->work = uv__cancelled; uv_mutex_lock(&loop->wq_mutex); - QUEUE_INSERT_TAIL(&loop->wq, &w->wq); + uv__queue_insert_tail(&loop->wq, &w->wq); uv_async_send(&loop->wq_async); uv_mutex_unlock(&loop->wq_mutex); @@ -304,22 +312,39 @@ static int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) { void uv__work_done(uv_async_t* handle) { struct uv__work* w; uv_loop_t* loop; - QUEUE* q; - QUEUE wq; + struct uv__queue* q; + struct uv__queue wq; int err; + int nevents; loop = container_of(handle, uv_loop_t, wq_async); uv_mutex_lock(&loop->wq_mutex); - QUEUE_MOVE(&loop->wq, &wq); + uv__queue_move(&loop->wq, &wq); uv_mutex_unlock(&loop->wq_mutex); - while (!QUEUE_EMPTY(&wq)) { - q = QUEUE_HEAD(&wq); - QUEUE_REMOVE(q); + nevents = 0; + + while (!uv__queue_empty(&wq)) { + q = uv__queue_head(&wq); + uv__queue_remove(q); w = container_of(q, struct uv__work, wq); err = (w->work == uv__cancelled) ? UV_ECANCELED : 0; w->done(w, err); + nevents++; + } + + /* This check accomplishes 2 things: + * 1. Even if the queue was empty, the call to uv__work_done() should count + * as an event. Which will have been added by the event loop when + * calling this callback. + * 2. Prevents accidental wrap around in case nevents == 0 events == 0. + */ + if (nevents > 1) { + /* Subtract 1 to counter the call to uv__work_done(). */ + uv__metrics_inc_events(loop, nevents - 1); + if (uv__get_internal_fields(loop)->current_timeout == 0) + uv__metrics_inc_events_waiting(loop, nevents - 1); } } diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/async.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/async.cpp index e1805c32379..fef4ae93343 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/async.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/async.cpp @@ -24,7 +24,6 @@ #include "uv.h" #include "internal.h" -#include "atomic-ops.h" #include #include /* snprintf() */ @@ -38,8 +37,11 @@ #include #endif +#include + static void uv__async_send(uv_loop_t* loop); static int uv__async_start(uv_loop_t* loop); +static void uv__cpu_relax(void); int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) { @@ -52,8 +54,9 @@ int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) { uv__handle_init(loop, (uv_handle_t*)handle, UV_ASYNC); handle->async_cb = async_cb; handle->pending = 0; + handle->u.fd = 0; /* This will be used as a busy flag. */ - QUEUE_INSERT_TAIL(&loop->async_handles, &handle->queue); + uv__queue_insert_tail(&loop->async_handles, &handle->queue); uv__handle_start(handle); return 0; @@ -61,46 +64,54 @@ int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) { int uv_async_send(uv_async_t* handle) { + std::atomic* pending; + std::atomic* busy; + + pending = (std::atomic*) &handle->pending; + busy = (std::atomic*) &handle->u.fd; + /* Do a cheap read first. */ - if (ACCESS_ONCE(int, handle->pending) != 0) + if (atomic_load_explicit(pending, std::memory_order_relaxed) != 0) return 0; - /* Tell the other thread we're busy with the handle. */ - if (cmpxchgi(&handle->pending, 0, 1) != 0) - return 0; + /* Set the loop to busy. */ + atomic_fetch_add(busy, 1); /* Wake up the other thread's event loop. */ - uv__async_send(handle->loop); + if (atomic_exchange(pending, 1) == 0) + uv__async_send(handle->loop); - /* Tell the other thread we're done. */ - if (cmpxchgi(&handle->pending, 1, 2) != 1) - abort(); + /* Set the loop to not-busy. */ + atomic_fetch_add(busy, -1); return 0; } -/* Only call this from the event loop thread. */ -static int uv__async_spin(uv_async_t* handle) { +/* Wait for the busy flag to clear before closing. + * Only call this from the event loop thread. */ +static void uv__async_spin(uv_async_t* handle) { + std::atomic* pending; + std::atomic* busy; int i; - int rc; + + pending = (std::atomic*) &handle->pending; + busy = (std::atomic*) &handle->u.fd; + + /* Set the pending flag first, so no new events will be added by other + * threads after this function returns. */ + atomic_store(pending, 1); for (;;) { - /* 997 is not completely chosen at random. It's a prime number, acyclical - * by nature, and should therefore hopefully dampen sympathetic resonance. + /* 997 is not completely chosen at random. It's a prime number, acyclic by + * nature, and should therefore hopefully dampen sympathetic resonance. */ for (i = 0; i < 997; i++) { - /* 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; + if (atomic_load(busy) == 0) + return; /* Other thread is busy with this handle, spin until it's done. */ - cpu_relax(); + uv__cpu_relax(); } /* Yield the CPU. We may have preempted the other thread while it's @@ -114,7 +125,7 @@ static int uv__async_spin(uv_async_t* handle) { void uv__async_close(uv_async_t* handle) { uv__async_spin(handle); - QUEUE_REMOVE(&handle->queue); + uv__queue_remove(&handle->queue); uv__handle_stop(handle); } @@ -122,9 +133,10 @@ void uv__async_close(uv_async_t* handle) { static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { char buf[1024]; ssize_t r; - QUEUE queue; - QUEUE* q; + struct uv__queue queue; + struct uv__queue* q; uv_async_t* h; + std::atomic *pending; assert(w == &loop->async_io_watcher); @@ -146,16 +158,18 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { abort(); } - QUEUE_MOVE(&loop->async_handles, &queue); - while (!QUEUE_EMPTY(&queue)) { - q = QUEUE_HEAD(&queue); - h = QUEUE_DATA(q, uv_async_t, queue); + uv__queue_move(&loop->async_handles, &queue); + while (!uv__queue_empty(&queue)) { + q = uv__queue_head(&queue); + h = uv__queue_data(q, uv_async_t, queue); - QUEUE_REMOVE(q); - QUEUE_INSERT_TAIL(&loop->async_handles, q); + uv__queue_remove(q); + uv__queue_insert_tail(&loop->async_handles, q); - if (0 == uv__async_spin(h)) - continue; /* Not pending. */ + /* Atomically fetch and clear pending flag */ + pending = (std::atomic*) &h->pending; + if (atomic_exchange(pending, 0) == 0) + continue; if (h->async_cb == NULL) continue; @@ -227,20 +241,68 @@ static int uv__async_start(uv_loop_t* loop) { } +void uv__async_stop(uv_loop_t* loop) { + struct uv__queue queue; + struct uv__queue* q; + uv_async_t* h; + + if (loop->async_io_watcher.fd == -1) + return; + + /* Make sure no other thread is accessing the async handle fd after the loop + * cleanup. + */ + uv__queue_move(&loop->async_handles, &queue); + while (!uv__queue_empty(&queue)) { + q = uv__queue_head(&queue); + h = uv__queue_data(q, uv_async_t, queue); + + uv__queue_remove(q); + uv__queue_insert_tail(&loop->async_handles, q); + + uv__async_spin(h); + } + + if (loop->async_wfd != -1) { + if (loop->async_wfd != loop->async_io_watcher.fd) + uv__close(loop->async_wfd); + loop->async_wfd = -1; + } + + uv__io_stop(loop, &loop->async_io_watcher, POLLIN); + uv__close(loop->async_io_watcher.fd); + loop->async_io_watcher.fd = -1; +} + + int uv__async_fork(uv_loop_t* loop) { + struct uv__queue queue; + struct uv__queue* q; + uv_async_t* h; + if (loop->async_io_watcher.fd == -1) /* never started */ return 0; - uv__async_stop(loop); - - return uv__async_start(loop); -} + uv__queue_move(&loop->async_handles, &queue); + while (!uv__queue_empty(&queue)) { + q = uv__queue_head(&queue); + h = uv__queue_data(q, uv_async_t, queue); + uv__queue_remove(q); + uv__queue_insert_tail(&loop->async_handles, q); -void uv__async_stop(uv_loop_t* loop) { - if (loop->async_io_watcher.fd == -1) - return; + /* The state of any thread that set pending is now likely corrupt in this + * child because the user called fork, so just clear these flags and move + * on. Calling most libc functions after `fork` is declared to be undefined + * behavior anyways, unless async-signal-safe, for multithreaded programs + * like libuv, and nothing interesting in pthreads is async-signal-safe. + */ + h->pending = 0; + /* This is the busy flag, and we just abruptly lost all other threads. */ + h->u.fd = 0; + } + /* Recreate these, since they still exist, but belong to the wrong pid now. */ if (loop->async_wfd != -1) { if (loop->async_wfd != loop->async_io_watcher.fd) uv__close(loop->async_wfd); @@ -250,4 +312,19 @@ void uv__async_stop(uv_loop_t* loop) { uv__io_stop(loop, &loop->async_io_watcher, POLLIN); uv__close(loop->async_io_watcher.fd); loop->async_io_watcher.fd = -1; + + return uv__async_start(loop); +} + + +static void uv__cpu_relax(void) { +#if defined(__i386__) || defined(__x86_64__) + __asm__ __volatile__ ("rep; nop" ::: "memory"); /* a.k.a. PAUSE */ +#elif (defined(__arm__) && __ARM_ARCH >= 7) || defined(__aarch64__) + __asm__ __volatile__ ("yield" ::: "memory"); +#elif (defined(__ppc__) || defined(__ppc64__)) && defined(__APPLE__) + __asm volatile ("" : : : "memory"); +#elif !defined(__APPLE__) && (defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__)) + __asm__ __volatile__ ("or 1,1,1; or 2,2,2" ::: "memory"); +#endif } diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/atomic-ops.h b/wpinet/src/main/native/thirdparty/libuv/src/unix/atomic-ops.h deleted file mode 100644 index 58043c42fbd..00000000000 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/atomic-ops.h +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright (c) 2013, Ben Noordhuis - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef UV_ATOMIC_OPS_H_ -#define UV_ATOMIC_OPS_H_ - -#include "internal.h" /* UV_UNUSED */ - -#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) -#include -#endif - -UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)); -UV_UNUSED(static void cpu_relax(void)); - -/* Prefer hand-rolled assembly over the gcc builtins because the latter also - * issue full memory barriers. - */ -UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) { -#if defined(__i386__) || defined(__x86_64__) - int out; - __asm__ __volatile__ ("lock; cmpxchg %2, %1;" - : "=a" (out), "+m" (*(volatile int*) ptr) - : "r" (newval), "0" (oldval) - : "memory"); - return out; -#elif defined(__MVS__) - /* Use hand-rolled assembly because codegen from builtin __plo_CSST results in - * a runtime bug. - */ - __asm(" cs %0,%2,%1 \n " : "+r"(oldval), "+m"(*ptr) : "r"(newval) :); - return oldval; -#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) - return atomic_cas_uint((uint_t *)ptr, (uint_t)oldval, (uint_t)newval); -#else - return __sync_val_compare_and_swap(ptr, oldval, newval); -#endif -} - -UV_UNUSED(static void cpu_relax(void)) { -#if defined(__i386__) || defined(__x86_64__) - __asm__ __volatile__ ("rep; nop" ::: "memory"); /* a.k.a. PAUSE */ -#elif (defined(__arm__) && __ARM_ARCH >= 7) || defined(__aarch64__) - __asm__ __volatile__ ("yield" ::: "memory"); -#elif (defined(__ppc__) || defined(__ppc64__)) && defined(__APPLE__) - __asm volatile ("" : : : "memory"); -#elif !defined(__APPLE__) && (defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__)) - __asm__ __volatile__ ("or 1,1,1; or 2,2,2" ::: "memory"); -#endif -} - -#endif /* UV_ATOMIC_OPS_H_ */ diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/core.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/core.cpp index 4c23f608c84..ce7fd2cdfdd 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/core.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/core.cpp @@ -41,12 +41,14 @@ #include /* writev */ #include /* getrusage */ #include +#include #include #include +#include /* clock_gettime */ +#include #ifdef __sun # include -# include # include #endif @@ -66,13 +68,14 @@ extern char** environ; #if defined(__DragonFly__) || \ defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || \ defined(__NetBSD__) || \ defined(__OpenBSD__) # include # include # include +# include # if defined(__FreeBSD__) +# include # define uv__accept4 accept4 # endif # if defined(__NetBSD__) @@ -107,6 +110,35 @@ STATIC_ASSERT(offsetof(uv_buf_t, base) == offsetof(struct iovec, iov_base)); STATIC_ASSERT(offsetof(uv_buf_t, len) == offsetof(struct iovec, iov_len)); +/* https://github.com/libuv/libuv/issues/1674 */ +int uv_clock_gettime(uv_clock_id clock_id, uv_timespec64_t* ts) { + struct timespec t; + int r; + + if (ts == NULL) + return UV_EFAULT; + + switch (clock_id) { + default: + return UV_EINVAL; + case UV_CLOCK_MONOTONIC: + r = clock_gettime(CLOCK_MONOTONIC, &t); + break; + case UV_CLOCK_REALTIME: + r = clock_gettime(CLOCK_REALTIME, &t); + break; + } + + if (r) + return UV__ERR(errno); + + ts->tv_sec = t.tv_sec; + ts->tv_nsec = t.tv_nsec; + + return 0; +} + + uint64_t uv_hrtime(void) { return uv__hrtime(UV_CLOCK_PRECISE); } @@ -232,10 +264,10 @@ int uv__getiovmax(void) { #if defined(IOV_MAX) return IOV_MAX; #elif defined(_SC_IOV_MAX) - static int iovmax_cached = -1; + static std::atomic iovmax_cached = -1; int iovmax; - iovmax = uv__load_relaxed(&iovmax_cached); + iovmax = atomic_load_explicit(&iovmax_cached, memory_order_relaxed); if (iovmax != -1) return iovmax; @@ -247,7 +279,7 @@ int uv__getiovmax(void) { if (iovmax == -1) iovmax = 1; - uv__store_relaxed(&iovmax_cached, iovmax); + atomic_store_explicit(&iovmax_cached, iovmax, memory_order_relaxed); return iovmax; #else @@ -313,7 +345,7 @@ static void uv__finish_close(uv_handle_t* handle) { } uv__handle_unref(handle); - QUEUE_REMOVE(&handle->handle_queue); + uv__queue_remove(&handle->handle_queue); if (handle->close_cb) { handle->close_cb(handle); @@ -349,7 +381,7 @@ int uv_backend_fd(const uv_loop_t* loop) { static int uv__loop_alive(const uv_loop_t* loop) { return uv__has_active_handles(loop) || uv__has_active_reqs(loop) || - !QUEUE_EMPTY(&loop->pending_queue) || + !uv__queue_empty(&loop->pending_queue) || loop->closing_handles != NULL; } @@ -358,8 +390,9 @@ static int uv__backend_timeout(const uv_loop_t* loop) { if (loop->stop_flag == 0 && /* uv__loop_alive(loop) && */ (uv__has_active_handles(loop) || uv__has_active_reqs(loop)) && - QUEUE_EMPTY(&loop->pending_queue) && - QUEUE_EMPTY(&loop->idle_handles) && + uv__queue_empty(&loop->pending_queue) && + uv__queue_empty(&loop->idle_handles) && + (loop->flags & UV_LOOP_REAP_CHILDREN) == 0 && loop->closing_handles == NULL) return uv__next_timeout(loop); return 0; @@ -367,7 +400,7 @@ static int uv__backend_timeout(const uv_loop_t* loop) { int uv_backend_timeout(const uv_loop_t* loop) { - if (QUEUE_EMPTY(&loop->watcher_queue)) + if (uv__queue_empty(&loop->watcher_queue)) return uv__backend_timeout(loop); /* Need to call uv_run to update the backend fd state. */ return 0; @@ -388,12 +421,19 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) { if (!r) uv__update_time(loop); - while (r != 0 && loop->stop_flag == 0) { + /* Maintain backwards compatibility by processing timers before entering the + * while loop for UV_RUN_DEFAULT. Otherwise timers only need to be executed + * once, which should be done after polling in order to maintain proper + * execution order of the conceptual event loop. */ + if (mode == UV_RUN_DEFAULT && r != 0 && loop->stop_flag == 0) { uv__update_time(loop); uv__run_timers(loop); + } + while (r != 0 && loop->stop_flag == 0) { can_sleep = - QUEUE_EMPTY(&loop->pending_queue) && QUEUE_EMPTY(&loop->idle_handles); + uv__queue_empty(&loop->pending_queue) && + uv__queue_empty(&loop->idle_handles); uv__run_pending(loop); uv__run_idle(loop); @@ -403,11 +443,13 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) { if ((mode == UV_RUN_ONCE && can_sleep) || mode == UV_RUN_DEFAULT) timeout = uv__backend_timeout(loop); + uv__metrics_inc_loop_count(loop); + uv__io_poll(loop, timeout); /* Process immediate callbacks (e.g. write_cb) a small fixed number of * times to avoid loop starvation.*/ - for (r = 0; r < 8 && !QUEUE_EMPTY(&loop->pending_queue); r++) + for (r = 0; r < 8 && !uv__queue_empty(&loop->pending_queue); r++) uv__run_pending(loop); /* Run one final update on the provider_idle_time in case uv__io_poll @@ -420,18 +462,8 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) { uv__run_check(loop); uv__run_closing_handles(loop); - if (mode == UV_RUN_ONCE) { - /* UV_RUN_ONCE implies forward progress: at least one callback must have - * been invoked when it returns. uv__io_poll() can return without doing - * I/O (meaning: no callbacks) when its timeout expires - which means we - * have pending timers that satisfy the forward progress constraint. - * - * UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from - * the check. - */ - uv__update_time(loop); - uv__run_timers(loop); - } + uv__update_time(loop); + uv__run_timers(loop); r = uv__loop_alive(loop); if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT) @@ -805,17 +837,17 @@ int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) { static void uv__run_pending(uv_loop_t* loop) { - QUEUE* q; - QUEUE pq; + struct uv__queue* q; + struct uv__queue pq; uv__io_t* w; - QUEUE_MOVE(&loop->pending_queue, &pq); + uv__queue_move(&loop->pending_queue, &pq); - while (!QUEUE_EMPTY(&pq)) { - q = QUEUE_HEAD(&pq); - QUEUE_REMOVE(q); - QUEUE_INIT(q); - w = QUEUE_DATA(q, uv__io_t, pending_queue); + while (!uv__queue_empty(&pq)) { + q = uv__queue_head(&pq); + uv__queue_remove(q); + uv__queue_init(q); + w = uv__queue_data(q, uv__io_t, pending_queue); w->cb(loop, w, POLLOUT); } } @@ -862,7 +894,7 @@ static void maybe_resize(uv_loop_t* loop, unsigned int len) { watchers[nwatchers] = fake_watcher_list; watchers[nwatchers + 1] = fake_watcher_count; - loop->watchers = watchers; + loop->watchers = (uv__io_t**)watchers; loop->nwatchers = nwatchers; } @@ -870,17 +902,12 @@ static void maybe_resize(uv_loop_t* loop, unsigned int len) { void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd) { assert(cb != NULL); assert(fd >= -1); - QUEUE_INIT(&w->pending_queue); - QUEUE_INIT(&w->watcher_queue); + uv__queue_init(&w->pending_queue); + uv__queue_init(&w->watcher_queue); w->cb = cb; w->fd = fd; w->events = 0; w->pevents = 0; - -#if defined(UV_HAVE_KQUEUE) - w->rcount = 0; - w->wcount = 0; -#endif /* defined(UV_HAVE_KQUEUE) */ } @@ -902,8 +929,8 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) { return; #endif - if (QUEUE_EMPTY(&w->watcher_queue)) - QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue); + if (uv__queue_empty(&w->watcher_queue)) + uv__queue_insert_tail(&loop->watcher_queue, &w->watcher_queue); if (loop->watchers[w->fd] == NULL) { loop->watchers[w->fd] = w; @@ -928,8 +955,8 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) { w->pevents &= ~events; if (w->pevents == 0) { - QUEUE_REMOVE(&w->watcher_queue); - QUEUE_INIT(&w->watcher_queue); + uv__queue_remove(&w->watcher_queue); + uv__queue_init(&w->watcher_queue); w->events = 0; if (w == loop->watchers[w->fd]) { @@ -938,14 +965,14 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) { loop->nfds--; } } - else if (QUEUE_EMPTY(&w->watcher_queue)) - QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue); + else if (uv__queue_empty(&w->watcher_queue)) + uv__queue_insert_tail(&loop->watcher_queue, &w->watcher_queue); } void uv__io_close(uv_loop_t* loop, uv__io_t* w) { uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI); - QUEUE_REMOVE(&w->pending_queue); + uv__queue_remove(&w->pending_queue); /* Remove stale events for this file descriptor */ if (w->fd != -1) @@ -954,8 +981,8 @@ void uv__io_close(uv_loop_t* loop, uv__io_t* w) { 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); + if (uv__queue_empty(&w->pending_queue)) + uv__queue_insert_tail(&loop->pending_queue, &w->pending_queue); } @@ -1000,6 +1027,15 @@ int uv_getrusage(uv_rusage_t* rusage) { rusage->ru_nivcsw = usage.ru_nivcsw; #endif + /* Most platforms report ru_maxrss in kilobytes; macOS and Solaris are + * the outliers because of course they are. + */ +#if defined(__APPLE__) + rusage->ru_maxrss /= 1024; /* macOS and iOS report bytes. */ +#elif defined(__sun) + rusage->ru_maxrss /= getpagesize() / 1024; /* Solaris reports pages. */ +#endif + return 0; } @@ -1099,8 +1135,8 @@ int uv_os_homedir(char* buffer, size_t* size) { if (r != UV_ENOENT) return r; - /* HOME is not set, so call uv__getpwuid_r() */ - r = uv__getpwuid_r(&pwd); + /* HOME is not set, so call uv_os_get_passwd() */ + r = uv_os_get_passwd(&pwd); if (r != 0) { return r; @@ -1173,11 +1209,10 @@ int uv_os_tmpdir(char* buffer, size_t* size) { } -int uv__getpwuid_r(uv_passwd_t* pwd) { +static int uv__getpwuid_r(uv_passwd_t *pwd, uid_t uid) { struct passwd pw; struct passwd* result; char* buf; - uid_t uid; size_t bufsize; size_t name_size; size_t homedir_size; @@ -1187,8 +1222,6 @@ int uv__getpwuid_r(uv_passwd_t* pwd) { if (pwd == NULL) return UV_EINVAL; - uid = geteuid(); - /* Calling sysconf(_SC_GETPW_R_SIZE_MAX) would get the suggested size, but it * is frequently 1024 or 4096, so we can just use that directly. The pwent * will not usually be large. */ @@ -1247,24 +1280,98 @@ int uv__getpwuid_r(uv_passwd_t* pwd) { } -void uv_os_free_passwd(uv_passwd_t* pwd) { - if (pwd == NULL) - return; +int uv_os_get_group(uv_group_t* grp, uv_uid_t gid) { +#if defined(__ANDROID__) && __ANDROID_API__ < 24 + /* This function getgrgid_r() was added in Android N (level 24) */ + return UV_ENOSYS; +#else + struct group gp; + struct group* result; + char* buf; + char* gr_mem; + size_t bufsize; + size_t name_size; + long members; + size_t mem_size; + int r; - /* - The memory for name, shell, and homedir are allocated in a single - uv__malloc() call. The base of the pointer is stored in pwd->username, so - that is the field that needs to be freed. - */ - uv__free(pwd->username); - pwd->username = NULL; - pwd->shell = NULL; - pwd->homedir = NULL; + if (grp == NULL) + return UV_EINVAL; + + /* Calling sysconf(_SC_GETGR_R_SIZE_MAX) would get the suggested size, but it + * is frequently 1024 or 4096, so we can just use that directly. The pwent + * will not usually be large. */ + for (bufsize = 2000;; bufsize *= 2) { + buf = (char*)uv__malloc(bufsize); + + if (buf == NULL) + return UV_ENOMEM; + + do + r = getgrgid_r(gid, &gp, buf, bufsize, &result); + while (r == EINTR); + + if (r != 0 || result == NULL) + uv__free(buf); + + if (r != ERANGE) + break; + } + + if (r != 0) + return UV__ERR(r); + + if (result == NULL) + return UV_ENOENT; + + /* Allocate memory for the groupname and members. */ + name_size = strlen(gp.gr_name) + 1; + members = 0; + mem_size = sizeof(char*); + for (r = 0; gp.gr_mem[r] != NULL; r++) { + mem_size += strlen(gp.gr_mem[r]) + 1 + sizeof(char*); + members++; + } + + gr_mem = (char*)uv__malloc(name_size + mem_size); + if (gr_mem == NULL) { + uv__free(buf); + return UV_ENOMEM; + } + + /* Copy the members */ + grp->members = (char**) gr_mem; + grp->members[members] = NULL; + gr_mem = (char*) &grp->members[members + 1]; + for (r = 0; r < members; r++) { + grp->members[r] = gr_mem; + strcpy(gr_mem, gp.gr_mem[r]); + gr_mem += strlen(gr_mem) + 1; + } + assert(gr_mem == (char*)grp->members + mem_size); + + /* Copy the groupname */ + grp->groupname = gr_mem; + memcpy(grp->groupname, gp.gr_name, name_size); + gr_mem += name_size; + + /* Copy the gid */ + grp->gid = gp.gr_gid; + + uv__free(buf); + + return 0; +#endif } int uv_os_get_passwd(uv_passwd_t* pwd) { - return uv__getpwuid_r(pwd); + return uv__getpwuid_r(pwd, geteuid()); +} + + +int uv_os_get_passwd2(uv_passwd_t* pwd, uv_uid_t uid) { + return uv__getpwuid_r(pwd, uid); } @@ -1425,6 +1532,13 @@ uv_pid_t uv_os_getppid(void) { return getppid(); } +int uv_cpumask_size(void) { +#if UV__CPU_AFFINITY_SUPPORTED + return CPU_SETSIZE; +#else + return UV_ENOTSUP; +#endif +} int uv_os_getpriority(uv_pid_t pid, int* priority) { int r; diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/cygwin.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/cygwin.cpp index 169958d55f2..4e5413963d6 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/cygwin.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/cygwin.cpp @@ -51,3 +51,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { uint64_t uv_get_constrained_memory(void) { return 0; /* Memory constraints are unknown. */ } + +uint64_t uv_get_available_memory(void) { + return uv_get_free_memory(); +} diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/darwin-stub.h b/wpinet/src/main/native/thirdparty/libuv/src/unix/darwin-stub.h index 433e3efa730..b93cf67c596 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/darwin-stub.h +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/darwin-stub.h @@ -27,7 +27,6 @@ struct CFArrayCallBacks; struct CFRunLoopSourceContext; struct FSEventStreamContext; -struct CFRange; typedef double CFAbsoluteTime; typedef double CFTimeInterval; @@ -43,23 +42,13 @@ typedef unsigned CFStringEncoding; typedef void* CFAllocatorRef; typedef void* CFArrayRef; typedef void* CFBundleRef; -typedef void* CFDataRef; typedef void* CFDictionaryRef; -typedef void* CFMutableDictionaryRef; -typedef struct CFRange CFRange; typedef void* CFRunLoopRef; typedef void* CFRunLoopSourceRef; typedef void* CFStringRef; typedef void* CFTypeRef; typedef void* FSEventStreamRef; -typedef uint32_t IOOptionBits; -typedef unsigned int io_iterator_t; -typedef unsigned int io_object_t; -typedef unsigned int io_service_t; -typedef unsigned int io_registry_entry_t; - - typedef void (*FSEventStreamCallback)(const FSEventStreamRef, void*, size_t, @@ -80,11 +69,6 @@ struct FSEventStreamContext { void* pad[3]; }; -struct CFRange { - CFIndex location; - CFIndex length; -}; - static const CFStringEncoding kCFStringEncodingUTF8 = 0x8000100; static const OSStatus noErr = 0; diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/darwin.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/darwin.cpp index ed51a6ad61c..9ee5cd8eb9d 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/darwin.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/darwin.cpp @@ -33,13 +33,10 @@ #include #include /* sysconf */ -#include "darwin-stub.h" - static uv_once_t once = UV_ONCE_INIT; static uint64_t (*time_func)(void); static mach_timebase_info_data_t timebase; -typedef unsigned char UInt8; int uv__platform_loop_init(uv_loop_t* loop) { loop->cf_state = NULL; @@ -110,7 +107,7 @@ uint64_t uv_get_free_memory(void) { if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&info, &count) != KERN_SUCCESS) { - return UV_EINVAL; /* FIXME(bnoordhuis) Translate error. */ + return 0; } return (uint64_t) info.free_count * sysconf(_SC_PAGESIZE); @@ -123,7 +120,7 @@ uint64_t uv_get_total_memory(void) { size_t size = sizeof(info); if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) - return UV__ERR(errno); + return 0; return (uint64_t) info; } @@ -134,6 +131,11 @@ uint64_t uv_get_constrained_memory(void) { } +uint64_t uv_get_available_memory(void) { + return uv_get_free_memory(); +} + + void uv_loadavg(double avg[3]) { struct loadavg info; size_t size = sizeof(info); @@ -183,164 +185,17 @@ int uv_uptime(double* uptime) { return 0; } -static int uv__get_cpu_speed(uint64_t* speed) { - /* IOKit */ - void (*pIOObjectRelease)(io_object_t); - kern_return_t (*pIOMasterPort)(mach_port_t, mach_port_t*); - CFMutableDictionaryRef (*pIOServiceMatching)(const char*); - kern_return_t (*pIOServiceGetMatchingServices)(mach_port_t, - CFMutableDictionaryRef, - io_iterator_t*); - io_service_t (*pIOIteratorNext)(io_iterator_t); - CFTypeRef (*pIORegistryEntryCreateCFProperty)(io_registry_entry_t, - CFStringRef, - CFAllocatorRef, - IOOptionBits); - - /* CoreFoundation */ - CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef, - const char*, - CFStringEncoding); - CFStringEncoding (*pCFStringGetSystemEncoding)(void); - UInt8 *(*pCFDataGetBytePtr)(CFDataRef); - CFIndex (*pCFDataGetLength)(CFDataRef); - void (*pCFDataGetBytes)(CFDataRef, CFRange, UInt8*); - void (*pCFRelease)(CFTypeRef); - - void* core_foundation_handle; - void* iokit_handle; - int err; - - kern_return_t kr; - mach_port_t mach_port; - io_iterator_t it; - io_object_t service; - - mach_port = 0; - - err = UV_ENOENT; - core_foundation_handle = dlopen("/System/Library/Frameworks/" - "CoreFoundation.framework/" - "CoreFoundation", - RTLD_LAZY | RTLD_LOCAL); - iokit_handle = dlopen("/System/Library/Frameworks/IOKit.framework/" - "IOKit", - RTLD_LAZY | RTLD_LOCAL); - - if (core_foundation_handle == NULL || iokit_handle == NULL) - goto out; - -#define V(handle, symbol) \ - do { \ - *(void **)(&p ## symbol) = dlsym((handle), #symbol); \ - if (p ## symbol == NULL) \ - goto out; \ - } \ - while (0) - V(iokit_handle, IOMasterPort); - V(iokit_handle, IOServiceMatching); - V(iokit_handle, IOServiceGetMatchingServices); - V(iokit_handle, IOIteratorNext); - V(iokit_handle, IOObjectRelease); - V(iokit_handle, IORegistryEntryCreateCFProperty); - V(core_foundation_handle, CFStringCreateWithCString); - V(core_foundation_handle, CFStringGetSystemEncoding); - V(core_foundation_handle, CFDataGetBytePtr); - V(core_foundation_handle, CFDataGetLength); - V(core_foundation_handle, CFDataGetBytes); - V(core_foundation_handle, CFRelease); -#undef V - -#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8) - - // Braces ensure goto doesn't jump into device_type_str's and - // clock_frequency_str's lifetimes after their initialization - { - kr = pIOMasterPort(MACH_PORT_NULL, &mach_port); - (void) kr; - assert(kr == KERN_SUCCESS); - CFMutableDictionaryRef classes_to_match - = pIOServiceMatching("IOPlatformDevice"); - kr = pIOServiceGetMatchingServices(mach_port, classes_to_match, &it); - assert(kr == KERN_SUCCESS); - service = pIOIteratorNext(it); - - CFStringRef device_type_str = S("device_type"); - CFStringRef clock_frequency_str = S("clock-frequency"); - - while (service != 0) { - CFDataRef data; - data = pIORegistryEntryCreateCFProperty(service, - device_type_str, - NULL, - 0); - if (data) { - const UInt8* raw = pCFDataGetBytePtr(data); - if (strncmp((char*)raw, "cpu", 3) == 0 || - strncmp((char*)raw, "processor", 9) == 0) { - CFDataRef freq_ref; - freq_ref = pIORegistryEntryCreateCFProperty(service, - clock_frequency_str, - NULL, - 0); - if (freq_ref) { - const UInt8* freq_ref_ptr = pCFDataGetBytePtr(freq_ref); - CFIndex len = pCFDataGetLength(freq_ref); - if (len == 8) - memcpy(speed, freq_ref_ptr, 8); - else if (len == 4) { - uint32_t v; - memcpy(&v, freq_ref_ptr, 4); - *speed = v; - } else { - *speed = 0; - } - - pCFRelease(freq_ref); - pCFRelease(data); - break; - } - } - pCFRelease(data); - } - - service = pIOIteratorNext(it); - } - - pIOObjectRelease(it); - - err = 0; - - if (device_type_str != NULL) - pCFRelease(device_type_str); - if (clock_frequency_str != NULL) - pCFRelease(clock_frequency_str); - } - -out: - if (core_foundation_handle != NULL) - dlclose(core_foundation_handle); - - if (iokit_handle != NULL) - dlclose(iokit_handle); - - mach_port_deallocate(mach_task_self(), mach_port); - - return err; -} - int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK), multiplier = ((uint64_t)1000L / ticks); char model[512]; + uint64_t cpuspeed; size_t size; unsigned int i; natural_t numcpus; mach_msg_type_number_t msg_type; processor_cpu_load_info_data_t *info; uv_cpu_info_t* cpu_info; - uint64_t cpuspeed; - int err; size = sizeof(model); if (sysctlbyname("machdep.cpu.brand_string", &model, &size, NULL, 0) && @@ -348,9 +203,13 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { return UV__ERR(errno); } - err = uv__get_cpu_speed(&cpuspeed); - if (err < 0) - return err; + cpuspeed = 0; + size = sizeof(cpuspeed); + sysctlbyname("hw.cpufrequency", &cpuspeed, &size, NULL, 0); + if (cpuspeed == 0) + /* If sysctl hw.cputype == CPU_TYPE_ARM64, the correct value is unavailable + * from Apple, but we can hard-code it here to a plausible value. */ + cpuspeed = 2400000000; if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numcpus, (processor_info_array_t*)&info, diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/epoll.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/epoll.cpp deleted file mode 100644 index 4c057fb3da3..00000000000 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/epoll.cpp +++ /dev/null @@ -1,422 +0,0 @@ -/* Copyright libuv 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 - -int uv__epoll_init(uv_loop_t* loop) { - int fd; - fd = epoll_create1(O_CLOEXEC); - - /* epoll_create1() can fail either because it's not implemented (old kernel) - * or because it doesn't understand the O_CLOEXEC flag. - */ - if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) { - fd = epoll_create(256); - - if (fd != -1) - uv__cloexec(fd, 1); - } - - loop->backend_fd = fd; - if (fd == -1) - return UV__ERR(errno); - - return 0; -} - - -void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { - struct epoll_event* events; - struct epoll_event dummy; - uintptr_t i; - uintptr_t nfds; - - assert(loop->watchers != NULL); - assert(fd >= 0); - - events = (struct epoll_event*) loop->watchers[loop->nwatchers]; - nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; - if (events != NULL) - /* Invalidate events with same file descriptor */ - for (i = 0; i < nfds; i++) - if (events[i].data.fd == fd) - events[i].data.fd = -1; - - /* Remove the file descriptor from the epoll. - * This avoids a problem where the same file description remains open - * in another process, causing repeated junk epoll events. - * - * We pass in a dummy epoll_event, to work around a bug in old kernels. - */ - if (loop->backend_fd >= 0) { - /* Work around a bug in kernels 3.10 to 3.19 where passing a struct that - * has the EPOLLWAKEUP flag set generates spurious audit syslog warnings. - */ - memset(&dummy, 0, sizeof(dummy)); - epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &dummy); - } -} - - -int uv__io_check_fd(uv_loop_t* loop, int fd) { - struct epoll_event e; - int rc; - - memset(&e, 0, sizeof(e)); - e.events = POLLIN; - e.data.fd = -1; - - rc = 0; - if (epoll_ctl(loop->backend_fd, EPOLL_CTL_ADD, fd, &e)) - if (errno != EEXIST) - rc = UV__ERR(errno); - - if (rc == 0) - if (epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &e)) - abort(); - - return rc; -} - - -void uv__io_poll(uv_loop_t* loop, int timeout) { - /* A bug in kernels < 2.6.37 makes timeouts larger than ~30 minutes - * effectively infinite on 32 bits architectures. To avoid blocking - * indefinitely, we cap the timeout and poll again if necessary. - * - * Note that "30 minutes" is a simplification because it depends on - * the value of CONFIG_HZ. The magic constant assumes CONFIG_HZ=1200, - * that being the largest value I have seen in the wild (and only once.) - */ - static const int max_safe_timeout = 1789569; - static int no_epoll_pwait_cached; - static int no_epoll_wait_cached; - int no_epoll_pwait; - int no_epoll_wait; - struct epoll_event events[1024]; - struct epoll_event* pe; - struct epoll_event e; - int real_timeout; - QUEUE* q; - uv__io_t* w; - sigset_t sigset; - uint64_t sigmask; - uint64_t base; - int have_signals; - int nevents; - int count; - int nfds; - int fd; - int op; - int i; - int user_timeout; - int reset_timeout; - - if (loop->nfds == 0) { - assert(QUEUE_EMPTY(&loop->watcher_queue)); - return; - } - - memset(&e, 0, sizeof(e)); - - while (!QUEUE_EMPTY(&loop->watcher_queue)) { - q = QUEUE_HEAD(&loop->watcher_queue); - QUEUE_REMOVE(q); - QUEUE_INIT(q); - - w = QUEUE_DATA(q, uv__io_t, watcher_queue); - assert(w->pevents != 0); - assert(w->fd >= 0); - assert(w->fd < (int) loop->nwatchers); - - e.events = w->pevents; - e.data.fd = w->fd; - - if (w->events == 0) - op = EPOLL_CTL_ADD; - else - op = EPOLL_CTL_MOD; - - /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching - * events, skip the syscall and squelch the events after epoll_wait(). - */ - if (epoll_ctl(loop->backend_fd, op, w->fd, &e)) { - if (errno != EEXIST) - abort(); - - assert(op == EPOLL_CTL_ADD); - - /* We've reactivated a file descriptor that's been watched before. */ - if (epoll_ctl(loop->backend_fd, EPOLL_CTL_MOD, w->fd, &e)) - abort(); - } - - w->events = w->pevents; - } - - sigmask = 0; - if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { - sigemptyset(&sigset); - sigaddset(&sigset, SIGPROF); - sigmask |= 1 << (SIGPROF - 1); - } - - assert(timeout >= -1); - base = loop->time; - count = 48; /* Benchmarks suggest this gives the best throughput. */ - real_timeout = timeout; - - if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) { - reset_timeout = 1; - user_timeout = timeout; - timeout = 0; - } else { - reset_timeout = 0; - user_timeout = 0; - } - - /* You could argue there is a dependency between these two but - * ultimately we don't care about their ordering with respect - * to one another. Worst case, we make a few system calls that - * could have been avoided because another thread already knows - * they fail with ENOSYS. Hardly the end of the world. - */ - no_epoll_pwait = uv__load_relaxed(&no_epoll_pwait_cached); - no_epoll_wait = uv__load_relaxed(&no_epoll_wait_cached); - - for (;;) { - /* Only need to set the provider_entry_time if timeout != 0. The function - * will return early if the loop isn't configured with UV_METRICS_IDLE_TIME. - */ - if (timeout != 0) - uv__metrics_set_provider_entry_time(loop); - - /* See the comment for max_safe_timeout for an explanation of why - * this is necessary. Executive summary: kernel bug workaround. - */ - if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout) - timeout = max_safe_timeout; - - if (sigmask != 0 && no_epoll_pwait != 0) - if (pthread_sigmask(SIG_BLOCK, &sigset, NULL)) - abort(); - - if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) { - nfds = epoll_pwait(loop->backend_fd, - events, - ARRAY_SIZE(events), - timeout, - &sigset); - if (nfds == -1 && errno == ENOSYS) { - uv__store_relaxed(&no_epoll_pwait_cached, 1); - no_epoll_pwait = 1; - } - } else { - nfds = epoll_wait(loop->backend_fd, - events, - ARRAY_SIZE(events), - timeout); - if (nfds == -1 && errno == ENOSYS) { - uv__store_relaxed(&no_epoll_wait_cached, 1); - no_epoll_wait = 1; - } - } - - if (sigmask != 0 && no_epoll_pwait != 0) - if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL)) - abort(); - - /* 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); - - if (reset_timeout != 0) { - timeout = user_timeout; - reset_timeout = 0; - } - - if (timeout == -1) - continue; - - if (timeout == 0) - return; - - /* We may have been inside the system call for longer than |timeout| - * milliseconds so we need to update the timestamp to avoid drift. - */ - goto update_timeout; - } - - if (nfds == -1) { - if (errno == ENOSYS) { - /* epoll_wait() or epoll_pwait() failed, try the other system call. */ - assert(no_epoll_wait == 0 || no_epoll_pwait == 0); - continue; - } - - if (errno != EINTR) - abort(); - - if (reset_timeout != 0) { - timeout = user_timeout; - reset_timeout = 0; - } - - if (timeout == -1) - continue; - - if (timeout == 0) - return; - - /* Interrupted by a signal. Update timeout and poll again. */ - goto update_timeout; - } - - have_signals = 0; - nevents = 0; - - { - /* Squelch a -Waddress-of-packed-member warning with gcc >= 9. */ - union { - struct epoll_event* events; - uv__io_t* watchers; - } x; - - x.events = events; - assert(loop->watchers != NULL); - loop->watchers[loop->nwatchers] = x.watchers; - loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; - } - - for (i = 0; i < nfds; i++) { - pe = events + i; - fd = pe->data.fd; - - /* Skip invalidated events, see uv__platform_invalidate_fd */ - if (fd == -1) - continue; - - assert(fd >= 0); - assert((unsigned) fd < loop->nwatchers); - - w = (uv__io_t*)loop->watchers[fd]; - - if (w == NULL) { - /* File descriptor that we've stopped watching, disarm it. - * - * Ignore all errors because we may be racing with another thread - * when the file descriptor is closed. - */ - epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, pe); - continue; - } - - /* Give users only events they're interested in. Prevents spurious - * callbacks when previous callback invocation in this loop has stopped - * the current watcher. Also, filters out events that users has not - * requested us to watch. - */ - pe->events &= w->pevents | POLLERR | POLLHUP; - - /* Work around an epoll quirk where it sometimes reports just the - * EPOLLERR or EPOLLHUP event. In order to force the event loop to - * move forward, we merge in the read/write events that the watcher - * is interested in; uv__read() and uv__write() will then deal with - * the error or hangup in the usual fashion. - * - * Note to self: happens when epoll reports EPOLLIN|EPOLLHUP, the user - * reads the available data, calls uv_read_stop(), then sometime later - * calls uv_read_start() again. By then, libuv has forgotten about the - * hangup and the kernel won't report EPOLLIN again because there's - * nothing left to read. If anything, libuv is to blame here. The - * current hack is just a quick bandaid; to properly fix it, libuv - * needs to remember the error/hangup event. We should get that for - * free when we switch over to edge-triggered I/O. - */ - if (pe->events == POLLERR || pe->events == POLLHUP) - pe->events |= - w->pevents & (POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI); - - if (pe->events != 0) { - /* Run signal watchers last. This also affects child process watchers - * because those are implemented in terms of signal watchers. - */ - if (w == &loop->signal_io_watcher) { - have_signals = 1; - } else { - uv__metrics_update_idle_time(loop); - w->cb(loop, w, pe->events); - } - - nevents++; - } - } - - if (reset_timeout != 0) { - timeout = user_timeout; - reset_timeout = 0; - } - - if (have_signals != 0) { - uv__metrics_update_idle_time(loop); - loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); - } - - loop->watchers[loop->nwatchers] = NULL; - loop->watchers[loop->nwatchers + 1] = NULL; - - if (have_signals != 0) - return; /* Event loop should cycle now so don't poll again. */ - - if (nevents != 0) { - if (nfds == ARRAY_SIZE(events) && --count != 0) { - /* Poll for more events but don't block this time. */ - timeout = 0; - continue; - } - return; - } - - if (timeout == 0) - return; - - if (timeout == -1) - continue; - -update_timeout: - assert(timeout > 0); - - real_timeout -= (loop->time - base); - if (real_timeout <= 0) - return; - - timeout = real_timeout; - } -} - diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/freebsd.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/freebsd.cpp index 6700ff61962..1bd63886b82 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/freebsd.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/freebsd.cpp @@ -91,7 +91,7 @@ uint64_t uv_get_free_memory(void) { size_t size = sizeof(freecount); if (sysctlbyname("vm.stats.vm.v_free_count", &freecount, &size, NULL, 0)) - return UV__ERR(errno); + return 0; return (uint64_t) freecount * sysconf(_SC_PAGESIZE); @@ -105,7 +105,7 @@ uint64_t uv_get_total_memory(void) { size_t size = sizeof(info); if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) - return UV__ERR(errno); + return 0; return (uint64_t) info; } @@ -116,6 +116,11 @@ uint64_t uv_get_constrained_memory(void) { } +uint64_t uv_get_available_memory(void) { + return uv_get_free_memory(); +} + + void uv_loadavg(double avg[3]) { struct loadavg info; size_t size = sizeof(info); @@ -264,30 +269,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { } -int uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) { -#if __FreeBSD__ >= 11 && !defined(__DragonFly__) - return sendmmsg(fd, - (struct mmsghdr*) mmsg, - vlen, - 0 /* flags */); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__recvmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) { -#if __FreeBSD__ >= 11 && !defined(__DragonFly__) - return recvmmsg(fd, - (struct mmsghdr*) mmsg, - vlen, - 0 /* flags */, - NULL /* timeout */); -#else - return errno = ENOSYS, -1; -#endif -} - ssize_t uv__fs_copy_file_range(int fd_in, off_t* off_in, diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/fs.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/fs.cpp index 1a615244f50..aba190a9c02 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/fs.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/fs.cpp @@ -46,9 +46,10 @@ #include #include +#include + #if defined(__DragonFly__) || \ defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || \ defined(__OpenBSD__) || \ defined(__NetBSD__) # define HAVE_PREADV 1 @@ -56,11 +57,16 @@ # define HAVE_PREADV 0 #endif +/* preadv() and pwritev() were added in Android N (level 24) */ +#if defined(__linux__) && !(defined(__ANDROID__) && __ANDROID_API__ < 24) +# define TRY_PREADV 1 +#endif + #if defined(__linux__) -# include "sys/utsname.h" +# include #endif -#if defined(__linux__) || defined(__sun) +#if defined(__sun) # include # include #endif @@ -79,7 +85,6 @@ #if defined(__APPLE__) || \ defined(__DragonFly__) || \ defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || \ defined(__OpenBSD__) || \ defined(__NetBSD__) # include @@ -256,7 +261,6 @@ static ssize_t uv__fs_futime(uv_fs_t* req) { #elif defined(__APPLE__) \ || defined(__DragonFly__) \ || defined(__FreeBSD__) \ - || defined(__FreeBSD_kernel__) \ || defined(__NetBSD__) \ || defined(__OpenBSD__) \ || defined(__sun) @@ -311,7 +315,7 @@ static int uv__fs_mkstemp(uv_fs_t* req) { static uv_once_t once = UV_ONCE_INIT; int r; #ifdef O_CLOEXEC - static int no_cloexec_support; + static std::atomic no_cloexec_support; #endif static const char pattern[] = "XXXXXX"; static const size_t pattern_size = sizeof(pattern) - 1; @@ -336,7 +340,8 @@ static int uv__fs_mkstemp(uv_fs_t* req) { uv_once(&once, uv__mkostemp_initonce); #ifdef O_CLOEXEC - if (uv__load_relaxed(&no_cloexec_support) == 0 && uv__mkostemp != NULL) { + if (atomic_load_explicit(&no_cloexec_support, std::memory_order_relaxed) == 0 && + uv__mkostemp != NULL) { r = uv__mkostemp(path, O_CLOEXEC); if (r >= 0) @@ -349,7 +354,7 @@ static int uv__fs_mkstemp(uv_fs_t* req) { /* We set the static variable so that next calls don't even try to use mkostemp. */ - uv__store_relaxed(&no_cloexec_support, 1); + atomic_store_explicit(&no_cloexec_support, 1, std::memory_order_relaxed); } #endif /* O_CLOEXEC */ @@ -458,8 +463,8 @@ static ssize_t uv__fs_preadv(uv_file fd, static ssize_t uv__fs_read(uv_fs_t* req) { -#if defined(__linux__) - static int no_preadv; +#if TRY_PREADV + static std::atomic no_preadv; #endif unsigned int iovmax; ssize_t result; @@ -482,20 +487,20 @@ 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 (uv__load_relaxed(&no_preadv)) retry: +# if TRY_PREADV + if (atomic_load_explicit(&no_preadv, std::memory_order_relaxed)) retry: # endif { result = uv__fs_preadv(req->file, req->bufs, req->nbufs, req->off); } -# if defined(__linux__) +# if TRY_PREADV else { - result = uv__preadv(req->file, - (struct iovec*)req->bufs, - req->nbufs, - req->off); + result = preadv(req->file, + (struct iovec*) req->bufs, + req->nbufs, + req->off); if (result == -1 && errno == ENOSYS) { - uv__store_relaxed(&no_preadv, 1); + atomic_store_explicit(&no_preadv, 1, std::memory_order_relaxed); goto retry; } } @@ -516,7 +521,7 @@ static ssize_t uv__fs_read(uv_fs_t* req) { if (result == -1 && errno == EOPNOTSUPP) { struct stat buf; ssize_t rc; - rc = fstat(req->file, &buf); + rc = uv__fstat(req->file, &buf); if (rc == 0 && S_ISDIR(buf.st_mode)) { errno = EISDIR; } @@ -527,19 +532,12 @@ static ssize_t uv__fs_read(uv_fs_t* req) { } -#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8) -#define UV_CONST_DIRENT uv__dirent_t -#else -#define UV_CONST_DIRENT const uv__dirent_t -#endif - - -static int uv__fs_scandir_filter(UV_CONST_DIRENT* dent) { +static int uv__fs_scandir_filter(const uv__dirent_t* dent) { return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0; } -static int uv__fs_scandir_sort(UV_CONST_DIRENT** a, UV_CONST_DIRENT** b) { +static int uv__fs_scandir_sort(const uv__dirent_t** a, const uv__dirent_t** b) { return strcmp((*a)->d_name, (*b)->d_name); } @@ -715,7 +713,7 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) { /* We may not have a real PATH_MAX. Read size of link. */ struct stat st; int ret; - ret = lstat(req->path, &st); + ret = uv__lstat(req->path, &st); if (ret != 0) return -1; if (!S_ISLNK(st.st_mode)) { @@ -907,31 +905,6 @@ static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) { #ifdef __linux__ -static unsigned uv__kernel_version(void) { - static unsigned cached_version; - struct utsname u; - unsigned version; - unsigned major; - unsigned minor; - unsigned patch; - - version = uv__load_relaxed(&cached_version); - if (version != 0) - return version; - - if (-1 == uname(&u)) - return 0; - - if (3 != sscanf(u.release, "%u.%u.%u", &major, &minor, &patch)) - return 0; - - version = major * 65536 + minor * 256 + patch; - uv__store_relaxed(&cached_version, version); - - return version; -} - - /* Pre-4.20 kernels have a bug where CephFS uses the RADOS copy-from command * in copy_file_range() when it shouldn't. There is no workaround except to * fall back to a regular copy. @@ -968,10 +941,10 @@ static int uv__is_cifs_or_smb(int fd) { static ssize_t uv__fs_try_copy_file_range(int in_fd, off_t* off, int out_fd, size_t len) { - static int no_copy_file_range_support; + static std::atomic no_copy_file_range_support; ssize_t r; - if (uv__load_relaxed(&no_copy_file_range_support)) { + if (atomic_load_explicit(&no_copy_file_range_support, std::memory_order_relaxed)) { errno = ENOSYS; return -1; } @@ -990,7 +963,7 @@ static ssize_t uv__fs_try_copy_file_range(int in_fd, off_t* off, errno = ENOSYS; /* Use fallback. */ break; case ENOSYS: - uv__store_relaxed(&no_copy_file_range_support, 1); + atomic_store_explicit(&no_copy_file_range_support, 1, std::memory_order_relaxed); break; case EPERM: /* It's been reported that CIFS spuriously fails. @@ -1061,10 +1034,7 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) { return -1; } -#elif defined(__APPLE__) || \ - defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) +#elif defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) { off_t len; ssize_t r; @@ -1088,15 +1058,6 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) { #endif len = 0; r = sendfile(in_fd, out_fd, req->off, req->bufsml[0].len, NULL, &len, 0); -#elif defined(__FreeBSD_kernel__) - len = 0; - r = bsd_sendfile(in_fd, - out_fd, - req->off, - req->bufsml[0].len, - NULL, - &len, - 0); #else /* The darwin sendfile takes len as an input for the length to send, * so make sure to initialize it with the caller's value. */ @@ -1148,7 +1109,6 @@ static ssize_t uv__fs_utime(uv_fs_t* req) { #elif defined(__APPLE__) \ || defined(__DragonFly__) \ || defined(__FreeBSD__) \ - || defined(__FreeBSD_kernel__) \ || defined(__NetBSD__) \ || defined(__OpenBSD__) struct timeval tv[2]; @@ -1190,7 +1150,6 @@ static ssize_t uv__fs_lutime(uv_fs_t* req) { #elif defined(__APPLE__) || \ defined(__DragonFly__) || \ defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || \ defined(__NetBSD__) struct timeval tv[2]; tv[0] = uv__fs_to_timeval(req->atime); @@ -1204,8 +1163,8 @@ static ssize_t uv__fs_lutime(uv_fs_t* req) { static ssize_t uv__fs_write(uv_fs_t* req) { -#if defined(__linux__) - static int no_pwritev; +#if TRY_PREADV + static std::atomic no_pwritev; #endif ssize_t r; @@ -1233,20 +1192,20 @@ 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 (no_pwritev) retry: +# if TRY_PREADV + if (atomic_load_explicit(&no_pwritev, std::memory_order_relaxed)) retry: # endif { r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off); } -# if defined(__linux__) +# if TRY_PREADV else { - r = uv__pwritev(req->file, - (struct iovec*) req->bufs, - req->nbufs, - req->off); + r = pwritev(req->file, + (struct iovec*) req->bufs, + req->nbufs, + req->off); if (r == -1 && errno == ENOSYS) { - no_pwritev = 1; + atomic_store_explicit(&no_pwritev, 1, std::memory_order_relaxed); goto retry; } } @@ -1288,7 +1247,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { return srcfd; /* Get the source file's mode. */ - if (fstat(srcfd, &src_statsbuf)) { + if (uv__fstat(srcfd, &src_statsbuf)) { err = UV__ERR(errno); goto out; } @@ -1316,7 +1275,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { destination are not the same file. If they are the same, bail out early. */ if ((req->flags & UV_FS_COPYFILE_EXCL) == 0) { /* Get the destination file's mode. */ - if (fstat(dstfd, &dst_statsbuf)) { + if (uv__fstat(dstfd, &dst_statsbuf)) { err = UV__ERR(errno); goto out; } @@ -1330,7 +1289,19 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { /* Truncate the file in case the destination already existed. */ if (ftruncate(dstfd, 0) != 0) { err = UV__ERR(errno); - goto out; + + /* ftruncate() on ceph-fuse fails with EACCES when the file is created + * with read only permissions. Since ftruncate() on a newly created + * file is a meaningless operation anyway, detect that condition + * and squelch the error. + */ + if (err != UV_EACCES) + goto out; + + if (dst_statsbuf.st_size > 0) + goto out; + + err = 0; } } @@ -1514,14 +1485,14 @@ static int uv__fs_statx(int fd, uv_stat_t* buf) { STATIC_ASSERT(UV_ENOSYS != -1); #ifdef __linux__ - static int no_statx; + static std::atomic no_statx; struct uv__statx statxbuf; int dirfd; int flags; int mode; int rc; - if (uv__load_relaxed(&no_statx)) + if (atomic_load_explicit(&no_statx, std::memory_order_relaxed)) return UV_ENOSYS; dirfd = AT_FDCWD; @@ -1555,30 +1526,11 @@ static int uv__fs_statx(int fd, * implemented, rc might return 1 with 0 set as the error code in which * case we return ENOSYS. */ - uv__store_relaxed(&no_statx, 1); + atomic_store_explicit(&no_statx, 1, std::memory_order_relaxed); return UV_ENOSYS; } - buf->st_dev = makedev(statxbuf.stx_dev_major, statxbuf.stx_dev_minor); - buf->st_mode = statxbuf.stx_mode; - buf->st_nlink = statxbuf.stx_nlink; - buf->st_uid = statxbuf.stx_uid; - buf->st_gid = statxbuf.stx_gid; - buf->st_rdev = makedev(statxbuf.stx_rdev_major, statxbuf.stx_rdev_minor); - buf->st_ino = statxbuf.stx_ino; - buf->st_size = statxbuf.stx_size; - buf->st_blksize = statxbuf.stx_blksize; - buf->st_blocks = statxbuf.stx_blocks; - buf->st_atim.tv_sec = statxbuf.stx_atime.tv_sec; - buf->st_atim.tv_nsec = statxbuf.stx_atime.tv_nsec; - buf->st_mtim.tv_sec = statxbuf.stx_mtime.tv_sec; - buf->st_mtim.tv_nsec = statxbuf.stx_mtime.tv_nsec; - buf->st_ctim.tv_sec = statxbuf.stx_ctime.tv_sec; - buf->st_ctim.tv_nsec = statxbuf.stx_ctime.tv_nsec; - buf->st_birthtim.tv_sec = statxbuf.stx_btime.tv_sec; - buf->st_birthtim.tv_nsec = statxbuf.stx_btime.tv_nsec; - buf->st_flags = 0; - buf->st_gen = 0; + uv__statx_to_stat(&statxbuf, buf); return 0; #else @@ -1595,7 +1547,7 @@ static int uv__fs_stat(const char *path, uv_stat_t *buf) { if (ret != UV_ENOSYS) return ret; - ret = stat(path, &pbuf); + ret = uv__stat(path, &pbuf); if (ret == 0) uv__to_stat(&pbuf, buf); @@ -1611,7 +1563,7 @@ static int uv__fs_lstat(const char *path, uv_stat_t *buf) { if (ret != UV_ENOSYS) return ret; - ret = lstat(path, &pbuf); + ret = uv__lstat(path, &pbuf); if (ret == 0) uv__to_stat(&pbuf, buf); @@ -1627,7 +1579,7 @@ static int uv__fs_fstat(int fd, uv_stat_t *buf) { if (ret != UV_ENOSYS) return ret; - ret = fstat(fd, &pbuf); + ret = uv__fstat(fd, &pbuf); if (ret == 0) uv__to_stat(&pbuf, buf); @@ -1822,6 +1774,9 @@ int uv_fs_chown(uv_loop_t* loop, int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { INIT(CLOSE); req->file = file; + if (cb != NULL) + if (uv__iou_fs_close(loop, req)) + return 0; POST; } @@ -1869,6 +1824,9 @@ int uv_fs_lchown(uv_loop_t* loop, int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { INIT(FDATASYNC); req->file = file; + if (cb != NULL) + if (uv__iou_fs_fsync_or_fdatasync(loop, req, /* IORING_FSYNC_DATASYNC */ 1)) + return 0; POST; } @@ -1876,6 +1834,9 @@ int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { INIT(FSTAT); req->file = file; + if (cb != NULL) + if (uv__iou_fs_statx(loop, req, /* is_fstat */ 1, /* is_lstat */ 0)) + return 0; POST; } @@ -1883,6 +1844,9 @@ int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { INIT(FSYNC); req->file = file; + if (cb != NULL) + if (uv__iou_fs_fsync_or_fdatasync(loop, req, /* no flags */ 0)) + return 0; POST; } @@ -1929,6 +1893,9 @@ int uv_fs_lutime(uv_loop_t* loop, int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { INIT(LSTAT); PATH; + if (cb != NULL) + if (uv__iou_fs_statx(loop, req, /* is_fstat */ 0, /* is_lstat */ 1)) + return 0; POST; } @@ -1940,6 +1907,9 @@ int uv_fs_link(uv_loop_t* loop, uv_fs_cb cb) { INIT(LINK); PATH2; + if (cb != NULL) + if (uv__iou_fs_link(loop, req)) + return 0; POST; } @@ -1952,6 +1922,9 @@ int uv_fs_mkdir(uv_loop_t* loop, INIT(MKDIR); PATH; req->mode = mode; + if (cb != NULL) + if (uv__iou_fs_mkdir(loop, req)) + return 0; POST; } @@ -1990,6 +1963,9 @@ int uv_fs_open(uv_loop_t* loop, PATH; req->flags = flags; req->mode = mode; + if (cb != NULL) + if (uv__iou_fs_open(loop, req)) + return 0; POST; } @@ -2018,6 +1994,11 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, memcpy(req->bufs, bufs, nbufs * sizeof(*bufs)); req->off = off; + + if (cb != NULL) + if (uv__iou_fs_read_or_write(loop, req, /* is_read */ 1)) + return 0; + POST; } @@ -2095,6 +2076,9 @@ int uv_fs_rename(uv_loop_t* loop, uv_fs_cb cb) { INIT(RENAME); PATH2; + if (cb != NULL) + if (uv__iou_fs_rename(loop, req)) + return 0; POST; } @@ -2125,6 +2109,9 @@ int uv_fs_sendfile(uv_loop_t* loop, int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { INIT(STAT); PATH; + if (cb != NULL) + if (uv__iou_fs_statx(loop, req, /* is_fstat */ 0, /* is_lstat */ 0)) + return 0; POST; } @@ -2138,6 +2125,9 @@ int uv_fs_symlink(uv_loop_t* loop, INIT(SYMLINK); PATH2; req->flags = flags; + if (cb != NULL) + if (uv__iou_fs_symlink(loop, req)) + return 0; POST; } @@ -2145,6 +2135,9 @@ int uv_fs_symlink(uv_loop_t* loop, int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { INIT(UNLINK); PATH; + if (cb != NULL) + if (uv__iou_fs_unlink(loop, req)) + return 0; POST; } @@ -2188,6 +2181,11 @@ int uv_fs_write(uv_loop_t* loop, memcpy(req->bufs, bufs, nbufs * sizeof(*bufs)); req->off = off; + + if (cb != NULL) + if (uv__iou_fs_read_or_write(loop, req, /* is_read */ 0)) + return 0; + POST; } @@ -2196,7 +2194,7 @@ void uv_fs_req_cleanup(uv_fs_t* req) { if (req == NULL) return; - /* Only necessary for asychronous requests, i.e., requests with a callback. + /* Only necessary for asynchronous requests, i.e., requests with a callback. * Synchronous ones don't copy their arguments and have req->path and * req->new_path pointing to user-owned memory. UV_FS_MKDTEMP and * UV_FS_MKSTEMP are the exception to the rule, they always allocate memory. diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/fsevents.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/fsevents.cpp index 648c8a98b81..c31d08ba37c 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/fsevents.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/fsevents.cpp @@ -80,13 +80,13 @@ enum uv__cf_loop_signal_type_e { typedef enum uv__cf_loop_signal_type_e uv__cf_loop_signal_type_t; struct uv__cf_loop_signal_s { - QUEUE member; + struct uv__queue member; uv_fs_event_t* handle; uv__cf_loop_signal_type_t type; }; struct uv__fsevents_event_s { - QUEUE member; + struct uv__queue member; int events; char path[1]; }; @@ -98,7 +98,7 @@ struct uv__cf_loop_state_s { FSEventStreamRef fsevent_stream; uv_sem_t fsevent_sem; uv_mutex_t fsevent_mutex; - void* fsevent_handles[2]; + struct uv__queue fsevent_handles; unsigned int fsevent_handle_count; }; @@ -132,7 +132,6 @@ static void (*pCFRunLoopWakeUp)(CFRunLoopRef); static CFStringRef (*pCFStringCreateWithFileSystemRepresentation)( CFAllocatorRef, const char*); -static CFStringEncoding (*pCFStringGetSystemEncoding)(void); static CFStringRef (*pkCFRunLoopDefaultMode); static FSEventStreamRef (*pFSEventStreamCreate)(CFAllocatorRef, FSEventStreamCallback, @@ -141,7 +140,6 @@ static FSEventStreamRef (*pFSEventStreamCreate)(CFAllocatorRef, FSEventStreamEventId, CFTimeInterval, FSEventStreamCreateFlags); -static void (*pFSEventStreamFlushSync)(FSEventStreamRef); static void (*pFSEventStreamInvalidate)(FSEventStreamRef); static void (*pFSEventStreamRelease)(FSEventStreamRef); static void (*pFSEventStreamScheduleWithRunLoop)(FSEventStreamRef, @@ -152,22 +150,22 @@ static void (*pFSEventStreamStop)(FSEventStreamRef); #define UV__FSEVENTS_PROCESS(handle, block) \ do { \ - QUEUE events; \ - QUEUE* q; \ + struct uv__queue events; \ + struct uv__queue* q; \ uv__fsevents_event_t* event; \ int err; \ uv_mutex_lock(&(handle)->cf_mutex); \ /* Split-off all events and empty original queue */ \ - QUEUE_MOVE(&(handle)->cf_events, &events); \ + uv__queue_move(&(handle)->cf_events, &events); \ /* Get error (if any) and zero original one */ \ err = (handle)->cf_error; \ (handle)->cf_error = 0; \ uv_mutex_unlock(&(handle)->cf_mutex); \ /* Loop through events, deallocating each after processing */ \ - while (!QUEUE_EMPTY(&events)) { \ - q = QUEUE_HEAD(&events); \ - event = QUEUE_DATA(q, uv__fsevents_event_t, member); \ - QUEUE_REMOVE(q); \ + while (!uv__queue_empty(&events)) { \ + q = uv__queue_head(&events); \ + event = uv__queue_data(q, uv__fsevents_event_t, member); \ + uv__queue_remove(q); \ /* NOTE: Checking uv__is_active() is required here, because handle \ * callback may close handle and invoking it after it will lead to \ * incorrect behaviour */ \ @@ -195,14 +193,14 @@ static void uv__fsevents_cb(uv_async_t* cb) { /* Runs in CF thread, pushed event into handle's event list */ static void uv__fsevents_push_event(uv_fs_event_t* handle, - QUEUE* events, + struct uv__queue* events, int err) { assert(events != NULL || err != 0); uv_mutex_lock(&handle->cf_mutex); /* Concatenate two queues */ if (events != NULL) - QUEUE_ADD(&handle->cf_events, events); + uv__queue_add(&handle->cf_events, events); /* Propagate error */ if (err != 0) @@ -226,12 +224,12 @@ static void uv__fsevents_event_cb(const FSEventStreamRef streamRef, char* path; char* pos; uv_fs_event_t* handle; - QUEUE* q; + struct uv__queue* q; uv_loop_t* loop; uv__cf_loop_state_t* state; uv__fsevents_event_t* event; FSEventStreamEventFlags flags; - QUEUE head; + struct uv__queue head; loop = (uv_loop_t*)info; state = (uv__cf_loop_state_t*)loop->cf_state; @@ -240,9 +238,9 @@ static void uv__fsevents_event_cb(const FSEventStreamRef streamRef, /* For each handle */ uv_mutex_lock(&state->fsevent_mutex); - QUEUE_FOREACH(q, &state->fsevent_handles) { - handle = QUEUE_DATA(q, uv_fs_event_t, cf_member); - QUEUE_INIT(&head); + uv__queue_foreach(q, &state->fsevent_handles) { + handle = uv__queue_data(q, uv_fs_event_t, cf_member); + uv__queue_init(&head); /* Process and filter out events */ for (i = 0; i < numEvents; i++) { @@ -320,10 +318,10 @@ static void uv__fsevents_event_cb(const FSEventStreamRef streamRef, event->events = UV_CHANGE; } - QUEUE_INSERT_TAIL(&head, &event->member); + uv__queue_insert_tail(&head, &event->member); } - if (!QUEUE_EMPTY(&head)) + if (!uv__queue_empty(&head)) uv__fsevents_push_event(handle, &head, 0); } uv_mutex_unlock(&state->fsevent_mutex); @@ -331,8 +329,9 @@ static void uv__fsevents_event_cb(const FSEventStreamRef streamRef, /* Runs in CF thread */ -static int uv__fsevents_create_stream(uv_loop_t* loop, CFArrayRef paths) { - uv__cf_loop_state_t* state; +static int uv__fsevents_create_stream(uv__cf_loop_state_t* state, + uv_loop_t* loop, + CFArrayRef paths) { FSEventStreamContext ctx; FSEventStreamRef ref; CFAbsoluteTime latency; @@ -373,10 +372,7 @@ static int uv__fsevents_create_stream(uv_loop_t* loop, CFArrayRef paths) { flags); assert(ref != NULL); - state = (uv__cf_loop_state_t*)loop->cf_state; - pFSEventStreamScheduleWithRunLoop(ref, - state->loop, - *pkCFRunLoopDefaultMode); + pFSEventStreamScheduleWithRunLoop(ref, state->loop, *pkCFRunLoopDefaultMode); if (!pFSEventStreamStart(ref)) { pFSEventStreamInvalidate(ref); pFSEventStreamRelease(ref); @@ -389,11 +385,7 @@ static int uv__fsevents_create_stream(uv_loop_t* loop, CFArrayRef paths) { /* Runs in CF thread */ -static void uv__fsevents_destroy_stream(uv_loop_t* loop) { - uv__cf_loop_state_t* state; - - state = (uv__cf_loop_state_t*)loop->cf_state; - +static void uv__fsevents_destroy_stream(uv__cf_loop_state_t* state) { if (state->fsevent_stream == NULL) return; @@ -408,10 +400,10 @@ static void uv__fsevents_destroy_stream(uv_loop_t* loop) { /* Runs in CF thread, when there're new fsevent handles to add to stream */ -static void uv__fsevents_reschedule(uv_fs_event_t* handle, +static void uv__fsevents_reschedule(uv__cf_loop_state_t* state, + uv_loop_t* loop, uv__cf_loop_signal_type_t type) { - uv__cf_loop_state_t* state; - QUEUE* q; + struct uv__queue* q; uv_fs_event_t* curr; CFArrayRef cf_paths; CFStringRef* paths; @@ -419,7 +411,6 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle, int err; unsigned int path_count; - state = (uv__cf_loop_state_t*)handle->loop->cf_state; paths = NULL; cf_paths = NULL; err = 0; @@ -438,7 +429,7 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle, uv_mutex_unlock(&state->fsevent_mutex); /* Destroy previous FSEventStream */ - uv__fsevents_destroy_stream(handle->loop); + uv__fsevents_destroy_stream(state); /* Any failure below will be a memory failure */ err = UV_ENOMEM; @@ -455,9 +446,9 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle, q = &state->fsevent_handles; for (; i < path_count; i++) { - q = QUEUE_NEXT(q); + q = uv__queue_next(q); assert(q != &state->fsevent_handles); - curr = QUEUE_DATA(q, uv_fs_event_t, cf_member); + curr = uv__queue_data(q, uv_fs_event_t, cf_member); assert(curr->realpath != NULL); paths[i] = @@ -478,7 +469,7 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle, err = UV_ENOMEM; goto final; } - err = uv__fsevents_create_stream(handle->loop, cf_paths); + err = uv__fsevents_create_stream(state, loop, cf_paths); } final: @@ -495,8 +486,8 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle, /* Broadcast error to all handles */ uv_mutex_lock(&state->fsevent_mutex); - QUEUE_FOREACH(q, &state->fsevent_handles) { - curr = QUEUE_DATA(q, uv_fs_event_t, cf_member); + uv__queue_foreach(q, &state->fsevent_handles) { + curr = uv__queue_data(q, uv_fs_event_t, cf_member); uv__fsevents_push_event(curr, NULL, err); } uv_mutex_unlock(&state->fsevent_mutex); @@ -563,10 +554,8 @@ static int uv__fsevents_global_init(void) { V(core_foundation_handle, CFRunLoopStop); V(core_foundation_handle, CFRunLoopWakeUp); V(core_foundation_handle, CFStringCreateWithFileSystemRepresentation); - V(core_foundation_handle, CFStringGetSystemEncoding); V(core_foundation_handle, kCFRunLoopDefaultMode); V(core_services_handle, FSEventStreamCreate); - V(core_services_handle, FSEventStreamFlushSync); V(core_services_handle, FSEventStreamInvalidate); V(core_services_handle, FSEventStreamRelease); V(core_services_handle, FSEventStreamScheduleWithRunLoop); @@ -617,7 +606,7 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) { if (err) goto fail_sem_init; - QUEUE_INIT(&loop->cf_signals); + uv__queue_init(&loop->cf_signals); err = uv_sem_init(&state->fsevent_sem, 0); if (err) @@ -627,7 +616,7 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) { if (err) goto fail_fsevent_mutex_init; - QUEUE_INIT(&state->fsevent_handles); + uv__queue_init(&state->fsevent_handles); state->fsevent_need_reschedule = 0; state->fsevent_handle_count = 0; @@ -686,7 +675,7 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) { void uv__fsevents_loop_delete(uv_loop_t* loop) { uv__cf_loop_signal_t* s; uv__cf_loop_state_t* state; - QUEUE* q; + struct uv__queue* q; if (loop->cf_state == NULL) return; @@ -699,10 +688,10 @@ void uv__fsevents_loop_delete(uv_loop_t* loop) { uv_mutex_destroy(&loop->cf_mutex); /* Free any remaining data */ - while (!QUEUE_EMPTY(&loop->cf_signals)) { - q = QUEUE_HEAD(&loop->cf_signals); - s = QUEUE_DATA(q, uv__cf_loop_signal_t, member); - QUEUE_REMOVE(q); + while (!uv__queue_empty(&loop->cf_signals)) { + q = uv__queue_head(&loop->cf_signals); + s = uv__queue_data(q, uv__cf_loop_signal_t, member); + uv__queue_remove(q); uv__free(s); } @@ -746,28 +735,28 @@ static void* uv__cf_loop_runner(void* arg) { static void uv__cf_loop_cb(void* arg) { uv_loop_t* loop; uv__cf_loop_state_t* state; - QUEUE* item; - QUEUE split_head; + struct uv__queue* item; + struct uv__queue split_head; uv__cf_loop_signal_t* s; loop = (uv_loop_t*)arg; state = (uv__cf_loop_state_t*)loop->cf_state; uv_mutex_lock(&loop->cf_mutex); - QUEUE_MOVE(&loop->cf_signals, &split_head); + uv__queue_move(&loop->cf_signals, &split_head); uv_mutex_unlock(&loop->cf_mutex); - while (!QUEUE_EMPTY(&split_head)) { - item = QUEUE_HEAD(&split_head); - QUEUE_REMOVE(item); + while (!uv__queue_empty(&split_head)) { + item = uv__queue_head(&split_head); + uv__queue_remove(item); - s = QUEUE_DATA(item, uv__cf_loop_signal_t, member); + s = uv__queue_data(item, uv__cf_loop_signal_t, member); /* This was a termination signal */ if (s->handle == NULL) pCFRunLoopStop(state->loop); else - uv__fsevents_reschedule(s->handle, s->type); + uv__fsevents_reschedule(state, loop, s->type); uv__free(s); } @@ -789,7 +778,7 @@ int uv__cf_loop_signal(uv_loop_t* loop, item->type = type; uv_mutex_lock(&loop->cf_mutex); - QUEUE_INSERT_TAIL(&loop->cf_signals, &item->member); + uv__queue_insert_tail(&loop->cf_signals, &item->member); state = (uv__cf_loop_state_t*)loop->cf_state; assert(state != NULL); @@ -818,7 +807,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) { handle->realpath_len = strlen(handle->realpath); /* Initialize event queue */ - QUEUE_INIT(&handle->cf_events); + uv__queue_init(&handle->cf_events); handle->cf_error = 0; /* @@ -843,7 +832,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) { /* Insert handle into the list */ state = (uv__cf_loop_state_t*)handle->loop->cf_state; uv_mutex_lock(&state->fsevent_mutex); - QUEUE_INSERT_TAIL(&state->fsevent_handles, &handle->cf_member); + uv__queue_insert_tail(&state->fsevent_handles, &handle->cf_member); state->fsevent_handle_count++; state->fsevent_need_reschedule = 1; uv_mutex_unlock(&state->fsevent_mutex); @@ -883,7 +872,7 @@ int uv__fsevents_close(uv_fs_event_t* handle) { /* Remove handle from the list */ state = (uv__cf_loop_state_t*)handle->loop->cf_state; uv_mutex_lock(&state->fsevent_mutex); - QUEUE_REMOVE(&handle->cf_member); + uv__queue_remove(&handle->cf_member); state->fsevent_handle_count--; state->fsevent_need_reschedule = 1; uv_mutex_unlock(&state->fsevent_mutex); diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/ibmi.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/ibmi.cpp index 56af31e979f..5e0fa98d104 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/ibmi.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/ibmi.cpp @@ -249,6 +249,11 @@ uint64_t uv_get_constrained_memory(void) { } +uint64_t uv_get_available_memory(void) { + return uv_get_free_memory(); +} + + void uv_loadavg(double avg[3]) { SSTS0200 rcvr; diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/internal.h b/wpinet/src/main/native/thirdparty/libuv/src/unix/internal.h index 2b6541576bd..854d98a16a7 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/internal.h +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/internal.h @@ -26,21 +26,34 @@ #include #include /* _POSIX_PATH_MAX, PATH_MAX */ +#include #include /* abort */ #include /* strrchr */ #include /* O_CLOEXEC and O_NONBLOCK, if supported. */ #include #include #include +#include +#include + +#define uv__msan_unpoison(p, n) \ + do { \ + (void) (p); \ + (void) (n); \ + } while (0) + +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) +# include +# undef uv__msan_unpoison +# define uv__msan_unpoison __msan_unpoison +# endif +#endif #if defined(__STRICT_ANSI__) # define inline __inline #endif -#if defined(__linux__) -# include "linux-syscalls.h" -#endif /* __linux__ */ - #if defined(__MVS__) # include "os390-syscalls.h" #endif /* __MVS__ */ @@ -79,13 +92,11 @@ # define UV__PATH_MAX 8192 #endif -#if defined(__ANDROID__) -int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset); -# ifdef pthread_sigmask -# undef pthread_sigmask -# endif -# define pthread_sigmask(how, set, oldset) uv__pthread_sigmask(how, set, oldset) -#endif +union uv__sockaddr { + struct sockaddr_in6 in6; + struct sockaddr_in in; + struct sockaddr addr; +}; #define ACCESS_ONCE(type, var) \ (*(volatile type*) &(var)) @@ -166,12 +177,42 @@ struct uv__stream_queued_fds_s { int fds[1]; }; +#ifdef __linux__ +struct uv__statx_timestamp { + int64_t tv_sec; + uint32_t tv_nsec; + int32_t unused0; +}; + +struct uv__statx { + uint32_t stx_mask; + uint32_t stx_blksize; + uint64_t stx_attributes; + uint32_t stx_nlink; + uint32_t stx_uid; + uint32_t stx_gid; + uint16_t stx_mode; + uint16_t unused0; + uint64_t stx_ino; + uint64_t stx_size; + uint64_t stx_blocks; + uint64_t stx_attributes_mask; + struct uv__statx_timestamp stx_atime; + struct uv__statx_timestamp stx_btime; + struct uv__statx_timestamp stx_ctime; + struct uv__statx_timestamp stx_mtime; + uint32_t stx_rdev_major; + uint32_t stx_rdev_minor; + uint32_t stx_dev_major; + uint32_t stx_dev_minor; + uint64_t unused1[14]; +}; +#endif /* __linux__ */ #if defined(_AIX) || \ defined(__APPLE__) || \ defined(__DragonFly__) || \ defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || \ defined(__linux__) || \ defined(__OpenBSD__) || \ defined(__NetBSD__) @@ -260,10 +301,10 @@ int uv__signal_loop_fork(uv_loop_t* loop); /* platform specific */ uint64_t uv__hrtime(uv_clocktype_t type); int uv__kqueue_init(uv_loop_t* loop); -int uv__epoll_init(uv_loop_t* loop); int uv__platform_loop_init(uv_loop_t* loop); void uv__platform_loop_delete(uv_loop_t* loop); void uv__platform_invalidate_fd(uv_loop_t* loop, int fd); +int uv__process_init(uv_loop_t* loop); /* various */ void uv__async_close(uv_async_t* handle); @@ -280,7 +321,6 @@ size_t uv__thread_stack_size(void); void uv__udp_close(uv_udp_t* handle); void uv__udp_finish_close(uv_udp_t* handle); FILE* uv__open_file(const char* path); -int uv__getpwuid_r(uv_passwd_t* pwd); int uv__search_path(const char* prog, char* buf, size_t* buflen); void uv__wait_children(uv_loop_t* loop); @@ -291,6 +331,38 @@ int uv__random_getentropy(void* buf, size_t buflen); int uv__random_readpath(const char* path, void* buf, size_t buflen); int uv__random_sysctl(void* buf, size_t buflen); +/* io_uring */ +#ifdef __linux__ +int uv__iou_fs_close(uv_loop_t* loop, uv_fs_t* req); +int uv__iou_fs_fsync_or_fdatasync(uv_loop_t* loop, + uv_fs_t* req, + uint32_t fsync_flags); +int uv__iou_fs_link(uv_loop_t* loop, uv_fs_t* req); +int uv__iou_fs_mkdir(uv_loop_t* loop, uv_fs_t* req); +int uv__iou_fs_open(uv_loop_t* loop, uv_fs_t* req); +int uv__iou_fs_read_or_write(uv_loop_t* loop, + uv_fs_t* req, + int is_read); +int uv__iou_fs_rename(uv_loop_t* loop, uv_fs_t* req); +int uv__iou_fs_statx(uv_loop_t* loop, + uv_fs_t* req, + int is_fstat, + int is_lstat); +int uv__iou_fs_symlink(uv_loop_t* loop, uv_fs_t* req); +int uv__iou_fs_unlink(uv_loop_t* loop, uv_fs_t* req); +#else +#define uv__iou_fs_close(loop, req) 0 +#define uv__iou_fs_fsync_or_fdatasync(loop, req, fsync_flags) 0 +#define uv__iou_fs_link(loop, req) 0 +#define uv__iou_fs_mkdir(loop, req) 0 +#define uv__iou_fs_open(loop, req) 0 +#define uv__iou_fs_read_or_write(loop, req, is_read) 0 +#define uv__iou_fs_rename(loop, req) 0 +#define uv__iou_fs_statx(loop, req, is_fstat, is_lstat) 0 +#define uv__iou_fs_symlink(loop, req) 0 +#define uv__iou_fs_unlink(loop, req) 0 +#endif + #if defined(__APPLE__) int uv___stream_fd(const uv_stream_t* handle); #define uv__stream_fd(handle) (uv___stream_fd((const uv_stream_t*) (handle))) @@ -324,8 +396,52 @@ UV_UNUSED(static const char* uv__basename_r(const char* path)) { return s + 1; } +UV_UNUSED(static int uv__fstat(int fd, struct stat* s)) { + int rc; + + rc = fstat(fd, s); + if (rc >= 0) + uv__msan_unpoison(s, sizeof(*s)); + + return rc; +} + +UV_UNUSED(static int uv__lstat(const char* path, struct stat* s)) { + int rc; + + rc = lstat(path, s); + if (rc >= 0) + uv__msan_unpoison(s, sizeof(*s)); + + return rc; +} + +UV_UNUSED(static int uv__stat(const char* path, struct stat* s)) { + int rc; + + rc = stat(path, s); + if (rc >= 0) + uv__msan_unpoison(s, sizeof(*s)); + + return rc; +} + #if defined(__linux__) -int uv__inotify_fork(uv_loop_t* loop, void* old_watchers); +ssize_t +uv__fs_copy_file_range(int fd_in, + off_t* off_in, + int fd_out, + off_t* off_out, + size_t len, + unsigned int flags); +int uv__statx(int dirfd, + const char* path, + int flags, + unsigned int mask, + struct uv__statx* statxbuf); +void uv__statx_to_stat(const struct uv__statx* statxbuf, uv_stat_t* buf); +ssize_t uv__getrandom(void* buf, size_t buflen, unsigned flags); +unsigned uv__kernel_version(void); #endif typedef int (*uv__peersockfunc)(int, struct sockaddr*, socklen_t*); @@ -335,22 +451,6 @@ int uv__getsockpeername(const uv_handle_t* handle, struct sockaddr* name, int* namelen); -#if defined(__linux__) || \ - defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || \ - defined(__DragonFly__) -#define HAVE_MMSG 1 -struct uv__mmsghdr { - struct msghdr msg_hdr; - unsigned int msg_len; -}; - -int uv__recvmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen); -int uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen); -#else -#define HAVE_MMSG 0 -#endif - #if defined(__sun) #if !defined(_POSIX_VERSION) || _POSIX_VERSION < 200809L size_t strnlen(const char* s, size_t maxlen); @@ -367,5 +467,10 @@ uv__fs_copy_file_range(int fd_in, unsigned int flags); #endif +#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 1301000) +#define UV__CPU_AFFINITY_SUPPORTED 1 +#else +#define UV__CPU_AFFINITY_SUPPORTED 0 +#endif #endif /* UV_UNIX_INTERNAL_H_ */ diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/kqueue.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/kqueue.cpp index 86eb529bcda..ffe0f9191cc 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/kqueue.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/kqueue.cpp @@ -34,6 +34,8 @@ #include #include +#include + /* * Required on * - Until at least FreeBSD 11.0 @@ -60,7 +62,7 @@ int uv__kqueue_init(uv_loop_t* loop) { #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 -static int uv__has_forked_with_cfrunloop; +static std::atomic uv__has_forked_with_cfrunloop; #endif int uv__io_fork(uv_loop_t* loop) { @@ -82,7 +84,9 @@ int uv__io_fork(uv_loop_t* loop) { process. So we sidestep the issue by pretending like we never started it in the first place. */ - uv__store_relaxed(&uv__has_forked_with_cfrunloop, 1); + atomic_store_explicit(&uv__has_forked_with_cfrunloop, + 1, + std::memory_order_relaxed); uv__free(loop->cf_state); loop->cf_state = NULL; } @@ -109,13 +113,29 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) { } +static void uv__kqueue_delete(int kqfd, const struct kevent *ev) { + struct kevent change; + + EV_SET(&change, ev->ident, ev->filter, EV_DELETE, 0, 0, 0); + + if (0 == kevent(kqfd, &change, 1, NULL, 0, NULL)) + return; + + if (errno == EBADF || errno == ENOENT) + return; + + abort(); +} + + void uv__io_poll(uv_loop_t* loop, int timeout) { + uv__loop_internal_fields_t* lfields; struct kevent events[1024]; struct kevent* ev; struct timespec spec; unsigned int nevents; unsigned int revents; - QUEUE* q; + struct uv__queue* q; uv__io_t* w; uv_process_t* process; sigset_t* pset; @@ -134,18 +154,19 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { int reset_timeout; if (loop->nfds == 0) { - assert(QUEUE_EMPTY(&loop->watcher_queue)); + assert(uv__queue_empty(&loop->watcher_queue)); return; } + lfields = uv__get_internal_fields(loop); nevents = 0; - while (!QUEUE_EMPTY(&loop->watcher_queue)) { - q = QUEUE_HEAD(&loop->watcher_queue); - QUEUE_REMOVE(q); - QUEUE_INIT(q); + while (!uv__queue_empty(&loop->watcher_queue)) { + q = uv__queue_head(&loop->watcher_queue); + uv__queue_remove(q); + uv__queue_init(q); - w = QUEUE_DATA(q, uv__io_t, watcher_queue); + w = uv__queue_data(q, uv__io_t, watcher_queue); assert(w->pevents != 0); assert(w->fd >= 0); assert(w->fd < (int) loop->nwatchers); @@ -205,7 +226,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { base = loop->time; count = 48; /* Benchmarks suggest this gives the best throughput. */ - if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) { + if (lfields->flags & UV_METRICS_IDLE_TIME) { reset_timeout = 1; user_timeout = timeout; timeout = 0; @@ -228,6 +249,12 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { if (pset != NULL) pthread_sigmask(SIG_BLOCK, pset, NULL); + /* Store the current timeout in a location that's globally accessible so + * other locations like uv__work_done() can determine whether the queue + * of events in the callback were waiting when poll was called. + */ + lfields->current_timeout = timeout; + nfds = kevent(loop->backend_fd, events, nevents, @@ -235,6 +262,9 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { ARRAY_SIZE(events), timeout == -1 ? NULL : &spec); + if (nfds == -1) + assert(errno == EINTR); + if (pset != NULL) pthread_sigmask(SIG_UNBLOCK, pset, NULL); @@ -242,36 +272,26 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { * 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) { - if (reset_timeout != 0) { - timeout = user_timeout; - reset_timeout = 0; - if (timeout == -1) - continue; - if (timeout > 0) - goto update_timeout; + uv__update_time(loop); + + if (nfds == 0 || nfds == -1) { + /* If kqueue is empty or interrupted, we might still have children ready + * to reap immediately. */ + if (loop->flags & UV_LOOP_REAP_CHILDREN) { + loop->flags &= ~UV_LOOP_REAP_CHILDREN; + uv__wait_children(loop); + assert((reset_timeout == 0 ? timeout : user_timeout) == 0); + return; /* Equivalent to fall-through behavior. */ } - assert(timeout != -1); - return; - } - - if (nfds == -1) { - if (errno != EINTR) - abort(); - if (reset_timeout != 0) { timeout = user_timeout; reset_timeout = 0; - } - - if (timeout == 0) + } else if (nfds == 0) { + /* Reached the user timeout value. */ + assert(timeout != -1); return; - - if (timeout == -1) - continue; + } /* Interrupted by a signal. Update timeout and poll again. */ goto update_timeout; @@ -289,8 +309,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { /* Handle kevent NOTE_EXIT results */ if (ev->filter == EVFILT_PROC) { - QUEUE_FOREACH(q, &loop->process_handles) { - process = QUEUE_DATA(q, uv_process_t, queue); + uv__queue_foreach(q, &loop->process_handles) { + process = uv__queue_data(q, uv_process_t, queue); if (process->pid == fd) { process->flags |= UV_HANDLE_REAP; loop->flags |= UV_LOOP_REAP_CHILDREN; @@ -307,15 +327,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { w = (uv__io_t*)loop->watchers[fd]; if (w == NULL) { - /* File descriptor that we've stopped watching, disarm it. - * TODO: batch up. */ - struct kevent events[1]; - - EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); - if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL)) - if (errno != EBADF && errno != ENOENT) - abort(); - + /* File descriptor that we've stopped watching, disarm it. */ + uv__kqueue_delete(loop->backend_fd, ev); continue; } @@ -331,47 +344,27 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { revents = 0; if (ev->filter == EVFILT_READ) { - if (w->pevents & POLLIN) { + if (w->pevents & POLLIN) revents |= POLLIN; - w->rcount = ev->data; - } else { - /* TODO batch up */ - struct kevent events[1]; - EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); - if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL)) - if (errno != ENOENT) - abort(); - } + else + uv__kqueue_delete(loop->backend_fd, ev); + if ((ev->flags & EV_EOF) && (w->pevents & UV__POLLRDHUP)) revents |= UV__POLLRDHUP; } if (ev->filter == EV_OOBAND) { - if (w->pevents & UV__POLLPRI) { + if (w->pevents & UV__POLLPRI) revents |= UV__POLLPRI; - w->rcount = ev->data; - } else { - /* TODO batch up */ - struct kevent events[1]; - EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); - if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL)) - if (errno != ENOENT) - abort(); - } + else + uv__kqueue_delete(loop->backend_fd, ev); } if (ev->filter == EVFILT_WRITE) { - if (w->pevents & POLLOUT) { + if (w->pevents & POLLOUT) revents |= POLLOUT; - w->wcount = ev->data; - } else { - /* TODO batch up */ - struct kevent events[1]; - EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); - if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL)) - if (errno != ENOENT) - abort(); - } + else + uv__kqueue_delete(loop->backend_fd, ev); } if (ev->flags & EV_ERROR) @@ -398,9 +391,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { uv__wait_children(loop); } + uv__metrics_inc_events(loop, nevents); if (reset_timeout != 0) { timeout = user_timeout; reset_timeout = 0; + uv__metrics_inc_events_waiting(loop, nevents); } if (have_signals != 0) { @@ -423,13 +418,13 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { return; } +update_timeout: if (timeout == 0) return; if (timeout == -1) continue; -update_timeout: assert(timeout > 0); diff = loop->time - base; @@ -541,13 +536,14 @@ int uv_fs_event_start(uv_fs_event_t* handle, handle->realpath_len = 0; handle->cf_flags = flags; - if (fstat(fd, &statbuf)) + if (uv__fstat(fd, &statbuf)) goto fallback; /* FSEvents works only with directories */ if (!(statbuf.st_mode & S_IFDIR)) goto fallback; - if (0 == uv__load_relaxed(&uv__has_forked_with_cfrunloop)) { + if (0 == atomic_load_explicit(&uv__has_forked_with_cfrunloop, + std::memory_order_relaxed)) { int r; /* The fallback fd is no longer needed */ uv__close_nocheckstdio(fd); @@ -582,7 +578,8 @@ int uv_fs_event_stop(uv_fs_event_t* handle) { uv__handle_stop(handle); #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 - if (0 == uv__load_relaxed(&uv__has_forked_with_cfrunloop)) + if (0 == atomic_load_explicit(&uv__has_forked_with_cfrunloop, + std::memory_order_relaxed)) if (handle->cf_cb != NULL) r = uv__fsevents_close(handle); #endif diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/linux-core.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/linux-core.cpp deleted file mode 100644 index 12ed7ff1129..00000000000 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/linux-core.cpp +++ /dev/null @@ -1,841 +0,0 @@ -/* 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. - */ - -/* We lean on the fact that POLL{IN,OUT,ERR,HUP} correspond with their - * EPOLL* counterparts. We use the POLL* variants in this file because that - * is what libuv uses elsewhere. - */ - -#include "uv.h" -#include "internal.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#define HAVE_IFADDRS_H 1 - -# if defined(__ANDROID_API__) && __ANDROID_API__ < 24 -# undef HAVE_IFADDRS_H -#endif - -#ifdef __UCLIBC__ -# if __UCLIBC_MAJOR__ < 0 && __UCLIBC_MINOR__ < 9 && __UCLIBC_SUBLEVEL__ < 32 -# undef HAVE_IFADDRS_H -# endif -#endif - -#ifdef HAVE_IFADDRS_H -# include -# include -# include -# include -#endif /* HAVE_IFADDRS_H */ - -/* Available from 2.6.32 onwards. */ -#ifndef CLOCK_MONOTONIC_COARSE -# define CLOCK_MONOTONIC_COARSE 6 -#endif - -#ifdef __FRC_ROBORIO__ -#include "wpi/timestamp.h" -#endif - -/* This is rather annoying: CLOCK_BOOTTIME lives in but we can't - * include that file because it conflicts with . We'll just have to - * define it ourselves. - */ -#ifndef CLOCK_BOOTTIME -# define CLOCK_BOOTTIME 7 -#endif - -static int read_models(unsigned int numcpus, uv_cpu_info_t* ci); -static int read_times(FILE* statfile_fp, - unsigned int numcpus, - uv_cpu_info_t* ci); -static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci); -static uint64_t read_cpufreq(unsigned int cpunum); - -int uv__platform_loop_init(uv_loop_t* loop) { - - loop->inotify_fd = -1; - loop->inotify_watchers = NULL; - - return uv__epoll_init(loop); -} - - -int uv__io_fork(uv_loop_t* loop) { - int err; - void* old_watchers; - - old_watchers = loop->inotify_watchers; - - uv__close(loop->backend_fd); - loop->backend_fd = -1; - uv__platform_loop_delete(loop); - - err = uv__platform_loop_init(loop); - if (err) - return err; - - return uv__inotify_fork(loop, old_watchers); -} - - -void uv__platform_loop_delete(uv_loop_t* loop) { - if (loop->inotify_fd == -1) return; - uv__io_stop(loop, &loop->inotify_read_watcher, POLLIN); - uv__close(loop->inotify_fd); - loop->inotify_fd = -1; -} - - -uint64_t uv__hrtime(uv_clocktype_t type) { -#ifdef __FRC_ROBORIO__ - return wpi::Now() * 1000u; -#else - static clock_t fast_clock_id = -1; - struct timespec t; - clock_t clock_id; - - /* Prefer CLOCK_MONOTONIC_COARSE if available but only when it has - * millisecond granularity or better. CLOCK_MONOTONIC_COARSE is - * serviced entirely from the vDSO, whereas CLOCK_MONOTONIC may - * decide to make a costly system call. - */ - /* TODO(bnoordhuis) Use CLOCK_MONOTONIC_COARSE for UV_CLOCK_PRECISE - * when it has microsecond granularity or better (unlikely). - */ - clock_id = CLOCK_MONOTONIC; - if (type != UV_CLOCK_FAST) - goto done; - - clock_id = uv__load_relaxed(&fast_clock_id); - if (clock_id != -1) - goto done; - - clock_id = CLOCK_MONOTONIC; - if (0 == clock_getres(CLOCK_MONOTONIC_COARSE, &t)) - if (t.tv_nsec <= 1 * 1000 * 1000) - clock_id = CLOCK_MONOTONIC_COARSE; - - uv__store_relaxed(&fast_clock_id, clock_id); - -done: - - if (clock_gettime(clock_id, &t)) - return 0; /* Not really possible. */ - - return t.tv_sec * (uint64_t) 1e9 + t.tv_nsec; -#endif -} - - -int uv_resident_set_memory(size_t* rss) { - char buf[1024]; - const char* s; - ssize_t n; - long val; - int fd; - int i; - - do - fd = open("/proc/self/stat", O_RDONLY); - while (fd == -1 && errno == EINTR); - - if (fd == -1) - return UV__ERR(errno); - - do - n = read(fd, buf, sizeof(buf) - 1); - while (n == -1 && errno == EINTR); - - uv__close(fd); - if (n == -1) - return UV__ERR(errno); - buf[n] = '\0'; - - s = strchr(buf, ' '); - if (s == NULL) - goto err; - - s += 1; - if (*s != '(') - goto err; - - s = strchr(s, ')'); - if (s == NULL) - goto err; - - for (i = 1; i <= 22; i++) { - s = strchr(s + 1, ' '); - if (s == NULL) - goto err; - } - - errno = 0; - val = strtol(s, NULL, 10); - if (errno != 0) - goto err; - if (val < 0) - goto err; - - *rss = val * getpagesize(); - return 0; - -err: - return UV_EINVAL; -} - -int uv_uptime(double* uptime) { - static volatile int no_clock_boottime; - char buf[128]; - struct timespec now; - int r; - - /* Try /proc/uptime first, then fallback to clock_gettime(). */ - - if (0 == uv__slurp("/proc/uptime", buf, sizeof(buf))) - if (1 == sscanf(buf, "%lf", uptime)) - return 0; - - /* Try CLOCK_BOOTTIME first, fall back to CLOCK_MONOTONIC if not available - * (pre-2.6.39 kernels). CLOCK_MONOTONIC doesn't increase when the system - * is suspended. - */ - if (no_clock_boottime) { - retry_clock_gettime: r = clock_gettime(CLOCK_MONOTONIC, &now); - } - else if ((r = clock_gettime(CLOCK_BOOTTIME, &now)) && errno == EINVAL) { - no_clock_boottime = 1; - goto retry_clock_gettime; - } - - if (r) - return UV__ERR(errno); - - *uptime = now.tv_sec; - return 0; -} - - -static int uv__cpu_num(FILE* statfile_fp, unsigned int* numcpus) { - unsigned int num; - char buf[1024]; - - if (!fgets(buf, sizeof(buf), statfile_fp)) - return UV_EIO; - - num = 0; - while (fgets(buf, sizeof(buf), statfile_fp)) { - if (strncmp(buf, "cpu", 3)) - break; - num++; - } - - if (num == 0) - return UV_EIO; - - *numcpus = num; - return 0; -} - - -int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { - unsigned int numcpus; - uv_cpu_info_t* ci; - int err; - FILE* statfile_fp; - - *cpu_infos = NULL; - *count = 0; - - statfile_fp = uv__open_file("/proc/stat"); - if (statfile_fp == NULL) - return UV__ERR(errno); - - err = uv__cpu_num(statfile_fp, &numcpus); - if (err < 0) - goto out; - - err = UV_ENOMEM; - ci = (uv_cpu_info_t*)uv__calloc(numcpus, sizeof(*ci)); - if (ci == NULL) - goto out; - - err = read_models(numcpus, ci); - if (err == 0) - err = read_times(statfile_fp, numcpus, ci); - - if (err) { - uv_free_cpu_info(ci, numcpus); - goto out; - } - - /* read_models() on x86 also reads the CPU speed from /proc/cpuinfo. - * We don't check for errors here. Worst case, the field is left zero. - */ - if (ci[0].speed == 0) - read_speeds(numcpus, ci); - - *cpu_infos = ci; - *count = numcpus; - err = 0; - -out: - - if (fclose(statfile_fp)) - if (errno != EINTR && errno != EINPROGRESS) - abort(); - - return err; -} - - -static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci) { - unsigned int num; - - for (num = 0; num < numcpus; num++) - ci[num].speed = read_cpufreq(num) / 1000; -} - - -/* Also reads the CPU frequency on ppc and x86. The other architectures only - * have a BogoMIPS field, which may not be very accurate. - * - * Note: Simply returns on error, uv_cpu_info() takes care of the cleanup. - */ -static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) { -#if defined(__PPC__) - static const char model_marker[] = "cpu\t\t: "; - static const char speed_marker[] = "clock\t\t: "; -#else - static const char model_marker[] = "model name\t: "; - static const char speed_marker[] = "cpu MHz\t\t: "; -#endif - const char* inferred_model; - unsigned int model_idx; - unsigned int speed_idx; - unsigned int part_idx; - char buf[1024]; - char* model; - FILE* fp; - int model_id; - - /* Most are unused on non-ARM, non-MIPS and non-x86 architectures. */ - (void) &model_marker; - (void) &speed_marker; - (void) &speed_idx; - (void) &part_idx; - (void) &model; - (void) &buf; - (void) &fp; - (void) &model_id; - - model_idx = 0; - speed_idx = 0; - part_idx = 0; - -#if defined(__arm__) || \ - defined(__i386__) || \ - defined(__mips__) || \ - defined(__aarch64__) || \ - defined(__PPC__) || \ - defined(__x86_64__) - fp = uv__open_file("/proc/cpuinfo"); - if (fp == NULL) - return UV__ERR(errno); - - while (fgets(buf, sizeof(buf), fp)) { - if (model_idx < numcpus) { - if (strncmp(buf, model_marker, sizeof(model_marker) - 1) == 0) { - model = buf + sizeof(model_marker) - 1; - model = uv__strndup(model, strlen(model) - 1); /* Strip newline. */ - if (model == NULL) { - fclose(fp); - return UV_ENOMEM; - } - ci[model_idx++].model = model; - continue; - } - } -#if defined(__arm__) || defined(__mips__) || defined(__aarch64__) - if (model_idx < numcpus) { -#if defined(__arm__) - /* Fallback for pre-3.8 kernels. */ - static const char model_marker[] = "Processor\t: "; -#elif defined(__aarch64__) - static const char part_marker[] = "CPU part\t: "; - - /* Adapted from: https://github.com/karelzak/util-linux */ - struct vendor_part { - const int id; - const char* name; - }; - - static const struct vendor_part arm_chips[] = { - { 0x811, "ARM810" }, - { 0x920, "ARM920" }, - { 0x922, "ARM922" }, - { 0x926, "ARM926" }, - { 0x940, "ARM940" }, - { 0x946, "ARM946" }, - { 0x966, "ARM966" }, - { 0xa20, "ARM1020" }, - { 0xa22, "ARM1022" }, - { 0xa26, "ARM1026" }, - { 0xb02, "ARM11 MPCore" }, - { 0xb36, "ARM1136" }, - { 0xb56, "ARM1156" }, - { 0xb76, "ARM1176" }, - { 0xc05, "Cortex-A5" }, - { 0xc07, "Cortex-A7" }, - { 0xc08, "Cortex-A8" }, - { 0xc09, "Cortex-A9" }, - { 0xc0d, "Cortex-A17" }, /* Originally A12 */ - { 0xc0f, "Cortex-A15" }, - { 0xc0e, "Cortex-A17" }, - { 0xc14, "Cortex-R4" }, - { 0xc15, "Cortex-R5" }, - { 0xc17, "Cortex-R7" }, - { 0xc18, "Cortex-R8" }, - { 0xc20, "Cortex-M0" }, - { 0xc21, "Cortex-M1" }, - { 0xc23, "Cortex-M3" }, - { 0xc24, "Cortex-M4" }, - { 0xc27, "Cortex-M7" }, - { 0xc60, "Cortex-M0+" }, - { 0xd01, "Cortex-A32" }, - { 0xd03, "Cortex-A53" }, - { 0xd04, "Cortex-A35" }, - { 0xd05, "Cortex-A55" }, - { 0xd06, "Cortex-A65" }, - { 0xd07, "Cortex-A57" }, - { 0xd08, "Cortex-A72" }, - { 0xd09, "Cortex-A73" }, - { 0xd0a, "Cortex-A75" }, - { 0xd0b, "Cortex-A76" }, - { 0xd0c, "Neoverse-N1" }, - { 0xd0d, "Cortex-A77" }, - { 0xd0e, "Cortex-A76AE" }, - { 0xd13, "Cortex-R52" }, - { 0xd20, "Cortex-M23" }, - { 0xd21, "Cortex-M33" }, - { 0xd41, "Cortex-A78" }, - { 0xd42, "Cortex-A78AE" }, - { 0xd4a, "Neoverse-E1" }, - { 0xd4b, "Cortex-A78C" }, - }; - - if (strncmp(buf, part_marker, sizeof(part_marker) - 1) == 0) { - model = buf + sizeof(part_marker) - 1; - - errno = 0; - model_id = strtol(model, NULL, 16); - if ((errno != 0) || model_id < 0) { - fclose(fp); - return UV_EINVAL; - } - - for (part_idx = 0; part_idx < ARRAY_SIZE(arm_chips); part_idx++) { - if (model_id == arm_chips[part_idx].id) { - model = uv__strdup(arm_chips[part_idx].name); - if (model == NULL) { - fclose(fp); - return UV_ENOMEM; - } - ci[model_idx++].model = model; - break; - } - } - } -#else /* defined(__mips__) */ - static const char model_marker[] = "cpu model\t\t: "; -#endif - if (strncmp(buf, model_marker, sizeof(model_marker) - 1) == 0) { - model = buf + sizeof(model_marker) - 1; - model = uv__strndup(model, strlen(model) - 1); /* Strip newline. */ - if (model == NULL) { - fclose(fp); - return UV_ENOMEM; - } - ci[model_idx++].model = model; - continue; - } - } -#else /* !__arm__ && !__mips__ && !__aarch64__ */ - if (speed_idx < numcpus) { - if (strncmp(buf, speed_marker, sizeof(speed_marker) - 1) == 0) { - ci[speed_idx++].speed = atoi(buf + sizeof(speed_marker) - 1); - continue; - } - } -#endif /* __arm__ || __mips__ || __aarch64__ */ - } - - fclose(fp); -#endif /* __arm__ || __i386__ || __mips__ || __PPC__ || __x86_64__ || __aarch__ */ - - /* Now we want to make sure that all the models contain *something* because - * it's not safe to leave them as null. Copy the last entry unless there - * isn't one, in that case we simply put "unknown" into everything. - */ - inferred_model = "unknown"; - if (model_idx > 0) - inferred_model = ci[model_idx - 1].model; - - while (model_idx < numcpus) { - model = uv__strndup(inferred_model, strlen(inferred_model)); - if (model == NULL) - return UV_ENOMEM; - ci[model_idx++].model = model; - } - - return 0; -} - - -static int read_times(FILE* statfile_fp, - unsigned int numcpus, - uv_cpu_info_t* ci) { - struct uv_cpu_times_s ts; - unsigned int ticks; - unsigned int multiplier; - uint64_t user; - uint64_t nice; - uint64_t sys; - uint64_t idle; - uint64_t dummy; - uint64_t irq; - uint64_t num; - uint64_t len; - char buf[1024]; - - ticks = (unsigned int)sysconf(_SC_CLK_TCK); - assert(ticks != (unsigned int) -1); - assert(ticks != 0); - multiplier = ((uint64_t)1000L / ticks); - - rewind(statfile_fp); - - if (!fgets(buf, sizeof(buf), statfile_fp)) - abort(); - - num = 0; - - while (fgets(buf, sizeof(buf), statfile_fp)) { - if (num >= numcpus) - break; - - if (strncmp(buf, "cpu", 3)) - break; - - /* skip "cpu " marker */ - { - unsigned int n; - int r = sscanf(buf, "cpu%u ", &n); - assert(r == 1); - (void) r; /* silence build warning */ - for (len = sizeof("cpu0"); n /= 10; len++); - } - - /* Line contains user, nice, system, idle, iowait, irq, softirq, steal, - * guest, guest_nice but we're only interested in the first four + irq. - * - * Don't use %*s to skip fields or %ll to read straight into the uint64_t - * fields, they're not allowed in C89 mode. - */ - if (6 != sscanf(buf + len, - "%" PRIu64 " %" PRIu64 " %" PRIu64 - "%" PRIu64 " %" PRIu64 " %" PRIu64, - &user, - &nice, - &sys, - &idle, - &dummy, - &irq)) - abort(); - - ts.user = user * multiplier; - ts.nice = nice * multiplier; - ts.sys = sys * multiplier; - ts.idle = idle * multiplier; - ts.irq = irq * multiplier; - ci[num++].cpu_times = ts; - } - assert(num == numcpus); - - return 0; -} - - -static uint64_t read_cpufreq(unsigned int cpunum) { - uint64_t val; - char buf[1024]; - FILE* fp; - - snprintf(buf, - sizeof(buf), - "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_cur_freq", - cpunum); - - fp = uv__open_file(buf); - if (fp == NULL) - return 0; - - if (fscanf(fp, "%" PRIu64, &val) != 1) - val = 0; - - fclose(fp); - - return val; -} - - -#ifdef HAVE_IFADDRS_H -static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) - return 1; - if (ent->ifa_addr == NULL) - return 1; - /* - * On Linux getifaddrs returns information related to the raw underlying - * devices. We're not interested in this information yet. - */ - if (ent->ifa_addr->sa_family == PF_PACKET) - return exclude_type; - return !exclude_type; -} -#endif - -int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { -#ifndef HAVE_IFADDRS_H - *count = 0; - *addresses = NULL; - return UV_ENOSYS; -#else - struct ifaddrs *addrs, *ent; - uv_interface_address_t* address; - int i; - struct sockaddr_ll *sll; - - *count = 0; - *addresses = NULL; - - if (getifaddrs(&addrs)) - return UV__ERR(errno); - - /* Count the number of interfaces */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR)) - continue; - - (*count)++; - } - - if (*count == 0) { - freeifaddrs(addrs); - return 0; - } - - /* Make sure the memory is initiallized to zero using calloc() */ - *addresses = (uv_interface_address_t*)uv__calloc(*count, sizeof(**addresses)); - if (!(*addresses)) { - freeifaddrs(addrs); - return UV_ENOMEM; - } - - address = *addresses; - - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR)) - continue; - - address->name = uv__strdup(ent->ifa_name); - - if (ent->ifa_addr->sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); - } - - if (ent->ifa_netmask->sa_family == AF_INET6) { - address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); - } else { - address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); - } - - address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK); - - address++; - } - - /* Fill in physical addresses for each interface */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS)) - continue; - - address = *addresses; - - for (i = 0; i < (*count); i++) { - size_t namelen = strlen(ent->ifa_name); - /* Alias interface share the same physical address */ - if (strncmp(address->name, ent->ifa_name, namelen) == 0 && - (address->name[namelen] == 0 || address->name[namelen] == ':')) { - sll = (struct sockaddr_ll*)ent->ifa_addr; - memcpy(address->phys_addr, sll->sll_addr, sizeof(address->phys_addr)); - } - address++; - } - } - - freeifaddrs(addrs); - - return 0; -#endif -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(addresses[i].name); - } - - uv__free(addresses); -} - - -void uv__set_process_title(const char* title) { -#if defined(PR_SET_NAME) - prctl(PR_SET_NAME, title); /* Only copies first 16 characters. */ -#endif -} - - -static uint64_t uv__read_proc_meminfo(const char* what) { - uint64_t rc; - char* p; - char buf[4096]; /* Large enough to hold all of /proc/meminfo. */ - - if (uv__slurp("/proc/meminfo", buf, sizeof(buf))) - return 0; - - p = strstr(buf, what); - - if (p == NULL) - return 0; - - p += strlen(what); - - rc = 0; - sscanf(p, "%" PRIu64 " kB", &rc); - - return rc * 1024; -} - - -uint64_t uv_get_free_memory(void) { - struct sysinfo info; - uint64_t rc; - - rc = uv__read_proc_meminfo("MemAvailable:"); - - if (rc != 0) - return rc; - - if (0 == sysinfo(&info)) - return (uint64_t) info.freeram * info.mem_unit; - - return 0; -} - - -uint64_t uv_get_total_memory(void) { - struct sysinfo info; - uint64_t rc; - - rc = uv__read_proc_meminfo("MemTotal:"); - - if (rc != 0) - return rc; - - if (0 == sysinfo(&info)) - return (uint64_t) info.totalram * info.mem_unit; - - return 0; -} - - -static uint64_t uv__read_cgroups_uint64(const char* cgroup, const char* param) { - char filename[256]; - char buf[32]; /* Large enough to hold an encoded uint64_t. */ - uint64_t rc; - - rc = 0; - snprintf(filename, sizeof(filename), "/sys/fs/cgroup/%s/%s", cgroup, param); - if (0 == uv__slurp(filename, buf, sizeof(buf))) - sscanf(buf, "%" PRIu64, &rc); - - return rc; -} - - -uint64_t uv_get_constrained_memory(void) { - /* - * This might return 0 if there was a problem getting the memory limit from - * cgroups. This is OK because a return value of 0 signifies that the memory - * limit is unknown. - */ - return uv__read_cgroups_uint64("memory", "memory.limit_in_bytes"); -} - - -void uv_loadavg(double avg[3]) { - struct sysinfo info; - char buf[128]; /* Large enough to hold all of /proc/loadavg. */ - - if (0 == uv__slurp("/proc/loadavg", buf, sizeof(buf))) - if (3 == sscanf(buf, "%lf %lf %lf", &avg[0], &avg[1], &avg[2])) - return; - - if (sysinfo(&info) < 0) - return; - - avg[0] = (double) info.loads[0] / 65536.0; - avg[1] = (double) info.loads[1] / 65536.0; - avg[2] = (double) info.loads[2] / 65536.0; -} diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/linux-inotify.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/linux-inotify.cpp deleted file mode 100644 index f5366e9626f..00000000000 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/linux-inotify.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/* 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 "uv/tree.h" -#include "internal.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -struct watcher_list { - RB_ENTRY(watcher_list) entry; - QUEUE watchers; - int iterating; - char* path; - int wd; -}; - -struct watcher_root { - struct watcher_list* rbh_root; -}; -#define CAST(p) ((struct watcher_root*)(p)) - - -static int compare_watchers(const struct watcher_list* a, - const struct watcher_list* b) { - if (a->wd < b->wd) return -1; - if (a->wd > b->wd) return 1; - return 0; -} - - -RB_GENERATE_STATIC(watcher_root, watcher_list, entry, compare_watchers) - - -static void uv__inotify_read(uv_loop_t* loop, - uv__io_t* w, - unsigned int revents); - -static void maybe_free_watcher_list(struct watcher_list* w, - uv_loop_t* loop); - -static int init_inotify(uv_loop_t* loop) { - int fd; - - if (loop->inotify_fd != -1) - return 0; - - fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); - if (fd < 0) - return UV__ERR(errno); - - loop->inotify_fd = fd; - uv__io_init(&loop->inotify_read_watcher, uv__inotify_read, loop->inotify_fd); - uv__io_start(loop, &loop->inotify_read_watcher, POLLIN); - - return 0; -} - - -int uv__inotify_fork(uv_loop_t* loop, void* old_watchers) { - /* Open the inotify_fd, and re-arm all the inotify watchers. */ - int err; - struct watcher_list* tmp_watcher_list_iter; - struct watcher_list* watcher_list; - struct watcher_list tmp_watcher_list; - QUEUE queue; - QUEUE* q; - uv_fs_event_t* handle; - char* tmp_path; - - if (old_watchers != NULL) { - /* We must restore the old watcher list to be able to close items - * out of it. - */ - loop->inotify_watchers = old_watchers; - - QUEUE_INIT(&tmp_watcher_list.watchers); - /* Note that the queue we use is shared with the start and stop() - * functions, making QUEUE_FOREACH unsafe to use. So we use the - * QUEUE_MOVE trick to safely iterate. Also don't free the watcher - * list until we're done iterating. c.f. uv__inotify_read. - */ - RB_FOREACH_SAFE(watcher_list, watcher_root, - CAST(&old_watchers), tmp_watcher_list_iter) { - watcher_list->iterating = 1; - QUEUE_MOVE(&watcher_list->watchers, &queue); - while (!QUEUE_EMPTY(&queue)) { - q = QUEUE_HEAD(&queue); - handle = QUEUE_DATA(q, uv_fs_event_t, watchers); - /* It's critical to keep a copy of path here, because it - * will be set to NULL by stop() and then deallocated by - * maybe_free_watcher_list - */ - tmp_path = uv__strdup(handle->path); - assert(tmp_path != NULL); - QUEUE_REMOVE(q); - QUEUE_INSERT_TAIL(&watcher_list->watchers, q); - uv_fs_event_stop(handle); - - QUEUE_INSERT_TAIL(&tmp_watcher_list.watchers, &handle->watchers); - handle->path = tmp_path; - } - watcher_list->iterating = 0; - maybe_free_watcher_list(watcher_list, loop); - } - - QUEUE_MOVE(&tmp_watcher_list.watchers, &queue); - while (!QUEUE_EMPTY(&queue)) { - q = QUEUE_HEAD(&queue); - QUEUE_REMOVE(q); - handle = QUEUE_DATA(q, uv_fs_event_t, watchers); - tmp_path = handle->path; - handle->path = NULL; - err = uv_fs_event_start(handle, handle->cb, tmp_path, 0); - uv__free(tmp_path); - if (err) - return err; - } - } - - return 0; -} - - -static struct watcher_list* find_watcher(uv_loop_t* loop, int wd) { - struct watcher_list w; - w.wd = wd; - return RB_FIND(watcher_root, CAST(&loop->inotify_watchers), &w); -} - -static void maybe_free_watcher_list(struct watcher_list* w, uv_loop_t* loop) { - /* if the watcher_list->watchers is being iterated over, we can't free it. */ - if ((!w->iterating) && QUEUE_EMPTY(&w->watchers)) { - /* No watchers left for this path. Clean up. */ - RB_REMOVE(watcher_root, CAST(&loop->inotify_watchers), w); - inotify_rm_watch(loop->inotify_fd, w->wd); - uv__free(w); - } -} - -static void uv__inotify_read(uv_loop_t* loop, - uv__io_t* dummy, - unsigned int events) { - const struct inotify_event* e; - struct watcher_list* w; - uv_fs_event_t* h; - QUEUE queue; - QUEUE* q; - const char* path; - ssize_t size; - const char *p; - /* needs to be large enough for sizeof(inotify_event) + strlen(path) */ - char buf[4096]; - - for (;;) { - do - size = read(loop->inotify_fd, buf, sizeof(buf)); - while (size == -1 && errno == EINTR); - - if (size == -1) { - assert(errno == EAGAIN || errno == EWOULDBLOCK); - break; - } - - assert(size > 0); /* pre-2.6.21 thing, size=0 == read buffer too small */ - - /* Now we have one or more inotify_event structs. */ - for (p = buf; p < buf + size; p += sizeof(*e) + e->len) { - e = (const struct inotify_event*) p; - - events = 0; - if (e->mask & (IN_ATTRIB|IN_MODIFY)) - events |= UV_CHANGE; - if (e->mask & ~(IN_ATTRIB|IN_MODIFY)) - events |= UV_RENAME; - - w = find_watcher(loop, e->wd); - if (w == NULL) - continue; /* Stale event, no watchers left. */ - - /* inotify does not return the filename when monitoring a single file - * for modifications. Repurpose the filename for API compatibility. - * I'm not convinced this is a good thing, maybe it should go. - */ - path = e->len ? (const char*) (e + 1) : uv__basename_r(w->path); - - /* We're about to iterate over the queue and call user's callbacks. - * What can go wrong? - * A callback could call uv_fs_event_stop() - * and the queue can change under our feet. - * So, we use QUEUE_MOVE() trick to safely iterate over the queue. - * And we don't free the watcher_list until we're done iterating. - * - * First, - * tell uv_fs_event_stop() (that could be called from a user's callback) - * not to free watcher_list. - */ - w->iterating = 1; - QUEUE_MOVE(&w->watchers, &queue); - while (!QUEUE_EMPTY(&queue)) { - q = QUEUE_HEAD(&queue); - h = QUEUE_DATA(q, uv_fs_event_t, watchers); - - QUEUE_REMOVE(q); - QUEUE_INSERT_TAIL(&w->watchers, q); - - h->cb(h, path, events, 0); - } - /* done iterating, time to (maybe) free empty watcher_list */ - w->iterating = 0; - maybe_free_watcher_list(w, loop); - } - } -} - - -int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { - uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); - return 0; -} - - -int uv_fs_event_start(uv_fs_event_t* handle, - uv_fs_event_cb cb, - const char* path, - unsigned int flags) { - struct watcher_list* w; - size_t len; - int events; - int err; - int wd; - - if (uv__is_active(handle)) - return UV_EINVAL; - - err = init_inotify(handle->loop); - if (err) - return err; - - events = IN_ATTRIB - | IN_CREATE - | IN_MODIFY - | IN_DELETE - | IN_DELETE_SELF - | IN_MOVE_SELF - | IN_MOVED_FROM - | IN_MOVED_TO; - - wd = inotify_add_watch(handle->loop->inotify_fd, path, events); - if (wd == -1) - return UV__ERR(errno); - - w = find_watcher(handle->loop, wd); - if (w) - goto no_insert; - - len = strlen(path) + 1; - w = (watcher_list*)uv__malloc(sizeof(*w) + len); - if (w == NULL) - return UV_ENOMEM; - - w->wd = wd; - w->path = (char*)memcpy(w + 1, path, len); - QUEUE_INIT(&w->watchers); - w->iterating = 0; - RB_INSERT(watcher_root, CAST(&handle->loop->inotify_watchers), w); - -no_insert: - uv__handle_start(handle); - QUEUE_INSERT_TAIL(&w->watchers, &handle->watchers); - handle->path = w->path; - handle->cb = cb; - handle->wd = wd; - - return 0; -} - - -int uv_fs_event_stop(uv_fs_event_t* handle) { - struct watcher_list* w; - - if (!uv__is_active(handle)) - return 0; - - w = find_watcher(handle->loop, handle->wd); - assert(w != NULL); - - handle->wd = -1; - handle->path = NULL; - uv__handle_stop(handle); - QUEUE_REMOVE(&handle->watchers); - - maybe_free_watcher_list(w, handle->loop); - - return 0; -} - - -void uv__fs_event_close(uv_fs_event_t* handle) { - uv_fs_event_stop(handle); -} diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/linux-syscalls.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/linux-syscalls.cpp deleted file mode 100644 index 5071cd56d1f..00000000000 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/linux-syscalls.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/* 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 "linux-syscalls.h" -#include -#include -#include -#include -#include - -#if defined(__arm__) -# if defined(__thumb__) || defined(__ARM_EABI__) -# define UV_SYSCALL_BASE 0 -# else -# define UV_SYSCALL_BASE 0x900000 -# endif -#endif /* __arm__ */ - -#ifndef __NR_recvmmsg -# if defined(__x86_64__) -# define __NR_recvmmsg 299 -# elif defined(__arm__) -# define __NR_recvmmsg (UV_SYSCALL_BASE + 365) -# endif -#endif /* __NR_recvmsg */ - -#ifndef __NR_sendmmsg -# if defined(__x86_64__) -# define __NR_sendmmsg 307 -# elif defined(__arm__) -# define __NR_sendmmsg (UV_SYSCALL_BASE + 374) -# endif -#endif /* __NR_sendmmsg */ - -#ifndef __NR_utimensat -# if defined(__x86_64__) -# define __NR_utimensat 280 -# elif defined(__i386__) -# define __NR_utimensat 320 -# elif defined(__arm__) -# define __NR_utimensat (UV_SYSCALL_BASE + 348) -# endif -#endif /* __NR_utimensat */ - -#ifndef __NR_preadv -# if defined(__x86_64__) -# define __NR_preadv 295 -# elif defined(__i386__) -# define __NR_preadv 333 -# elif defined(__arm__) -# define __NR_preadv (UV_SYSCALL_BASE + 361) -# endif -#endif /* __NR_preadv */ - -#ifndef __NR_pwritev -# if defined(__x86_64__) -# define __NR_pwritev 296 -# elif defined(__i386__) -# define __NR_pwritev 334 -# elif defined(__arm__) -# define __NR_pwritev (UV_SYSCALL_BASE + 362) -# endif -#endif /* __NR_pwritev */ - -#ifndef __NR_dup3 -# if defined(__x86_64__) -# define __NR_dup3 292 -# elif defined(__i386__) -# define __NR_dup3 330 -# elif defined(__arm__) -# define __NR_dup3 (UV_SYSCALL_BASE + 358) -# endif -#endif /* __NR_pwritev */ - -#ifndef __NR_copy_file_range -# if defined(__x86_64__) -# define __NR_copy_file_range 326 -# elif defined(__i386__) -# define __NR_copy_file_range 377 -# elif defined(__s390__) -# define __NR_copy_file_range 375 -# elif defined(__arm__) -# define __NR_copy_file_range (UV_SYSCALL_BASE + 391) -# elif defined(__aarch64__) -# define __NR_copy_file_range 285 -# elif defined(__powerpc__) -# define __NR_copy_file_range 379 -# elif defined(__arc__) -# define __NR_copy_file_range 285 -# endif -#endif /* __NR_copy_file_range */ - -#ifndef __NR_statx -# if defined(__x86_64__) -# define __NR_statx 332 -# elif defined(__i386__) -# define __NR_statx 383 -# elif defined(__aarch64__) -# define __NR_statx 397 -# elif defined(__arm__) -# define __NR_statx (UV_SYSCALL_BASE + 397) -# elif defined(__ppc__) -# define __NR_statx 383 -# elif defined(__s390__) -# define __NR_statx 379 -# endif -#endif /* __NR_statx */ - -#ifndef __NR_getrandom -# if defined(__x86_64__) -# define __NR_getrandom 318 -# elif defined(__i386__) -# define __NR_getrandom 355 -# elif defined(__aarch64__) -# define __NR_getrandom 384 -# elif defined(__arm__) -# define __NR_getrandom (UV_SYSCALL_BASE + 384) -# elif defined(__ppc__) -# define __NR_getrandom 359 -# elif defined(__s390__) -# define __NR_getrandom 349 -# endif -#endif /* __NR_getrandom */ - -struct uv__mmsghdr; - -int uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) { -#if defined(__i386__) - unsigned long args[4]; - int rc; - - args[0] = (unsigned long) fd; - args[1] = (unsigned long) mmsg; - args[2] = (unsigned long) vlen; - args[3] = /* flags */ 0; - - /* socketcall() raises EINVAL when SYS_SENDMMSG is not supported. */ - rc = syscall(/* __NR_socketcall */ 102, 20 /* SYS_SENDMMSG */, args); - if (rc == -1) - if (errno == EINVAL) - errno = ENOSYS; - - return rc; -#elif defined(__NR_sendmmsg) - return syscall(__NR_sendmmsg, fd, mmsg, vlen, /* flags */ 0); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__recvmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) { -#if defined(__i386__) - unsigned long args[5]; - int rc; - - args[0] = (unsigned long) fd; - args[1] = (unsigned long) mmsg; - args[2] = (unsigned long) vlen; - args[3] = /* flags */ 0; - args[4] = /* timeout */ 0; - - /* socketcall() raises EINVAL when SYS_RECVMMSG is not supported. */ - rc = syscall(/* __NR_socketcall */ 102, 19 /* SYS_RECVMMSG */, args); - if (rc == -1) - if (errno == EINVAL) - errno = ENOSYS; - - return rc; -#elif defined(__NR_recvmmsg) - return syscall(__NR_recvmmsg, fd, mmsg, vlen, /* flags */ 0, /* timeout */ 0); -#else - return errno = ENOSYS, -1; -#endif -} - - -ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset) { -#if !defined(__NR_preadv) || defined(__ANDROID_API__) && __ANDROID_API__ < 24 - return errno = ENOSYS, -1; -#else - return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32)); -#endif -} - - -ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset) { -#if !defined(__NR_pwritev) || defined(__ANDROID_API__) && __ANDROID_API__ < 24 - return errno = ENOSYS, -1; -#else - return syscall(__NR_pwritev, fd, iov, iovcnt, (long)offset, (long)(offset >> 32)); -#endif -} - - -int uv__dup3(int oldfd, int newfd, int flags) { -#if !defined(__NR_dup3) || defined(__ANDROID_API__) && __ANDROID_API__ < 21 - return errno = ENOSYS, -1; -#else - return syscall(__NR_dup3, oldfd, newfd, flags); -#endif -} - - -ssize_t -uv__fs_copy_file_range(int fd_in, - off_t* off_in, - int fd_out, - off_t* off_out, - size_t len, - unsigned int flags) -{ -#ifdef __NR_copy_file_range - return syscall(__NR_copy_file_range, - fd_in, - off_in, - fd_out, - off_out, - len, - flags); -#else - return errno = ENOSYS, -1; -#endif -} - - -int uv__statx(int dirfd, - const char* path, - int flags, - unsigned int mask, - struct uv__statx* statxbuf) { -#if !defined(__NR_statx) || defined(__ANDROID_API__) && __ANDROID_API__ < 30 - return errno = ENOSYS, -1; -#else - return syscall(__NR_statx, dirfd, path, flags, mask, statxbuf); -#endif -} - - -ssize_t uv__getrandom(void* buf, size_t buflen, unsigned flags) { -#if !defined(__NR_getrandom) || defined(__ANDROID_API__) && __ANDROID_API__ < 28 - return errno = ENOSYS, -1; -#else - return syscall(__NR_getrandom, buf, buflen, flags); -#endif -} diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/linux-syscalls.h b/wpinet/src/main/native/thirdparty/libuv/src/unix/linux-syscalls.h deleted file mode 100644 index b4d9082d46f..00000000000 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/linux-syscalls.h +++ /dev/null @@ -1,78 +0,0 @@ -/* 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. - */ - -#ifndef UV_LINUX_SYSCALL_H_ -#define UV_LINUX_SYSCALL_H_ - -#include -#include -#include -#include -#include - -struct uv__statx_timestamp { - int64_t tv_sec; - uint32_t tv_nsec; - int32_t unused0; -}; - -struct uv__statx { - uint32_t stx_mask; - uint32_t stx_blksize; - uint64_t stx_attributes; - uint32_t stx_nlink; - uint32_t stx_uid; - uint32_t stx_gid; - uint16_t stx_mode; - uint16_t unused0; - uint64_t stx_ino; - uint64_t stx_size; - uint64_t stx_blocks; - uint64_t stx_attributes_mask; - struct uv__statx_timestamp stx_atime; - struct uv__statx_timestamp stx_btime; - struct uv__statx_timestamp stx_ctime; - struct uv__statx_timestamp stx_mtime; - uint32_t stx_rdev_major; - uint32_t stx_rdev_minor; - uint32_t stx_dev_major; - uint32_t stx_dev_minor; - uint64_t unused1[14]; -}; - -ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset); -ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset); -int uv__dup3(int oldfd, int newfd, int flags); -ssize_t -uv__fs_copy_file_range(int fd_in, - off_t* off_in, - int fd_out, - off_t* off_out, - size_t len, - unsigned int flags); -int uv__statx(int dirfd, - const char* path, - int flags, - unsigned int mask, - struct uv__statx* statxbuf); -ssize_t uv__getrandom(void* buf, size_t buflen, unsigned flags); - -#endif /* UV_LINUX_SYSCALL_H_ */ diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/linux.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/linux.cpp new file mode 100644 index 00000000000..d365b623a0a --- /dev/null +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/linux.cpp @@ -0,0 +1,2526 @@ +/* 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. + */ + +/* We lean on the fact that POLL{IN,OUT,ERR,HUP} correspond with their + * EPOLL* counterparts. We use the POLL* variants in this file because that + * is what libuv uses elsewhere. + */ + +#include "uv.h" +#include "internal.h" + +#include +#include /* offsetof */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __NR_io_uring_setup +# define __NR_io_uring_setup 425 +#endif + +#ifndef __NR_io_uring_enter +# define __NR_io_uring_enter 426 +#endif + +#ifndef __NR_io_uring_register +# define __NR_io_uring_register 427 +#endif + +#ifndef __NR_copy_file_range +# if defined(__x86_64__) +# define __NR_copy_file_range 326 +# elif defined(__i386__) +# define __NR_copy_file_range 377 +# elif defined(__s390__) +# define __NR_copy_file_range 375 +# elif defined(__arm__) +# define __NR_copy_file_range 391 +# elif defined(__aarch64__) +# define __NR_copy_file_range 285 +# elif defined(__powerpc__) +# define __NR_copy_file_range 379 +# elif defined(__arc__) +# define __NR_copy_file_range 285 +# endif +#endif /* __NR_copy_file_range */ + +#ifndef __NR_statx +# if defined(__x86_64__) +# define __NR_statx 332 +# elif defined(__i386__) +# define __NR_statx 383 +# elif defined(__aarch64__) +# define __NR_statx 397 +# elif defined(__arm__) +# define __NR_statx 397 +# elif defined(__ppc__) +# define __NR_statx 383 +# elif defined(__s390__) +# define __NR_statx 379 +# endif +#endif /* __NR_statx */ + +#ifndef __NR_getrandom +# if defined(__x86_64__) +# define __NR_getrandom 318 +# elif defined(__i386__) +# define __NR_getrandom 355 +# elif defined(__aarch64__) +# define __NR_getrandom 384 +# elif defined(__arm__) +# define __NR_getrandom 384 +# elif defined(__ppc__) +# define __NR_getrandom 359 +# elif defined(__s390__) +# define __NR_getrandom 349 +# endif +#endif /* __NR_getrandom */ + +#define HAVE_IFADDRS_H 1 + +# if defined(__ANDROID_API__) && __ANDROID_API__ < 24 +# undef HAVE_IFADDRS_H +#endif + +#ifdef __UCLIBC__ +# if __UCLIBC_MAJOR__ < 0 && __UCLIBC_MINOR__ < 9 && __UCLIBC_SUBLEVEL__ < 32 +# undef HAVE_IFADDRS_H +# endif +#endif + +#ifdef HAVE_IFADDRS_H +# include +# include +# include +# include +#endif /* HAVE_IFADDRS_H */ + +#include + +enum { + UV__IORING_SETUP_SQPOLL = 2u, +}; + +enum { + UV__IORING_FEAT_SINGLE_MMAP = 1u, + UV__IORING_FEAT_NODROP = 2u, + UV__IORING_FEAT_RSRC_TAGS = 1024u, /* linux v5.13 */ +}; + +enum { + UV__IORING_OP_READV = 1, + UV__IORING_OP_WRITEV = 2, + UV__IORING_OP_FSYNC = 3, + UV__IORING_OP_OPENAT = 18, + UV__IORING_OP_CLOSE = 19, + UV__IORING_OP_STATX = 21, + UV__IORING_OP_EPOLL_CTL = 29, + UV__IORING_OP_RENAMEAT = 35, + UV__IORING_OP_UNLINKAT = 36, + UV__IORING_OP_MKDIRAT = 37, + UV__IORING_OP_SYMLINKAT = 38, + UV__IORING_OP_LINKAT = 39, +}; + +enum { + UV__IORING_ENTER_GETEVENTS = 1u, + UV__IORING_ENTER_SQ_WAKEUP = 2u, +}; + +enum { + UV__IORING_SQ_NEED_WAKEUP = 1u, + UV__IORING_SQ_CQ_OVERFLOW = 2u, +}; + +enum { + UV__MKDIRAT_SYMLINKAT_LINKAT = 1u, +}; + +struct uv__io_cqring_offsets { + uint32_t head; + uint32_t tail; + uint32_t ring_mask; + uint32_t ring_entries; + uint32_t overflow; + uint32_t cqes; + uint64_t reserved0; + uint64_t reserved1; +}; + +STATIC_ASSERT(40 == sizeof(struct uv__io_cqring_offsets)); + +struct uv__io_sqring_offsets { + uint32_t head; + uint32_t tail; + uint32_t ring_mask; + uint32_t ring_entries; + uint32_t flags; + uint32_t dropped; + uint32_t array; + uint32_t reserved0; + uint64_t reserved1; +}; + +STATIC_ASSERT(40 == sizeof(struct uv__io_sqring_offsets)); + +struct uv__io_uring_cqe { + uint64_t user_data; + int32_t res; + uint32_t flags; +}; + +STATIC_ASSERT(16 == sizeof(struct uv__io_uring_cqe)); + +struct uv__io_uring_sqe { + uint8_t opcode; + uint8_t flags; + uint16_t ioprio; + int32_t fd; + union { + uint64_t off; + uint64_t addr2; + }; + union { + uint64_t addr; + }; + uint32_t len; + union { + uint32_t rw_flags; + uint32_t fsync_flags; + uint32_t open_flags; + uint32_t statx_flags; + }; + uint64_t user_data; + union { + uint16_t buf_index; + uint64_t pad[3]; + }; +}; + +STATIC_ASSERT(64 == sizeof(struct uv__io_uring_sqe)); +STATIC_ASSERT(0 == offsetof(struct uv__io_uring_sqe, opcode)); +STATIC_ASSERT(1 == offsetof(struct uv__io_uring_sqe, flags)); +STATIC_ASSERT(2 == offsetof(struct uv__io_uring_sqe, ioprio)); +STATIC_ASSERT(4 == offsetof(struct uv__io_uring_sqe, fd)); +STATIC_ASSERT(8 == offsetof(struct uv__io_uring_sqe, off)); +STATIC_ASSERT(16 == offsetof(struct uv__io_uring_sqe, addr)); +STATIC_ASSERT(24 == offsetof(struct uv__io_uring_sqe, len)); +STATIC_ASSERT(28 == offsetof(struct uv__io_uring_sqe, rw_flags)); +STATIC_ASSERT(32 == offsetof(struct uv__io_uring_sqe, user_data)); +STATIC_ASSERT(40 == offsetof(struct uv__io_uring_sqe, buf_index)); + +struct uv__io_uring_params { + uint32_t sq_entries; + uint32_t cq_entries; + uint32_t flags; + uint32_t sq_thread_cpu; + uint32_t sq_thread_idle; + uint32_t features; + uint32_t reserved[4]; + struct uv__io_sqring_offsets sq_off; /* 40 bytes */ + struct uv__io_cqring_offsets cq_off; /* 40 bytes */ +}; + +STATIC_ASSERT(40 + 40 + 40 == sizeof(struct uv__io_uring_params)); +STATIC_ASSERT(40 == offsetof(struct uv__io_uring_params, sq_off)); +STATIC_ASSERT(80 == offsetof(struct uv__io_uring_params, cq_off)); + +STATIC_ASSERT(EPOLL_CTL_ADD < 4); +STATIC_ASSERT(EPOLL_CTL_DEL < 4); +STATIC_ASSERT(EPOLL_CTL_MOD < 4); + +struct watcher_list { + RB_ENTRY(watcher_list) entry; + struct uv__queue watchers; + int iterating; + char* path; + int wd; +}; + +struct watcher_root { + struct watcher_list* rbh_root; +}; + +static int uv__inotify_fork(uv_loop_t* loop, struct watcher_list* root); +static void uv__inotify_read(uv_loop_t* loop, + uv__io_t* w, + unsigned int revents); +static int compare_watchers(const struct watcher_list* a, + const struct watcher_list* b); +static void maybe_free_watcher_list(struct watcher_list* w, + uv_loop_t* loop); + +static void uv__epoll_ctl_flush(int epollfd, + struct uv__iou* ctl, + struct epoll_event (*events)[256]); + +static void uv__epoll_ctl_prep(int epollfd, + struct uv__iou* ctl, + struct epoll_event (*events)[256], + int op, + int fd, + struct epoll_event* e); + +RB_GENERATE_STATIC(watcher_root, watcher_list, entry, compare_watchers) + + +static struct watcher_root* uv__inotify_watchers(uv_loop_t* loop) { + /* This cast works because watcher_root is a struct with a pointer as its + * sole member. Such type punning is unsafe in the presence of strict + * pointer aliasing (and is just plain nasty) but that is why libuv + * is compiled with -fno-strict-aliasing. + */ + return (struct watcher_root*) &loop->inotify_watchers; +} + + +unsigned uv__kernel_version(void) { + static std::atomic cached_version; + struct utsname u; + unsigned version; + unsigned major; + unsigned minor; + unsigned patch; + + version = std::atomic_load_explicit(&cached_version, std::memory_order_relaxed); + if (version != 0) + return version; + + if (-1 == uname(&u)) + return 0; + + if (3 != sscanf(u.release, "%u.%u.%u", &major, &minor, &patch)) + return 0; + + version = major * 65536 + minor * 256 + patch; + std::atomic_store_explicit(&cached_version, version, std::memory_order_relaxed); + + return version; +} + + +ssize_t +uv__fs_copy_file_range(int fd_in, + off_t* off_in, + int fd_out, + off_t* off_out, + size_t len, + unsigned int flags) +{ +#ifdef __NR_copy_file_range + return syscall(__NR_copy_file_range, + fd_in, + off_in, + fd_out, + off_out, + len, + flags); +#else + return errno = ENOSYS, -1; +#endif +} + + +int uv__statx(int dirfd, + const char* path, + int flags, + unsigned int mask, + struct uv__statx* statxbuf) { +#if !defined(__NR_statx) || defined(__ANDROID_API__) && __ANDROID_API__ < 30 + return errno = ENOSYS, -1; +#else + int rc; + + rc = syscall(__NR_statx, dirfd, path, flags, mask, statxbuf); + if (rc >= 0) + uv__msan_unpoison(statxbuf, sizeof(*statxbuf)); + + return rc; +#endif +} + + +ssize_t uv__getrandom(void* buf, size_t buflen, unsigned flags) { +#if !defined(__NR_getrandom) || defined(__ANDROID_API__) && __ANDROID_API__ < 28 + return errno = ENOSYS, -1; +#else + ssize_t rc; + + rc = syscall(__NR_getrandom, buf, buflen, flags); + if (rc >= 0) + uv__msan_unpoison(buf, buflen); + + return rc; +#endif +} + + +int uv__io_uring_setup(int entries, struct uv__io_uring_params* params) { + return syscall(__NR_io_uring_setup, entries, params); +} + + +int uv__io_uring_enter(int fd, + unsigned to_submit, + unsigned min_complete, + unsigned flags) { + /* io_uring_enter used to take a sigset_t but it's unused + * in newer kernels unless IORING_ENTER_EXT_ARG is set, + * in which case it takes a struct io_uring_getevents_arg. + */ + return syscall(__NR_io_uring_enter, + fd, + to_submit, + min_complete, + flags, + NULL, + 0L); +} + + +int uv__io_uring_register(int fd, unsigned opcode, void* arg, unsigned nargs) { + return syscall(__NR_io_uring_register, fd, opcode, arg, nargs); +} + + +static int uv__use_io_uring(void) { +#if defined(__ANDROID_API__) + return 0; /* Possibly available but blocked by seccomp. */ +#else + /* Ternary: unknown=0, yes=1, no=-1 */ + static std::atomic use_io_uring; + char* val; + int use; + + use = std::atomic_load_explicit(&use_io_uring, std::memory_order_relaxed); + + if (use == 0) { + val = getenv("UV_USE_IO_URING"); + use = val == NULL || atoi(val) ? 1 : -1; + std::atomic_store_explicit(&use_io_uring, use, std::memory_order_relaxed); + } + + return use > 0; +#endif +} + + +static void uv__iou_init(int epollfd, + struct uv__iou* iou, + uint32_t entries, + uint32_t flags) { + struct uv__io_uring_params params; + struct epoll_event e; + size_t cqlen; + size_t sqlen; + size_t maxlen; + size_t sqelen; + uint32_t i; + char* sq; + char* sqe; + int ringfd; + + sq = (char*)MAP_FAILED; + sqe = (char*)MAP_FAILED; + + if (!uv__use_io_uring()) + return; + + /* SQPOLL required CAP_SYS_NICE until linux v5.12 relaxed that requirement. + * Mostly academic because we check for a v5.13 kernel afterwards anyway. + */ + memset(¶ms, 0, sizeof(params)); + params.flags = flags; + + if (flags & UV__IORING_SETUP_SQPOLL) + params.sq_thread_idle = 10; /* milliseconds */ + + /* Kernel returns a file descriptor with O_CLOEXEC flag set. */ + ringfd = uv__io_uring_setup(entries, ¶ms); + if (ringfd == -1) + return; + + /* IORING_FEAT_RSRC_TAGS is used to detect linux v5.13 but what we're + * actually detecting is whether IORING_OP_STATX works with SQPOLL. + */ + if (!(params.features & UV__IORING_FEAT_RSRC_TAGS)) + goto fail; + + /* Implied by IORING_FEAT_RSRC_TAGS but checked explicitly anyway. */ + if (!(params.features & UV__IORING_FEAT_SINGLE_MMAP)) + goto fail; + + /* Implied by IORING_FEAT_RSRC_TAGS but checked explicitly anyway. */ + if (!(params.features & UV__IORING_FEAT_NODROP)) + goto fail; + + sqlen = params.sq_off.array + params.sq_entries * sizeof(uint32_t); + cqlen = + params.cq_off.cqes + params.cq_entries * sizeof(struct uv__io_uring_cqe); + maxlen = sqlen < cqlen ? cqlen : sqlen; + sqelen = params.sq_entries * sizeof(struct uv__io_uring_sqe); + + sq = (char*)mmap(0, + maxlen, + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_POPULATE, + ringfd, + 0); /* IORING_OFF_SQ_RING */ + + sqe = (char*)mmap(0, + sqelen, + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_POPULATE, + ringfd, + 0x10000000ull); /* IORING_OFF_SQES */ + + if (sq == MAP_FAILED || sqe == MAP_FAILED) + goto fail; + + if (flags & UV__IORING_SETUP_SQPOLL) { + /* Only interested in completion events. To get notified when + * the kernel pulls items from the submission ring, add POLLOUT. + */ + memset(&e, 0, sizeof(e)); + e.events = POLLIN; + e.data.fd = ringfd; + + if (epoll_ctl(epollfd, EPOLL_CTL_ADD, ringfd, &e)) + goto fail; + } + + iou->sqhead = (uint32_t*) (sq + params.sq_off.head); + iou->sqtail = (uint32_t*) (sq + params.sq_off.tail); + iou->sqmask = *(uint32_t*) (sq + params.sq_off.ring_mask); + iou->sqarray = (uint32_t*) (sq + params.sq_off.array); + iou->sqflags = (uint32_t*) (sq + params.sq_off.flags); + iou->cqhead = (uint32_t*) (sq + params.cq_off.head); + iou->cqtail = (uint32_t*) (sq + params.cq_off.tail); + iou->cqmask = *(uint32_t*) (sq + params.cq_off.ring_mask); + iou->sq = sq; + iou->cqe = sq + params.cq_off.cqes; + iou->sqe = sqe; + iou->sqlen = sqlen; + iou->cqlen = cqlen; + iou->maxlen = maxlen; + iou->sqelen = sqelen; + iou->ringfd = ringfd; + iou->in_flight = 0; + iou->flags = 0; + + if (uv__kernel_version() >= /* 5.15.0 */ 0x050F00) + iou->flags |= UV__MKDIRAT_SYMLINKAT_LINKAT; + + for (i = 0; i <= iou->sqmask; i++) + iou->sqarray[i] = i; /* Slot -> sqe identity mapping. */ + + return; + +fail: + if (sq != MAP_FAILED) + munmap(sq, maxlen); + + if (sqe != MAP_FAILED) + munmap(sqe, sqelen); + + uv__close(ringfd); +} + + +static void uv__iou_delete(struct uv__iou* iou) { + if (iou->ringfd != -1) { + munmap(iou->sq, iou->maxlen); + munmap(iou->sqe, iou->sqelen); + uv__close(iou->ringfd); + iou->ringfd = -1; + } +} + + +int uv__platform_loop_init(uv_loop_t* loop) { + uv__loop_internal_fields_t* lfields; + + lfields = uv__get_internal_fields(loop); + lfields->ctl.ringfd = -1; + lfields->iou.ringfd = -1; + + loop->inotify_watchers = NULL; + loop->inotify_fd = -1; + loop->backend_fd = epoll_create1(O_CLOEXEC); + + if (loop->backend_fd == -1) + return UV__ERR(errno); + + uv__iou_init(loop->backend_fd, &lfields->iou, 64, UV__IORING_SETUP_SQPOLL); + uv__iou_init(loop->backend_fd, &lfields->ctl, 256, 0); + + return 0; +} + + +int uv__io_fork(uv_loop_t* loop) { + int err; + struct watcher_list* root; + + root = uv__inotify_watchers(loop)->rbh_root; + + uv__close(loop->backend_fd); + loop->backend_fd = -1; + + /* TODO(bnoordhuis) Loses items from the submission and completion rings. */ + uv__platform_loop_delete(loop); + + err = uv__platform_loop_init(loop); + if (err) + return err; + + return uv__inotify_fork(loop, root); +} + + +void uv__platform_loop_delete(uv_loop_t* loop) { + uv__loop_internal_fields_t* lfields; + + lfields = uv__get_internal_fields(loop); + uv__iou_delete(&lfields->ctl); + uv__iou_delete(&lfields->iou); + + if (loop->inotify_fd != -1) { + uv__io_stop(loop, &loop->inotify_read_watcher, POLLIN); + uv__close(loop->inotify_fd); + loop->inotify_fd = -1; + } +} + + +struct uv__invalidate { + struct epoll_event (*prep)[256]; + struct epoll_event* events; + int nfds; +}; + + +void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { + uv__loop_internal_fields_t* lfields; + struct uv__invalidate* inv; + struct epoll_event dummy; + int i; + + lfields = uv__get_internal_fields(loop); + inv = (uv__invalidate*)lfields->inv; + + /* Invalidate events with same file descriptor */ + if (inv != NULL) + for (i = 0; i < inv->nfds; i++) + if (inv->events[i].data.fd == fd) + inv->events[i].data.fd = -1; + + /* Remove the file descriptor from the epoll. + * This avoids a problem where the same file description remains open + * in another process, causing repeated junk epoll events. + * + * We pass in a dummy epoll_event, to work around a bug in old kernels. + * + * Work around a bug in kernels 3.10 to 3.19 where passing a struct that + * has the EPOLLWAKEUP flag set generates spurious audit syslog warnings. + */ + memset(&dummy, 0, sizeof(dummy)); + + if (inv == NULL) { + epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &dummy); + } else { + uv__epoll_ctl_prep(loop->backend_fd, + &lfields->ctl, + inv->prep, + EPOLL_CTL_DEL, + fd, + &dummy); + } +} + + +int uv__io_check_fd(uv_loop_t* loop, int fd) { + struct epoll_event e; + int rc; + + memset(&e, 0, sizeof(e)); + e.events = POLLIN; + e.data.fd = -1; + + rc = 0; + if (epoll_ctl(loop->backend_fd, EPOLL_CTL_ADD, fd, &e)) + if (errno != EEXIST) + rc = UV__ERR(errno); + + if (rc == 0) + if (epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &e)) + abort(); + + return rc; +} + + +/* Caller must initialize SQE and call uv__iou_submit(). */ +static struct uv__io_uring_sqe* uv__iou_get_sqe(struct uv__iou* iou, + uv_loop_t* loop, + uv_fs_t* req) { + struct uv__io_uring_sqe* sqe; + uint32_t head; + uint32_t tail; + uint32_t mask; + uint32_t slot; + + if (iou->ringfd == -1) + return NULL; + + head = std::atomic_load_explicit((std::atomic*) iou->sqhead, + std::memory_order_acquire); + tail = *iou->sqtail; + mask = iou->sqmask; + + if ((head & mask) == ((tail + 1) & mask)) + return NULL; /* No room in ring buffer. TODO(bnoordhuis) maybe flush it? */ + + slot = tail & mask; + sqe = (uv__io_uring_sqe*)iou->sqe; + sqe = &sqe[slot]; + memset(sqe, 0, sizeof(*sqe)); + sqe->user_data = (uintptr_t) req; + + /* Pacify uv_cancel(). */ + req->work_req.loop = loop; + req->work_req.work = NULL; + req->work_req.done = NULL; + uv__queue_init(&req->work_req.wq); + + uv__req_register(loop, req); + iou->in_flight++; + + return sqe; +} + + +static void uv__iou_submit(struct uv__iou* iou) { + uint32_t flags; + + std::atomic_store_explicit((std::atomic*) iou->sqtail, + *iou->sqtail + 1, + std::memory_order_release); + + flags = std::atomic_load_explicit((std::atomic*) iou->sqflags, + std::memory_order_acquire); + + if (flags & UV__IORING_SQ_NEED_WAKEUP) + if (uv__io_uring_enter(iou->ringfd, 0, 0, UV__IORING_ENTER_SQ_WAKEUP)) + if (errno != EOWNERDEAD) /* Kernel bug. Harmless, ignore. */ + perror("libuv: io_uring_enter(wakeup)"); /* Can't happen. */ +} + + +int uv__iou_fs_close(uv_loop_t* loop, uv_fs_t* req) { + struct uv__io_uring_sqe* sqe; + struct uv__iou* iou; + + /* Work around a poorly understood bug in older kernels where closing a file + * descriptor pointing to /foo/bar results in ETXTBSY errors when trying to + * execve("/foo/bar") later on. The bug seems to have been fixed somewhere + * between 5.15.85 and 5.15.90. I couldn't pinpoint the responsible commit + * but good candidates are the several data race fixes. Interestingly, it + * seems to manifest only when running under Docker so the possibility of + * a Docker bug can't be completely ruled out either. Yay, computers. + */ + if (uv__kernel_version() < /* 5.15.90 */ 0x050F5A) + return 0; + + iou = &uv__get_internal_fields(loop)->iou; + + sqe = uv__iou_get_sqe(iou, loop, req); + if (sqe == NULL) + return 0; + + sqe->fd = req->file; + sqe->opcode = UV__IORING_OP_CLOSE; + + uv__iou_submit(iou); + + return 1; +} + + +int uv__iou_fs_fsync_or_fdatasync(uv_loop_t* loop, + uv_fs_t* req, + uint32_t fsync_flags) { + struct uv__io_uring_sqe* sqe; + struct uv__iou* iou; + + iou = &uv__get_internal_fields(loop)->iou; + + sqe = uv__iou_get_sqe(iou, loop, req); + if (sqe == NULL) + return 0; + + /* Little known fact: setting seq->off and seq->len turns + * it into an asynchronous sync_file_range() operation. + */ + sqe->fd = req->file; + sqe->fsync_flags = fsync_flags; + sqe->opcode = UV__IORING_OP_FSYNC; + + uv__iou_submit(iou); + + return 1; +} + + +int uv__iou_fs_link(uv_loop_t* loop, uv_fs_t* req) { + struct uv__io_uring_sqe* sqe; + struct uv__iou* iou; + + iou = &uv__get_internal_fields(loop)->iou; + + if (!(iou->flags & UV__MKDIRAT_SYMLINKAT_LINKAT)) + return 0; + + sqe = uv__iou_get_sqe(iou, loop, req); + if (sqe == NULL) + return 0; + + sqe->addr = (uintptr_t) req->path; + sqe->fd = AT_FDCWD; + sqe->addr2 = (uintptr_t) req->new_path; + sqe->len = AT_FDCWD; + sqe->opcode = UV__IORING_OP_LINKAT; + + uv__iou_submit(iou); + + return 1; +} + + +int uv__iou_fs_mkdir(uv_loop_t* loop, uv_fs_t* req) { + struct uv__io_uring_sqe* sqe; + struct uv__iou* iou; + + iou = &uv__get_internal_fields(loop)->iou; + + if (!(iou->flags & UV__MKDIRAT_SYMLINKAT_LINKAT)) + return 0; + + sqe = uv__iou_get_sqe(iou, loop, req); + if (sqe == NULL) + return 0; + + sqe->addr = (uintptr_t) req->path; + sqe->fd = AT_FDCWD; + sqe->len = req->mode; + sqe->opcode = UV__IORING_OP_MKDIRAT; + + uv__iou_submit(iou); + + return 1; +} + + +int uv__iou_fs_open(uv_loop_t* loop, uv_fs_t* req) { + struct uv__io_uring_sqe* sqe; + struct uv__iou* iou; + + iou = &uv__get_internal_fields(loop)->iou; + + sqe = uv__iou_get_sqe(iou, loop, req); + if (sqe == NULL) + return 0; + + sqe->addr = (uintptr_t) req->path; + sqe->fd = AT_FDCWD; + sqe->len = req->mode; + sqe->opcode = UV__IORING_OP_OPENAT; + sqe->open_flags = req->flags | O_CLOEXEC; + + uv__iou_submit(iou); + + return 1; +} + + +int uv__iou_fs_rename(uv_loop_t* loop, uv_fs_t* req) { + struct uv__io_uring_sqe* sqe; + struct uv__iou* iou; + + iou = &uv__get_internal_fields(loop)->iou; + + sqe = uv__iou_get_sqe(iou, loop, req); + if (sqe == NULL) + return 0; + + sqe->addr = (uintptr_t) req->path; + sqe->fd = AT_FDCWD; + sqe->addr2 = (uintptr_t) req->new_path; + sqe->len = AT_FDCWD; + sqe->opcode = UV__IORING_OP_RENAMEAT; + + uv__iou_submit(iou); + + return 1; +} + + +int uv__iou_fs_symlink(uv_loop_t* loop, uv_fs_t* req) { + struct uv__io_uring_sqe* sqe; + struct uv__iou* iou; + + iou = &uv__get_internal_fields(loop)->iou; + + if (!(iou->flags & UV__MKDIRAT_SYMLINKAT_LINKAT)) + return 0; + + sqe = uv__iou_get_sqe(iou, loop, req); + if (sqe == NULL) + return 0; + + sqe->addr = (uintptr_t) req->path; + sqe->fd = AT_FDCWD; + sqe->addr2 = (uintptr_t) req->new_path; + sqe->opcode = UV__IORING_OP_SYMLINKAT; + + uv__iou_submit(iou); + + return 1; +} + + +int uv__iou_fs_unlink(uv_loop_t* loop, uv_fs_t* req) { + struct uv__io_uring_sqe* sqe; + struct uv__iou* iou; + + iou = &uv__get_internal_fields(loop)->iou; + + sqe = uv__iou_get_sqe(iou, loop, req); + if (sqe == NULL) + return 0; + + sqe->addr = (uintptr_t) req->path; + sqe->fd = AT_FDCWD; + sqe->opcode = UV__IORING_OP_UNLINKAT; + + uv__iou_submit(iou); + + return 1; +} + + +int uv__iou_fs_read_or_write(uv_loop_t* loop, + uv_fs_t* req, + int is_read) { + struct uv__io_uring_sqe* sqe; + struct uv__iou* iou; + + /* If iovcnt is greater than IOV_MAX, cap it to IOV_MAX on reads and fallback + * to the threadpool on writes */ + if (req->nbufs > IOV_MAX) { + if (is_read) + req->nbufs = IOV_MAX; + else + return 0; + } + + iou = &uv__get_internal_fields(loop)->iou; + + sqe = uv__iou_get_sqe(iou, loop, req); + if (sqe == NULL) + return 0; + + sqe->addr = (uintptr_t) req->bufs; + sqe->fd = req->file; + sqe->len = req->nbufs; + sqe->off = req->off < 0 ? -1 : req->off; + sqe->opcode = is_read ? UV__IORING_OP_READV : UV__IORING_OP_WRITEV; + + uv__iou_submit(iou); + + return 1; +} + + +int uv__iou_fs_statx(uv_loop_t* loop, + uv_fs_t* req, + int is_fstat, + int is_lstat) { + struct uv__io_uring_sqe* sqe; + struct uv__statx* statxbuf; + struct uv__iou* iou; + + statxbuf = (struct uv__statx*)uv__malloc(sizeof(*statxbuf)); + if (statxbuf == NULL) + return 0; + + iou = &uv__get_internal_fields(loop)->iou; + + sqe = uv__iou_get_sqe(iou, loop, req); + if (sqe == NULL) { + uv__free(statxbuf); + return 0; + } + + req->ptr = statxbuf; + + sqe->addr = (uintptr_t) req->path; + sqe->addr2 = (uintptr_t) statxbuf; + sqe->fd = AT_FDCWD; + sqe->len = 0xFFF; /* STATX_BASIC_STATS + STATX_BTIME */ + sqe->opcode = UV__IORING_OP_STATX; + + if (is_fstat) { + sqe->addr = (uintptr_t) ""; + sqe->fd = req->file; + sqe->statx_flags |= 0x1000; /* AT_EMPTY_PATH */ + } + + if (is_lstat) + sqe->statx_flags |= AT_SYMLINK_NOFOLLOW; + + uv__iou_submit(iou); + + return 1; +} + + +void uv__statx_to_stat(const struct uv__statx* statxbuf, uv_stat_t* buf) { + buf->st_dev = makedev(statxbuf->stx_dev_major, statxbuf->stx_dev_minor); + buf->st_mode = statxbuf->stx_mode; + buf->st_nlink = statxbuf->stx_nlink; + buf->st_uid = statxbuf->stx_uid; + buf->st_gid = statxbuf->stx_gid; + buf->st_rdev = makedev(statxbuf->stx_rdev_major, statxbuf->stx_rdev_minor); + buf->st_ino = statxbuf->stx_ino; + buf->st_size = statxbuf->stx_size; + buf->st_blksize = statxbuf->stx_blksize; + buf->st_blocks = statxbuf->stx_blocks; + buf->st_atim.tv_sec = statxbuf->stx_atime.tv_sec; + buf->st_atim.tv_nsec = statxbuf->stx_atime.tv_nsec; + buf->st_mtim.tv_sec = statxbuf->stx_mtime.tv_sec; + buf->st_mtim.tv_nsec = statxbuf->stx_mtime.tv_nsec; + buf->st_ctim.tv_sec = statxbuf->stx_ctime.tv_sec; + buf->st_ctim.tv_nsec = statxbuf->stx_ctime.tv_nsec; + buf->st_birthtim.tv_sec = statxbuf->stx_btime.tv_sec; + buf->st_birthtim.tv_nsec = statxbuf->stx_btime.tv_nsec; + buf->st_flags = 0; + buf->st_gen = 0; +} + + +static void uv__iou_fs_statx_post(uv_fs_t* req) { + struct uv__statx* statxbuf; + uv_stat_t* buf; + + buf = &req->statbuf; + statxbuf = (struct uv__statx*)req->ptr; + req->ptr = NULL; + + if (req->result == 0) { + uv__msan_unpoison(statxbuf, sizeof(*statxbuf)); + uv__statx_to_stat(statxbuf, buf); + req->ptr = buf; + } + + uv__free(statxbuf); +} + + +static void uv__poll_io_uring(uv_loop_t* loop, struct uv__iou* iou) { + struct uv__io_uring_cqe* cqe; + struct uv__io_uring_cqe* e; + uv_fs_t* req; + uint32_t head; + uint32_t tail; + uint32_t mask; + uint32_t i; + uint32_t flags; + int nevents; + int rc; + + head = *iou->cqhead; + tail = std::atomic_load_explicit((std::atomic*) iou->cqtail, + std::memory_order_acquire); + mask = iou->cqmask; + cqe = (uv__io_uring_cqe*)iou->cqe; + nevents = 0; + + for (i = head; i != tail; i++) { + e = &cqe[i & mask]; + + req = (uv_fs_t*) (uintptr_t) e->user_data; + assert(req->type == UV_FS); + + uv__req_unregister(loop, req); + iou->in_flight--; + + /* io_uring stores error codes as negative numbers, same as libuv. */ + req->result = e->res; + + switch (req->fs_type) { + case UV_FS_FSTAT: + case UV_FS_LSTAT: + case UV_FS_STAT: + uv__iou_fs_statx_post(req); + break; + default: /* Squelch -Wswitch warnings. */ + break; + } + + uv__metrics_update_idle_time(loop); + req->cb(req); + nevents++; + } + + std::atomic_store_explicit((std::atomic*) iou->cqhead, + tail, + std::memory_order_release); + + /* Check whether CQE's overflowed, if so enter the kernel to make them + * available. Don't grab them immediately but in the next loop iteration to + * avoid loop starvation. */ + flags = std::atomic_load_explicit((std::atomic*) iou->sqflags, + std::memory_order_acquire); + + if (flags & UV__IORING_SQ_CQ_OVERFLOW) { + do + rc = uv__io_uring_enter(iou->ringfd, 0, 0, UV__IORING_ENTER_GETEVENTS); + while (rc == -1 && errno == EINTR); + + if (rc < 0) + perror("libuv: io_uring_enter(getevents)"); /* Can't happen. */ + } + + uv__metrics_inc_events(loop, nevents); + if (uv__get_internal_fields(loop)->current_timeout == 0) + uv__metrics_inc_events_waiting(loop, nevents); +} + + +static void uv__epoll_ctl_prep(int epollfd, + struct uv__iou* ctl, + struct epoll_event (*events)[256], + int op, + int fd, + struct epoll_event* e) { + struct uv__io_uring_sqe* sqe; + struct epoll_event* pe; + uint32_t mask; + uint32_t slot; + + if (ctl->ringfd == -1) { + if (!epoll_ctl(epollfd, op, fd, e)) + return; + + if (op == EPOLL_CTL_DEL) + return; /* Ignore errors, may be racing with another thread. */ + + if (op != EPOLL_CTL_ADD) + abort(); + + if (errno != EEXIST) + abort(); + + /* File descriptor that's been watched before, update event mask. */ + if (!epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, e)) + return; + + abort(); + } else { + mask = ctl->sqmask; + slot = (*ctl->sqtail)++ & mask; + + pe = &(*events)[slot]; + *pe = *e; + + sqe = (uv__io_uring_sqe*)ctl->sqe; + sqe = &sqe[slot]; + + memset(sqe, 0, sizeof(*sqe)); + sqe->addr = (uintptr_t) pe; + sqe->fd = epollfd; + sqe->len = op; + sqe->off = fd; + sqe->opcode = UV__IORING_OP_EPOLL_CTL; + sqe->user_data = op | slot << 2 | (int64_t) fd << 32; + + if ((*ctl->sqhead & mask) == (*ctl->sqtail & mask)) + uv__epoll_ctl_flush(epollfd, ctl, events); + } +} + + +static void uv__epoll_ctl_flush(int epollfd, + struct uv__iou* ctl, + struct epoll_event (*events)[256]) { + struct epoll_event oldevents[256]; + struct uv__io_uring_cqe* cqe; + uint32_t oldslot; + uint32_t slot; + uint32_t n; + int fd; + int op; + int rc; + + STATIC_ASSERT(sizeof(oldevents) == sizeof(*events)); + assert(ctl->ringfd != -1); + assert(*ctl->sqhead != *ctl->sqtail); + + n = *ctl->sqtail - *ctl->sqhead; + do + rc = uv__io_uring_enter(ctl->ringfd, n, n, UV__IORING_ENTER_GETEVENTS); + while (rc == -1 && errno == EINTR); + + if (rc < 0) + perror("libuv: io_uring_enter(getevents)"); /* Can't happen. */ + + if (rc != (int) n) + abort(); + + assert(*ctl->sqhead == *ctl->sqtail); + + memcpy(oldevents, *events, sizeof(*events)); + + /* Failed submissions are either EPOLL_CTL_DEL commands for file descriptors + * that have been closed, or EPOLL_CTL_ADD commands for file descriptors + * that we are already watching. Ignore the former and retry the latter + * with EPOLL_CTL_MOD. + */ + while (*ctl->cqhead != *ctl->cqtail) { + slot = (*ctl->cqhead)++ & ctl->cqmask; + + cqe = (uv__io_uring_cqe*)ctl->cqe; + cqe = &cqe[slot]; + + if (cqe->res == 0) + continue; + + fd = cqe->user_data >> 32; + op = 3 & cqe->user_data; + oldslot = 255 & (cqe->user_data >> 2); + + if (op == EPOLL_CTL_DEL) + continue; + + if (op != EPOLL_CTL_ADD) + abort(); + + if (cqe->res != -EEXIST) + abort(); + + uv__epoll_ctl_prep(epollfd, + ctl, + events, + EPOLL_CTL_MOD, + fd, + &oldevents[oldslot]); + } +} + + +void uv__io_poll(uv_loop_t* loop, int timeout) { + uv__loop_internal_fields_t* lfields; + struct epoll_event events[1024]; + struct epoll_event prep[256]; + struct uv__invalidate inv; + struct epoll_event* pe; + struct epoll_event e; + struct uv__iou* ctl; + struct uv__iou* iou; + int real_timeout; + struct uv__queue* q; + uv__io_t* w; + sigset_t* sigmask; + sigset_t sigset; + uint64_t base; + int have_iou_events; + int have_signals; + int nevents; + int epollfd; + int count; + int nfds; + int fd; + int op; + int i; + int user_timeout; + int reset_timeout; + + lfields = uv__get_internal_fields(loop); + ctl = &lfields->ctl; + iou = &lfields->iou; + + sigmask = NULL; + if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { + sigemptyset(&sigset); + sigaddset(&sigset, SIGPROF); + sigmask = &sigset; + } + + assert(timeout >= -1); + base = loop->time; + count = 48; /* Benchmarks suggest this gives the best throughput. */ + real_timeout = timeout; + + if (lfields->flags & UV_METRICS_IDLE_TIME) { + reset_timeout = 1; + user_timeout = timeout; + timeout = 0; + } else { + reset_timeout = 0; + user_timeout = 0; + } + + epollfd = loop->backend_fd; + + memset(&e, 0, sizeof(e)); + + while (!uv__queue_empty(&loop->watcher_queue)) { + q = uv__queue_head(&loop->watcher_queue); + w = uv__queue_data(q, uv__io_t, watcher_queue); + uv__queue_remove(q); + uv__queue_init(q); + + op = EPOLL_CTL_MOD; + if (w->events == 0) + op = EPOLL_CTL_ADD; + + w->events = w->pevents; + e.events = w->pevents; + e.data.fd = w->fd; + + uv__epoll_ctl_prep(epollfd, ctl, &prep, op, w->fd, &e); + } + + inv.events = events; + inv.prep = &prep; + inv.nfds = -1; + + for (;;) { + if (loop->nfds == 0) + if (iou->in_flight == 0) + break; + + /* All event mask mutations should be visible to the kernel before + * we enter epoll_pwait(). + */ + if (ctl->ringfd != -1) + while (*ctl->sqhead != *ctl->sqtail) + uv__epoll_ctl_flush(epollfd, ctl, &prep); + + /* Only need to set the provider_entry_time if timeout != 0. The function + * will return early if the loop isn't configured with UV_METRICS_IDLE_TIME. + */ + if (timeout != 0) + uv__metrics_set_provider_entry_time(loop); + + /* Store the current timeout in a location that's globally accessible so + * other locations like uv__work_done() can determine whether the queue + * of events in the callback were waiting when poll was called. + */ + lfields->current_timeout = timeout; + + nfds = epoll_pwait(epollfd, events, ARRAY_SIZE(events), timeout, sigmask); + + /* 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); + + if (reset_timeout != 0) { + timeout = user_timeout; + reset_timeout = 0; + } + + if (timeout == -1) + continue; + + if (timeout == 0) + break; + + /* We may have been inside the system call for longer than |timeout| + * milliseconds so we need to update the timestamp to avoid drift. + */ + goto update_timeout; + } + + if (nfds == -1) { + if (errno != EINTR) + abort(); + + if (reset_timeout != 0) { + timeout = user_timeout; + reset_timeout = 0; + } + + if (timeout == -1) + continue; + + if (timeout == 0) + break; + + /* Interrupted by a signal. Update timeout and poll again. */ + goto update_timeout; + } + + have_iou_events = 0; + have_signals = 0; + nevents = 0; + + inv.nfds = nfds; + lfields->inv = &inv; + + for (i = 0; i < nfds; i++) { + pe = events + i; + fd = pe->data.fd; + + /* Skip invalidated events, see uv__platform_invalidate_fd */ + if (fd == -1) + continue; + + if (fd == iou->ringfd) { + uv__poll_io_uring(loop, iou); + have_iou_events = 1; + continue; + } + + assert(fd >= 0); + assert((unsigned) fd < loop->nwatchers); + + w = loop->watchers[fd]; + + if (w == NULL) { + /* File descriptor that we've stopped watching, disarm it. + * + * Ignore all errors because we may be racing with another thread + * when the file descriptor is closed. + */ + uv__epoll_ctl_prep(epollfd, ctl, &prep, EPOLL_CTL_DEL, fd, pe); + continue; + } + + /* Give users only events they're interested in. Prevents spurious + * callbacks when previous callback invocation in this loop has stopped + * the current watcher. Also, filters out events that users has not + * requested us to watch. + */ + pe->events &= w->pevents | POLLERR | POLLHUP; + + /* Work around an epoll quirk where it sometimes reports just the + * EPOLLERR or EPOLLHUP event. In order to force the event loop to + * move forward, we merge in the read/write events that the watcher + * is interested in; uv__read() and uv__write() will then deal with + * the error or hangup in the usual fashion. + * + * Note to self: happens when epoll reports EPOLLIN|EPOLLHUP, the user + * reads the available data, calls uv_read_stop(), then sometime later + * calls uv_read_start() again. By then, libuv has forgotten about the + * hangup and the kernel won't report EPOLLIN again because there's + * nothing left to read. If anything, libuv is to blame here. The + * current hack is just a quick bandaid; to properly fix it, libuv + * needs to remember the error/hangup event. We should get that for + * free when we switch over to edge-triggered I/O. + */ + if (pe->events == POLLERR || pe->events == POLLHUP) + pe->events |= + w->pevents & (POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI); + + if (pe->events != 0) { + /* Run signal watchers last. This also affects child process watchers + * because those are implemented in terms of signal watchers. + */ + if (w == &loop->signal_io_watcher) { + have_signals = 1; + } else { + uv__metrics_update_idle_time(loop); + w->cb(loop, w, pe->events); + } + + nevents++; + } + } + + uv__metrics_inc_events(loop, nevents); + if (reset_timeout != 0) { + timeout = user_timeout; + reset_timeout = 0; + uv__metrics_inc_events_waiting(loop, nevents); + } + + if (have_signals != 0) { + uv__metrics_update_idle_time(loop); + loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); + } + + lfields->inv = NULL; + + if (have_iou_events != 0) + break; /* Event loop should cycle now so don't poll again. */ + + if (have_signals != 0) + break; /* Event loop should cycle now so don't poll again. */ + + if (nevents != 0) { + if (nfds == ARRAY_SIZE(events) && --count != 0) { + /* Poll for more events but don't block this time. */ + timeout = 0; + continue; + } + break; + } + + if (timeout == 0) + break; + + if (timeout == -1) + continue; + +update_timeout: + assert(timeout > 0); + + real_timeout -= (loop->time - base); + if (real_timeout <= 0) + break; + + timeout = real_timeout; + } + + if (ctl->ringfd != -1) + while (*ctl->sqhead != *ctl->sqtail) + uv__epoll_ctl_flush(epollfd, ctl, &prep); +} + +uint64_t uv__hrtime(uv_clocktype_t type) { + static std::atomic fast_clock_id = -1; + struct timespec t; + clock_t clock_id; + + /* Prefer CLOCK_MONOTONIC_COARSE if available but only when it has + * millisecond granularity or better. CLOCK_MONOTONIC_COARSE is + * serviced entirely from the vDSO, whereas CLOCK_MONOTONIC may + * decide to make a costly system call. + */ + /* TODO(bnoordhuis) Use CLOCK_MONOTONIC_COARSE for UV_CLOCK_PRECISE + * when it has microsecond granularity or better (unlikely). + */ + clock_id = CLOCK_MONOTONIC; + if (type != UV_CLOCK_FAST) + goto done; + + clock_id = std::atomic_load_explicit(&fast_clock_id, std::memory_order_relaxed); + if (clock_id != -1) + goto done; + + clock_id = CLOCK_MONOTONIC; + if (0 == clock_getres(CLOCK_MONOTONIC_COARSE, &t)) + if (t.tv_nsec <= 1 * 1000 * 1000) + clock_id = CLOCK_MONOTONIC_COARSE; + + std::atomic_store_explicit(&fast_clock_id, clock_id, std::memory_order_relaxed); + +done: + + if (clock_gettime(clock_id, &t)) + return 0; /* Not really possible. */ + + return t.tv_sec * (uint64_t) 1e9 + t.tv_nsec; +} + + +int uv_resident_set_memory(size_t* rss) { + char buf[1024]; + const char* s; + ssize_t n; + long val; + int fd; + int i; + + do + fd = open("/proc/self/stat", O_RDONLY); + while (fd == -1 && errno == EINTR); + + if (fd == -1) + return UV__ERR(errno); + + do + n = read(fd, buf, sizeof(buf) - 1); + while (n == -1 && errno == EINTR); + + uv__close(fd); + if (n == -1) + return UV__ERR(errno); + buf[n] = '\0'; + + s = strchr(buf, ' '); + if (s == NULL) + goto err; + + s += 1; + if (*s != '(') + goto err; + + s = strchr(s, ')'); + if (s == NULL) + goto err; + + for (i = 1; i <= 22; i++) { + s = strchr(s + 1, ' '); + if (s == NULL) + goto err; + } + + errno = 0; + val = strtol(s, NULL, 10); + if (errno != 0) + goto err; + if (val < 0) + goto err; + + *rss = val * getpagesize(); + return 0; + +err: + return UV_EINVAL; +} + +int uv_uptime(double* uptime) { + struct timespec now; + char buf[128]; + + /* Consult /proc/uptime when present (common case), or fall back to + * clock_gettime. Why not always clock_gettime? It doesn't always return the + * right result under OpenVZ and possibly other containerized environments. + */ + if (0 == uv__slurp("/proc/uptime", buf, sizeof(buf))) + if (1 == sscanf(buf, "%lf", uptime)) + return 0; + + if (clock_gettime(CLOCK_BOOTTIME, &now)) + return UV__ERR(errno); + + *uptime = now.tv_sec; + return 0; +} + + +int uv_cpu_info(uv_cpu_info_t** ci, int* count) { +#if defined(__PPC__) + static const char model_marker[] = "cpu\t\t: "; +#elif defined(__arm__) + static const char model_marker[] = "Processor\t: "; +#elif defined(__aarch64__) + static const char model_marker[] = "CPU part\t: "; +#elif defined(__mips__) + static const char model_marker[] = "cpu model\t\t: "; +#elif defined(__loongarch__) + static const char model_marker[] = "cpu family\t\t: "; +#else + static const char model_marker[] = "model name\t: "; +#endif + static const char parts[] = +#ifdef __aarch64__ + "0x811\nARM810\n" "0x920\nARM920\n" "0x922\nARM922\n" + "0x926\nARM926\n" "0x940\nARM940\n" "0x946\nARM946\n" + "0x966\nARM966\n" "0xa20\nARM1020\n" "0xa22\nARM1022\n" + "0xa26\nARM1026\n" "0xb02\nARM11 MPCore\n" "0xb36\nARM1136\n" + "0xb56\nARM1156\n" "0xb76\nARM1176\n" "0xc05\nCortex-A5\n" + "0xc07\nCortex-A7\n" "0xc08\nCortex-A8\n" "0xc09\nCortex-A9\n" + "0xc0d\nCortex-A17\n" /* Originally A12 */ + "0xc0f\nCortex-A15\n" "0xc0e\nCortex-A17\n" "0xc14\nCortex-R4\n" + "0xc15\nCortex-R5\n" "0xc17\nCortex-R7\n" "0xc18\nCortex-R8\n" + "0xc20\nCortex-M0\n" "0xc21\nCortex-M1\n" "0xc23\nCortex-M3\n" + "0xc24\nCortex-M4\n" "0xc27\nCortex-M7\n" "0xc60\nCortex-M0+\n" + "0xd01\nCortex-A32\n" "0xd03\nCortex-A53\n" "0xd04\nCortex-A35\n" + "0xd05\nCortex-A55\n" "0xd06\nCortex-A65\n" "0xd07\nCortex-A57\n" + "0xd08\nCortex-A72\n" "0xd09\nCortex-A73\n" "0xd0a\nCortex-A75\n" + "0xd0b\nCortex-A76\n" "0xd0c\nNeoverse-N1\n" "0xd0d\nCortex-A77\n" + "0xd0e\nCortex-A76AE\n" "0xd13\nCortex-R52\n" "0xd20\nCortex-M23\n" + "0xd21\nCortex-M33\n" "0xd41\nCortex-A78\n" "0xd42\nCortex-A78AE\n" + "0xd4a\nNeoverse-E1\n" "0xd4b\nCortex-A78C\n" +#endif + ""; + struct cpu { + unsigned long long freq, user, nice, sys, idle, irq; + unsigned model; + }; + FILE* fp; + char* p; + int found; + int n; + unsigned i; + unsigned cpu; + unsigned maxcpu; + unsigned size; + unsigned long long skip; + struct cpu (*cpus)[8192]; /* Kernel maximum. */ + struct cpu* c; + struct cpu t; + char (*model)[64]; + unsigned char bitmap[ARRAY_SIZE(*cpus) / 8]; + /* Assumption: even big.LITTLE systems will have only a handful + * of different CPU models. Most systems will just have one. + */ + char models[8][64]; + char buf[1024]; + + memset(bitmap, 0, sizeof(bitmap)); + memset(models, 0, sizeof(models)); + snprintf(*models, sizeof(*models), "unknown"); + maxcpu = 0; + + cpus = (decltype(cpus))uv__calloc(ARRAY_SIZE(*cpus), sizeof(**cpus)); + if (cpus == NULL) + return UV_ENOMEM; + + fp = uv__open_file("/proc/stat"); + if (fp == NULL) { + uv__free(cpus); + return UV__ERR(errno); + } + + /* Skip first line. */ + if (!fgets(buf, sizeof(buf), fp)) { + uv__free(cpus); + return UV__ERR(errno); + } + + for (;;) { + memset(&t, 0, sizeof(t)); + + n = fscanf(fp, "cpu%u %llu %llu %llu %llu %llu %llu", + &cpu, &t.user, &t.nice, &t.sys, &t.idle, &skip, &t.irq); + + if (n != 7) + break; + + /* Skip rest of line. */ + if (!fgets(buf, sizeof(buf), fp)) { + break; + } + + if (cpu >= ARRAY_SIZE(*cpus)) + continue; + + (*cpus)[cpu] = t; + + bitmap[cpu >> 3] |= 1 << (cpu & 7); + + if (cpu >= maxcpu) + maxcpu = cpu + 1; + } + + fclose(fp); + + fp = uv__open_file("/proc/cpuinfo"); + if (fp == NULL) + goto nocpuinfo; + + for (;;) { + if (1 != fscanf(fp, "processor\t: %u\n", &cpu)) + break; /* Parse error. */ + + found = 0; + while (!found && fgets(buf, sizeof(buf), fp)) + found = !strncmp(buf, model_marker, sizeof(model_marker) - 1); + + if (!found) + goto next; + + p = buf + sizeof(model_marker) - 1; + n = (int) strcspn(p, "\n"); + + /* arm64: translate CPU part code to model name. */ + if (*parts) { + p = (char*)memmem(parts, sizeof(parts) - 1, p, n + 1); + if (p == NULL) + p = const_cast("unknown"); + else + p += n + 1; + n = (int) strcspn(p, "\n"); + } + + found = 0; + for (model = models; !found && model < ARRAY_END(models); model++) + found = !strncmp(p, *model, strlen(*model)); + + if (!found) + goto next; + + if (**model == '\0') + snprintf(*model, sizeof(*model), "%.*s", n, p); + + if (cpu < maxcpu) + (*cpus)[cpu].model = model - models; + +next: + while (fgets(buf, sizeof(buf), fp)) + if (*buf == '\n') + break; + } + + fclose(fp); + fp = NULL; + +nocpuinfo: + + n = 0; + for (cpu = 0; cpu < maxcpu; cpu++) { + if (!(bitmap[cpu >> 3] & (1 << (cpu & 7)))) + continue; + + n++; + snprintf(buf, sizeof(buf), + "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_cur_freq", cpu); + + fp = uv__open_file(buf); + if (fp == NULL) + continue; + + if (0 > fscanf(fp, "%llu", &(*cpus)[cpu].freq)) { + (*cpus)[cpu].freq = 0llu; + } + fclose(fp); + fp = NULL; + } + + size = n * sizeof(**ci) + sizeof(models); + *ci = (uv_cpu_info_t*)uv__malloc(size); + *count = 0; + + if (*ci == NULL) { + uv__free(cpus); + return UV_ENOMEM; + } + + *count = n; + p = (char*)memcpy(*ci + n, models, sizeof(models)); + + i = 0; + for (cpu = 0; cpu < maxcpu; cpu++) { + if (!(bitmap[cpu >> 3] & (1 << (cpu & 7)))) + continue; + + c = *cpus + cpu; + + (*ci)[i++] = uv_cpu_info_t{ + .model = p + c->model * sizeof(*model), + .speed = (int)(c->freq / 1000), + /* Note: sysconf(_SC_CLK_TCK) is fixed at 100 Hz, + * therefore the multiplier is always 1000/100 = 10. + */ + .cpu_times = { + .user = 10 * c->user, + .nice = 10 * c->nice, + .sys = 10 * c->sys, + .idle = 10 * c->idle, + .irq = 10 * c->irq, + } + }; + } + + uv__free(cpus); + + return 0; +} + + +#ifdef HAVE_IFADDRS_H +static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { + if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) + return 1; + if (ent->ifa_addr == NULL) + return 1; + /* + * On Linux getifaddrs returns information related to the raw underlying + * devices. We're not interested in this information yet. + */ + if (ent->ifa_addr->sa_family == PF_PACKET) + return exclude_type; + return !exclude_type; +} +#endif + +int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { +#ifndef HAVE_IFADDRS_H + *count = 0; + *addresses = NULL; + return UV_ENOSYS; +#else + struct ifaddrs *addrs, *ent; + uv_interface_address_t* address; + int i; + struct sockaddr_ll *sll; + + *count = 0; + *addresses = NULL; + + if (getifaddrs(&addrs)) + return UV__ERR(errno); + + /* Count the number of interfaces */ + for (ent = addrs; ent != NULL; ent = ent->ifa_next) { + if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR)) + continue; + + (*count)++; + } + + if (*count == 0) { + freeifaddrs(addrs); + return 0; + } + + /* Make sure the memory is initiallized to zero using calloc() */ + *addresses = (uv_interface_address_t*)uv__calloc(*count, sizeof(**addresses)); + if (!(*addresses)) { + freeifaddrs(addrs); + return UV_ENOMEM; + } + + address = *addresses; + + for (ent = addrs; ent != NULL; ent = ent->ifa_next) { + if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR)) + continue; + + address->name = uv__strdup(ent->ifa_name); + + if (ent->ifa_addr->sa_family == AF_INET6) { + address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); + } else { + address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr); + } + + if (ent->ifa_netmask->sa_family == AF_INET6) { + address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask); + } else { + address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask); + } + + address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK); + + address++; + } + + /* Fill in physical addresses for each interface */ + for (ent = addrs; ent != NULL; ent = ent->ifa_next) { + if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS)) + continue; + + address = *addresses; + + for (i = 0; i < (*count); i++) { + size_t namelen = strlen(ent->ifa_name); + /* Alias interface share the same physical address */ + if (strncmp(address->name, ent->ifa_name, namelen) == 0 && + (address->name[namelen] == 0 || address->name[namelen] == ':')) { + sll = (struct sockaddr_ll*)ent->ifa_addr; + memcpy(address->phys_addr, sll->sll_addr, sizeof(address->phys_addr)); + } + address++; + } + } + + freeifaddrs(addrs); + + return 0; +#endif +} + + +void uv_free_interface_addresses(uv_interface_address_t* addresses, + int count) { + int i; + + for (i = 0; i < count; i++) { + uv__free(addresses[i].name); + } + + uv__free(addresses); +} + + +void uv__set_process_title(const char* title) { +#if defined(PR_SET_NAME) + prctl(PR_SET_NAME, title); /* Only copies first 16 characters. */ +#endif +} + + +static uint64_t uv__read_proc_meminfo(const char* what) { + uint64_t rc; + char* p; + char buf[4096]; /* Large enough to hold all of /proc/meminfo. */ + + if (uv__slurp("/proc/meminfo", buf, sizeof(buf))) + return 0; + + p = strstr(buf, what); + + if (p == NULL) + return 0; + + p += strlen(what); + + rc = 0; + sscanf(p, "%" PRIu64 " kB", &rc); + + return rc * 1024; +} + + +uint64_t uv_get_free_memory(void) { + struct sysinfo info; + uint64_t rc; + + rc = uv__read_proc_meminfo("MemAvailable:"); + + if (rc != 0) + return rc; + + if (0 == sysinfo(&info)) + return (uint64_t) info.freeram * info.mem_unit; + + return 0; +} + + +uint64_t uv_get_total_memory(void) { + struct sysinfo info; + uint64_t rc; + + rc = uv__read_proc_meminfo("MemTotal:"); + + if (rc != 0) + return rc; + + if (0 == sysinfo(&info)) + return (uint64_t) info.totalram * info.mem_unit; + + return 0; +} + + +static uint64_t uv__read_uint64(const char* filename) { + char buf[32]; /* Large enough to hold an encoded uint64_t. */ + uint64_t rc; + + rc = 0; + if (0 == uv__slurp(filename, buf, sizeof(buf))) + if (1 != sscanf(buf, "%" PRIu64, &rc)) + if (0 == strcmp(buf, "max\n")) + rc = UINT64_MAX; + + return rc; +} + + +/* Given a buffer with the contents of a cgroup1 /proc/self/cgroups, + * finds the location and length of the memory controller mount path. + * This disregards the leading / for easy concatenation of paths. + * Returns NULL if the memory controller wasn't found. */ +static char* uv__cgroup1_find_memory_controller(char buf[1024], + int* n) { + char* p; + + /* Seek to the memory controller line. */ + p = strchr(buf, ':'); + while (p != NULL && strncmp(p, ":memory:", 8)) { + p = strchr(p, '\n'); + if (p != NULL) + p = strchr(p, ':'); + } + + if (p != NULL) { + /* Determine the length of the mount path. */ + p = p + strlen(":memory:/"); + *n = (int) strcspn(p, "\n"); + } + + return p; +} + +static void uv__get_cgroup1_memory_limits(char buf[1024], uint64_t* high, + uint64_t* max) { + char filename[4097]; + char* p; + int n; + uint64_t cgroup1_max; + + /* Find out where the controller is mounted. */ + p = uv__cgroup1_find_memory_controller(buf, &n); + if (p != NULL) { + snprintf(filename, sizeof(filename), + "/sys/fs/cgroup/memory/%.*s/memory.soft_limit_in_bytes", n, p); + *high = uv__read_uint64(filename); + + snprintf(filename, sizeof(filename), + "/sys/fs/cgroup/memory/%.*s/memory.limit_in_bytes", n, p); + *max = uv__read_uint64(filename); + + /* If the controller wasn't mounted, the reads above will have failed, + * as indicated by uv__read_uint64 returning 0. + */ + if (*high != 0 && *max != 0) + goto update_limits; + } + + /* Fall back to the limits of the global memory controller. */ + *high = uv__read_uint64("/sys/fs/cgroup/memory/memory.soft_limit_in_bytes"); + *max = uv__read_uint64("/sys/fs/cgroup/memory/memory.limit_in_bytes"); + + /* uv__read_uint64 detects cgroup2's "max", so we need to separately detect + * cgroup1's maximum value (which is derived from LONG_MAX and PAGE_SIZE). + */ +update_limits: + cgroup1_max = LONG_MAX & ~(sysconf(_SC_PAGESIZE) - 1); + if (*high == cgroup1_max) + *high = UINT64_MAX; + if (*max == cgroup1_max) + *max = UINT64_MAX; +} + +static void uv__get_cgroup2_memory_limits(char buf[1024], uint64_t* high, + uint64_t* max) { + char filename[4097]; + char* p; + int n; + + /* Find out where the controller is mounted. */ + p = buf + strlen("0::/"); + n = (int) strcspn(p, "\n"); + + /* Read the memory limits of the controller. */ + snprintf(filename, sizeof(filename), "/sys/fs/cgroup/%.*s/memory.max", n, p); + *max = uv__read_uint64(filename); + snprintf(filename, sizeof(filename), "/sys/fs/cgroup/%.*s/memory.high", n, p); + *high = uv__read_uint64(filename); +} + +static uint64_t uv__get_cgroup_constrained_memory(char buf[1024]) { + uint64_t high; + uint64_t max; + + /* In the case of cgroupv2, we'll only have a single entry. */ + if (strncmp(buf, "0::/", 4)) + uv__get_cgroup1_memory_limits(buf, &high, &max); + else + uv__get_cgroup2_memory_limits(buf, &high, &max); + + if (high == 0 || max == 0) + return 0; + + return high < max ? high : max; +} + +uint64_t uv_get_constrained_memory(void) { + char buf[1024]; + + if (uv__slurp("/proc/self/cgroup", buf, sizeof(buf))) + return 0; + + return uv__get_cgroup_constrained_memory(buf); +} + + +static uint64_t uv__get_cgroup1_current_memory(char buf[1024]) { + char filename[4097]; + uint64_t current; + char* p; + int n; + + /* Find out where the controller is mounted. */ + p = uv__cgroup1_find_memory_controller(buf, &n); + if (p != NULL) { + snprintf(filename, sizeof(filename), + "/sys/fs/cgroup/memory/%.*s/memory.usage_in_bytes", n, p); + current = uv__read_uint64(filename); + + /* If the controller wasn't mounted, the reads above will have failed, + * as indicated by uv__read_uint64 returning 0. + */ + if (current != 0) + return current; + } + + /* Fall back to the usage of the global memory controller. */ + return uv__read_uint64("/sys/fs/cgroup/memory/memory.usage_in_bytes"); +} + +static uint64_t uv__get_cgroup2_current_memory(char buf[1024]) { + char filename[4097]; + char* p; + int n; + + /* Find out where the controller is mounted. */ + p = buf + strlen("0::/"); + n = (int) strcspn(p, "\n"); + + snprintf(filename, sizeof(filename), + "/sys/fs/cgroup/%.*s/memory.current", n, p); + return uv__read_uint64(filename); +} + +uint64_t uv_get_available_memory(void) { + char buf[1024]; + uint64_t constrained; + uint64_t current; + uint64_t total; + + if (uv__slurp("/proc/self/cgroup", buf, sizeof(buf))) + return 0; + + constrained = uv__get_cgroup_constrained_memory(buf); + if (constrained == 0) + return uv_get_free_memory(); + + total = uv_get_total_memory(); + if (constrained > total) + return uv_get_free_memory(); + + /* In the case of cgroupv2, we'll only have a single entry. */ + if (strncmp(buf, "0::/", 4)) + current = uv__get_cgroup1_current_memory(buf); + else + current = uv__get_cgroup2_current_memory(buf); + + /* memory usage can be higher than the limit (for short bursts of time) */ + if (constrained < current) + return 0; + + return constrained - current; +} + + +void uv_loadavg(double avg[3]) { + struct sysinfo info; + char buf[128]; /* Large enough to hold all of /proc/loadavg. */ + + if (0 == uv__slurp("/proc/loadavg", buf, sizeof(buf))) + if (3 == sscanf(buf, "%lf %lf %lf", &avg[0], &avg[1], &avg[2])) + return; + + if (sysinfo(&info) < 0) + return; + + avg[0] = (double) info.loads[0] / 65536.0; + avg[1] = (double) info.loads[1] / 65536.0; + avg[2] = (double) info.loads[2] / 65536.0; +} + + +static int compare_watchers(const struct watcher_list* a, + const struct watcher_list* b) { + if (a->wd < b->wd) return -1; + if (a->wd > b->wd) return 1; + return 0; +} + + +static int init_inotify(uv_loop_t* loop) { + int fd; + + if (loop->inotify_fd != -1) + return 0; + + fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); + if (fd < 0) + return UV__ERR(errno); + + loop->inotify_fd = fd; + uv__io_init(&loop->inotify_read_watcher, uv__inotify_read, loop->inotify_fd); + uv__io_start(loop, &loop->inotify_read_watcher, POLLIN); + + return 0; +} + + +static int uv__inotify_fork(uv_loop_t* loop, struct watcher_list* root) { + /* Open the inotify_fd, and re-arm all the inotify watchers. */ + int err; + struct watcher_list* tmp_watcher_list_iter; + struct watcher_list* watcher_list; + struct watcher_list tmp_watcher_list; + struct uv__queue queue; + struct uv__queue* q; + uv_fs_event_t* handle; + char* tmp_path; + + if (root == NULL) + return 0; + + /* We must restore the old watcher list to be able to close items + * out of it. + */ + loop->inotify_watchers = root; + + uv__queue_init(&tmp_watcher_list.watchers); + /* Note that the queue we use is shared with the start and stop() + * functions, making uv__queue_foreach unsafe to use. So we use the + * uv__queue_move trick to safely iterate. Also don't free the watcher + * list until we're done iterating. c.f. uv__inotify_read. + */ + RB_FOREACH_SAFE(watcher_list, watcher_root, + uv__inotify_watchers(loop), tmp_watcher_list_iter) { + watcher_list->iterating = 1; + uv__queue_move(&watcher_list->watchers, &queue); + while (!uv__queue_empty(&queue)) { + q = uv__queue_head(&queue); + handle = uv__queue_data(q, uv_fs_event_t, watchers); + /* It's critical to keep a copy of path here, because it + * will be set to NULL by stop() and then deallocated by + * maybe_free_watcher_list + */ + tmp_path = uv__strdup(handle->path); + assert(tmp_path != NULL); + uv__queue_remove(q); + uv__queue_insert_tail(&watcher_list->watchers, q); + uv_fs_event_stop(handle); + + uv__queue_insert_tail(&tmp_watcher_list.watchers, &handle->watchers); + handle->path = tmp_path; + } + watcher_list->iterating = 0; + maybe_free_watcher_list(watcher_list, loop); + } + + uv__queue_move(&tmp_watcher_list.watchers, &queue); + while (!uv__queue_empty(&queue)) { + q = uv__queue_head(&queue); + uv__queue_remove(q); + handle = uv__queue_data(q, uv_fs_event_t, watchers); + tmp_path = handle->path; + handle->path = NULL; + err = uv_fs_event_start(handle, handle->cb, tmp_path, 0); + uv__free(tmp_path); + if (err) + return err; + } + + return 0; +} + + +static struct watcher_list* find_watcher(uv_loop_t* loop, int wd) { + struct watcher_list w; + w.wd = wd; + return RB_FIND(watcher_root, uv__inotify_watchers(loop), &w); +} + + +static void maybe_free_watcher_list(struct watcher_list* w, uv_loop_t* loop) { + /* if the watcher_list->watchers is being iterated over, we can't free it. */ + if ((!w->iterating) && uv__queue_empty(&w->watchers)) { + /* No watchers left for this path. Clean up. */ + RB_REMOVE(watcher_root, uv__inotify_watchers(loop), w); + inotify_rm_watch(loop->inotify_fd, w->wd); + uv__free(w); + } +} + + +static void uv__inotify_read(uv_loop_t* loop, + uv__io_t* dummy, + unsigned int events) { + const struct inotify_event* e; + struct watcher_list* w; + uv_fs_event_t* h; + struct uv__queue queue; + struct uv__queue* q; + const char* path; + ssize_t size; + const char *p; + /* needs to be large enough for sizeof(inotify_event) + strlen(path) */ + char buf[4096]; + + for (;;) { + do + size = read(loop->inotify_fd, buf, sizeof(buf)); + while (size == -1 && errno == EINTR); + + if (size == -1) { + assert(errno == EAGAIN || errno == EWOULDBLOCK); + break; + } + + assert(size > 0); /* pre-2.6.21 thing, size=0 == read buffer too small */ + + /* Now we have one or more inotify_event structs. */ + for (p = buf; p < buf + size; p += sizeof(*e) + e->len) { + e = (const struct inotify_event*) p; + + events = 0; + if (e->mask & (IN_ATTRIB|IN_MODIFY)) + events |= UV_CHANGE; + if (e->mask & ~(IN_ATTRIB|IN_MODIFY)) + events |= UV_RENAME; + + w = find_watcher(loop, e->wd); + if (w == NULL) + continue; /* Stale event, no watchers left. */ + + /* inotify does not return the filename when monitoring a single file + * for modifications. Repurpose the filename for API compatibility. + * I'm not convinced this is a good thing, maybe it should go. + */ + path = e->len ? (const char*) (e + 1) : uv__basename_r(w->path); + + /* We're about to iterate over the queue and call user's callbacks. + * What can go wrong? + * A callback could call uv_fs_event_stop() + * and the queue can change under our feet. + * So, we use uv__queue_move() trick to safely iterate over the queue. + * And we don't free the watcher_list until we're done iterating. + * + * First, + * tell uv_fs_event_stop() (that could be called from a user's callback) + * not to free watcher_list. + */ + w->iterating = 1; + uv__queue_move(&w->watchers, &queue); + while (!uv__queue_empty(&queue)) { + q = uv__queue_head(&queue); + h = uv__queue_data(q, uv_fs_event_t, watchers); + + uv__queue_remove(q); + uv__queue_insert_tail(&w->watchers, q); + + h->cb(h, path, events, 0); + } + /* done iterating, time to (maybe) free empty watcher_list */ + w->iterating = 0; + maybe_free_watcher_list(w, loop); + } + } +} + + +int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { + uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); + return 0; +} + + +int uv_fs_event_start(uv_fs_event_t* handle, + uv_fs_event_cb cb, + const char* path, + unsigned int flags) { + struct watcher_list* w; + uv_loop_t* loop; + size_t len; + int events; + int err; + int wd; + + if (uv__is_active(handle)) + return UV_EINVAL; + + loop = handle->loop; + + err = init_inotify(loop); + if (err) + return err; + + events = IN_ATTRIB + | IN_CREATE + | IN_MODIFY + | IN_DELETE + | IN_DELETE_SELF + | IN_MOVE_SELF + | IN_MOVED_FROM + | IN_MOVED_TO; + + wd = inotify_add_watch(loop->inotify_fd, path, events); + if (wd == -1) + return UV__ERR(errno); + + w = find_watcher(loop, wd); + if (w) + goto no_insert; + + len = strlen(path) + 1; + w = (watcher_list*)uv__malloc(sizeof(*w) + len); + if (w == NULL) + return UV_ENOMEM; + + w->wd = wd; + w->path = (char*)memcpy(w + 1, path, len); + uv__queue_init(&w->watchers); + w->iterating = 0; + RB_INSERT(watcher_root, uv__inotify_watchers(loop), w); + +no_insert: + uv__handle_start(handle); + uv__queue_insert_tail(&w->watchers, &handle->watchers); + handle->path = w->path; + handle->cb = cb; + handle->wd = wd; + + return 0; +} + + +int uv_fs_event_stop(uv_fs_event_t* handle) { + struct watcher_list* w; + + if (!uv__is_active(handle)) + return 0; + + w = find_watcher(handle->loop, handle->wd); + assert(w != NULL); + + handle->wd = -1; + handle->path = NULL; + uv__handle_stop(handle); + uv__queue_remove(&handle->watchers); + + maybe_free_watcher_list(w, handle->loop); + + return 0; +} + + +void uv__fs_event_close(uv_fs_event_t* handle) { + uv_fs_event_stop(handle); +} diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/loop-watcher.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/loop-watcher.cpp index b8c1c2a7102..2db8b515df7 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/loop-watcher.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/loop-watcher.cpp @@ -32,7 +32,7 @@ int uv_##name##_start(uv_##name##_t* handle, uv_##name##_cb cb) { \ if (uv__is_active(handle)) return 0; \ if (cb == NULL) return UV_EINVAL; \ - QUEUE_INSERT_HEAD(&handle->loop->name##_handles, &handle->queue); \ + uv__queue_insert_head(&handle->loop->name##_handles, &handle->queue); \ handle->name##_cb = cb; \ uv__handle_start(handle); \ return 0; \ @@ -40,21 +40,21 @@ \ int uv_##name##_stop(uv_##name##_t* handle) { \ if (!uv__is_active(handle)) return 0; \ - QUEUE_REMOVE(&handle->queue); \ + uv__queue_remove(&handle->queue); \ uv__handle_stop(handle); \ return 0; \ } \ \ void uv__run_##name(uv_loop_t* loop) { \ uv_##name##_t* h; \ - QUEUE queue; \ - QUEUE* q; \ - QUEUE_MOVE(&loop->name##_handles, &queue); \ - while (!QUEUE_EMPTY(&queue)) { \ - q = QUEUE_HEAD(&queue); \ - h = QUEUE_DATA(q, uv_##name##_t, queue); \ - QUEUE_REMOVE(q); \ - QUEUE_INSERT_TAIL(&loop->name##_handles, q); \ + struct uv__queue queue; \ + struct uv__queue* q; \ + uv__queue_move(&loop->name##_handles, &queue); \ + while (!uv__queue_empty(&queue)) { \ + q = uv__queue_head(&queue); \ + h = uv__queue_data(q, uv_##name##_t, queue); \ + uv__queue_remove(q); \ + uv__queue_insert_tail(&loop->name##_handles, q); \ h->name##_cb(h); \ } \ } \ diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/loop.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/loop.cpp index 2e819cdda71..3babe4d7019 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/loop.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/loop.cpp @@ -45,22 +45,25 @@ int uv_loop_init(uv_loop_t* loop) { err = uv_mutex_init(&lfields->loop_metrics.lock); if (err) goto fail_metrics_mutex_init; + memset(&lfields->loop_metrics.metrics, + 0, + sizeof(lfields->loop_metrics.metrics)); heap_init((struct heap*) &loop->timer_heap); - QUEUE_INIT(&loop->wq); - QUEUE_INIT(&loop->idle_handles); - QUEUE_INIT(&loop->async_handles); - QUEUE_INIT(&loop->check_handles); - QUEUE_INIT(&loop->prepare_handles); - QUEUE_INIT(&loop->handle_queue); + uv__queue_init(&loop->wq); + uv__queue_init(&loop->idle_handles); + uv__queue_init(&loop->async_handles); + uv__queue_init(&loop->check_handles); + uv__queue_init(&loop->prepare_handles); + uv__queue_init(&loop->handle_queue); loop->active_handles = 0; loop->active_reqs.count = 0; loop->nfds = 0; loop->watchers = NULL; loop->nwatchers = 0; - QUEUE_INIT(&loop->pending_queue); - QUEUE_INIT(&loop->watcher_queue); + uv__queue_init(&loop->pending_queue); + uv__queue_init(&loop->watcher_queue); loop->closing_handles = NULL; uv__update_time(loop); @@ -79,13 +82,10 @@ int uv_loop_init(uv_loop_t* loop) { goto fail_platform_init; uv__signal_global_once_init(); - err = uv_signal_init(loop, &loop->child_watcher); + err = uv__process_init(loop); if (err) goto fail_signal_init; - - uv__handle_unref(&loop->child_watcher); - loop->child_watcher.flags |= UV_HANDLE_INTERNAL; - QUEUE_INIT(&loop->process_handles); + uv__queue_init(&loop->process_handles); err = uv_rwlock_init(&loop->cloexec_lock); if (err) @@ -152,9 +152,9 @@ int uv_loop_fork(uv_loop_t* loop) { if (w == NULL) continue; - if (w->pevents != 0 && QUEUE_EMPTY(&w->watcher_queue)) { + if (w->pevents != 0 && uv__queue_empty(&w->watcher_queue)) { w->events = 0; /* Force re-registration in uv__io_poll. */ - QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue); + uv__queue_insert_tail(&loop->watcher_queue, &w->watcher_queue); } } @@ -180,7 +180,7 @@ void uv__loop_close(uv_loop_t* loop) { } uv_mutex_lock(&loop->wq_mutex); - assert(QUEUE_EMPTY(&loop->wq) && "thread pool work queue not empty!"); + assert(uv__queue_empty(&loop->wq) && "thread pool work queue not empty!"); assert(!uv__has_active_reqs(loop)); uv_mutex_unlock(&loop->wq_mutex); uv_mutex_destroy(&loop->wq_mutex); @@ -192,8 +192,8 @@ void uv__loop_close(uv_loop_t* loop) { uv_rwlock_destroy(&loop->cloexec_lock); #if 0 - assert(QUEUE_EMPTY(&loop->pending_queue)); - assert(QUEUE_EMPTY(&loop->watcher_queue)); + assert(uv__queue_empty(&loop->pending_queue)); + assert(uv__queue_empty(&loop->watcher_queue)); assert(loop->nfds == 0); #endif diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/netbsd.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/netbsd.cpp index b6886a1ce5a..4c6d5a24fe8 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/netbsd.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/netbsd.cpp @@ -103,7 +103,7 @@ uint64_t uv_get_free_memory(void) { int which[] = {CTL_VM, VM_UVMEXP}; if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) - return UV__ERR(errno); + return 0; return (uint64_t) info.free * sysconf(_SC_PAGESIZE); } @@ -120,7 +120,7 @@ uint64_t uv_get_total_memory(void) { size_t size = sizeof(info); if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) - return UV__ERR(errno); + return 0; return (uint64_t) info; } @@ -131,6 +131,11 @@ uint64_t uv_get_constrained_memory(void) { } +uint64_t uv_get_available_memory(void) { + return uv_get_free_memory(); +} + + int uv_resident_set_memory(size_t* rss) { kvm_t *kd = NULL; struct kinfo_proc2 *kinfo = NULL; diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/openbsd.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/openbsd.cpp index 62740f73498..2aa61e2ee33 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/openbsd.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/openbsd.cpp @@ -116,7 +116,7 @@ uint64_t uv_get_free_memory(void) { int which[] = {CTL_VM, VM_UVMEXP}; if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) - return UV__ERR(errno); + return 0; return (uint64_t) info.free * sysconf(_SC_PAGESIZE); } @@ -128,7 +128,7 @@ uint64_t uv_get_total_memory(void) { size_t size = sizeof(info); if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) - return UV__ERR(errno); + return 0; return (uint64_t) info; } @@ -139,6 +139,11 @@ uint64_t uv_get_constrained_memory(void) { } +uint64_t uv_get_available_memory(void) { + return uv_get_free_memory(); +} + + int uv_resident_set_memory(size_t* rss) { struct kinfo_proc kinfo; size_t page_size = getpagesize(); diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/pipe.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/pipe.cpp index c8ba31daf84..a60b1a0e442 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/pipe.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/pipe.cpp @@ -41,26 +41,60 @@ int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) { int uv_pipe_bind(uv_pipe_t* handle, const char* name) { + return uv_pipe_bind2(handle, name, strlen(name), 0); +} + + +int uv_pipe_bind2(uv_pipe_t* handle, + const char* name, + size_t namelen, + unsigned int flags) { struct sockaddr_un saddr; - const char* pipe_fname; + char* pipe_fname; int sockfd; int err; pipe_fname = NULL; + if (flags & ~UV_PIPE_NO_TRUNCATE) + return UV_EINVAL; + + if (name == NULL) + return UV_EINVAL; + + if (namelen == 0) + return UV_EINVAL; + +#ifndef __linux__ + /* Abstract socket namespace only works on Linux. */ + if (*name == '\0') + return UV_EINVAL; +#endif + + if (flags & UV_PIPE_NO_TRUNCATE) + if (namelen > sizeof(saddr.sun_path)) + return UV_EINVAL; + + /* Truncate long paths. Documented behavior. */ + if (namelen > sizeof(saddr.sun_path)) + namelen = sizeof(saddr.sun_path); + /* Already bound? */ if (uv__stream_fd(handle) >= 0) return UV_EINVAL; - if (uv__is_closing(handle)) { + + if (uv__is_closing(handle)) return UV_EINVAL; - } - /* Make a copy of the file name, it outlives this function's scope. */ - pipe_fname = uv__strdup(name); - if (pipe_fname == NULL) - return UV_ENOMEM; - /* We've got a copy, don't touch the original any more. */ - name = NULL; + /* Make a copy of the file path unless it is an abstract socket. + * We unlink the file later but abstract sockets disappear + * automatically since they're not real file system entities. + */ + if (*name != '\0') { + pipe_fname = uv__strdup(name); + if (pipe_fname == NULL) + return UV_ENOMEM; + } err = uv__socket(AF_UNIX, SOCK_STREAM, 0); if (err < 0) @@ -68,7 +102,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { sockfd = err; memset(&saddr, 0, sizeof saddr); - uv__strscpy(saddr.sun_path, pipe_fname, sizeof(saddr.sun_path)); + memcpy(&saddr.sun_path, name, namelen); saddr.sun_family = AF_UNIX; if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) { @@ -83,12 +117,12 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { /* Success. */ handle->flags |= UV_HANDLE_BOUND; - handle->pipe_fname = pipe_fname; /* Is a strdup'ed copy. */ + handle->pipe_fname = pipe_fname; /* NULL or a strdup'ed copy. */ handle->io_watcher.fd = sockfd; return 0; err_socket: - uv__free((void*)pipe_fname); + uv__free(pipe_fname); return err; } @@ -176,11 +210,44 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb) { + uv_pipe_connect2(req, handle, name, strlen(name), 0, cb); +} + + +int uv_pipe_connect2(uv_connect_t* req, + uv_pipe_t* handle, + const char* name, + size_t namelen, + unsigned int flags, + uv_connect_cb cb) { struct sockaddr_un saddr; int new_sock; int err; int r; + if (flags & ~UV_PIPE_NO_TRUNCATE) + return UV_EINVAL; + + if (name == NULL) + return UV_EINVAL; + + if (namelen == 0) + return UV_EINVAL; + +#ifndef __linux__ + /* Abstract socket namespace only works on Linux. */ + if (*name == '\0') + return UV_EINVAL; +#endif + + if (flags & UV_PIPE_NO_TRUNCATE) + if (namelen > sizeof(saddr.sun_path)) + return UV_EINVAL; + + /* Truncate long paths. Documented behavior. */ + if (namelen > sizeof(saddr.sun_path)) + namelen = sizeof(saddr.sun_path); + new_sock = (uv__stream_fd(handle) == -1); if (new_sock) { @@ -191,7 +258,7 @@ void uv_pipe_connect(uv_connect_t* req, } memset(&saddr, 0, sizeof saddr); - uv__strscpy(saddr.sun_path, name, sizeof(saddr.sun_path)); + memcpy(&saddr.sun_path, name, namelen); saddr.sun_family = AF_UNIX; do { @@ -230,12 +297,13 @@ void uv_pipe_connect(uv_connect_t* req, uv__req_init(handle->loop, req, UV_CONNECT); req->handle = (uv_stream_t*)handle; req->cb = cb; - QUEUE_INIT(&req->queue); + uv__queue_init(&req->queue); /* Force callback to run on next tick in case of error. */ if (err) uv__io_feed(handle->loop, &handle->io_watcher); + return 0; } @@ -357,7 +425,7 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) { } /* stat must be used as fstat has a bug on Darwin */ - if (stat(name_buffer, &pipe_stat) == -1) { + if (uv__stat(name_buffer, &pipe_stat) == -1) { uv__free(name_buffer); return -errno; } diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/poll.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/poll.cpp index 73647317575..c21722b2e8e 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/poll.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/poll.cpp @@ -125,7 +125,7 @@ int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) { UV_PRIORITIZED)) == 0); assert(!uv__is_closing(handle)); - watchers = handle->loop->watchers; + watchers = (void**)handle->loop->watchers; w = &handle->io_watcher; if (uv__fd_exists(handle->loop, w->fd)) diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/posix-hrtime.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/posix-hrtime.cpp index 323dfc20392..7b45c01a4d0 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/posix-hrtime.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/posix-hrtime.cpp @@ -23,13 +23,14 @@ #include "internal.h" #include +#include #include -#undef NANOSEC -#define NANOSEC ((uint64_t) 1e9) - 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); + struct timespec t; + + if (clock_gettime(CLOCK_MONOTONIC, &t)) + abort(); + + return t.tv_sec * (uint64_t) 1e9 + t.tv_nsec; } diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/posix-poll.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/posix-poll.cpp index 8da038d1da6..b71eee3f01a 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/posix-poll.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/posix-poll.cpp @@ -132,11 +132,12 @@ static void uv__pollfds_del(uv_loop_t* loop, int fd) { void uv__io_poll(uv_loop_t* loop, int timeout) { + uv__loop_internal_fields_t* lfields; sigset_t* pset; sigset_t set; uint64_t time_base; uint64_t time_diff; - QUEUE* q; + struct uv__queue* q; uv__io_t* w; size_t i; unsigned int nevents; @@ -148,17 +149,19 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { int reset_timeout; if (loop->nfds == 0) { - assert(QUEUE_EMPTY(&loop->watcher_queue)); + assert(uv__queue_empty(&loop->watcher_queue)); return; } + lfields = uv__get_internal_fields(loop); + /* Take queued watchers and add their fds to our poll fds array. */ - while (!QUEUE_EMPTY(&loop->watcher_queue)) { - q = QUEUE_HEAD(&loop->watcher_queue); - QUEUE_REMOVE(q); - QUEUE_INIT(q); + while (!uv__queue_empty(&loop->watcher_queue)) { + q = uv__queue_head(&loop->watcher_queue); + uv__queue_remove(q); + uv__queue_init(q); - w = QUEUE_DATA(q, uv__io_t, watcher_queue); + w = uv__queue_data(q, uv__io_t, watcher_queue); assert(w->pevents != 0); assert(w->fd >= 0); assert(w->fd < (int) loop->nwatchers); @@ -179,7 +182,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { assert(timeout >= -1); time_base = loop->time; - if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) { + if (lfields->flags & UV_METRICS_IDLE_TIME) { reset_timeout = 1; user_timeout = timeout; timeout = 0; @@ -198,6 +201,12 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { if (timeout != 0) uv__metrics_set_provider_entry_time(loop); + /* Store the current timeout in a location that's globally accessible so + * other locations like uv__work_done() can determine whether the queue + * of events in the callback were waiting when poll was called. + */ + lfields->current_timeout = timeout; + if (pset != NULL) if (pthread_sigmask(SIG_BLOCK, pset, NULL)) abort(); @@ -292,9 +301,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { } } + uv__metrics_inc_events(loop, nevents); if (reset_timeout != 0) { timeout = user_timeout; reset_timeout = 0; + uv__metrics_inc_events_waiting(loop, nevents); } if (have_signals != 0) { diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/process.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/process.cpp index 0916aa458d4..2d622c956de 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/process.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/process.cpp @@ -55,7 +55,7 @@ extern char **environ; #endif -#if defined(__linux__) || defined(__GLIBC__) +#if defined(__linux__) # include #endif @@ -79,8 +79,28 @@ static void uv__chld(uv_signal_t* handle, int signum) { assert(signum == SIGCHLD); uv__wait_children(handle->loop); } + + +int uv__process_init(uv_loop_t* loop) { + int err; + + err = uv_signal_init(loop, &loop->child_watcher); + if (err) + return err; + uv__handle_unref(&loop->child_watcher); + loop->child_watcher.flags |= UV_HANDLE_INTERNAL; + return 0; +} + + +#else +int uv__process_init(uv_loop_t* loop) { + memset(&loop->child_watcher, 0, sizeof(loop->child_watcher)); + return 0; +} #endif + void uv__wait_children(uv_loop_t* loop) { uv_process_t* process; int exit_status; @@ -88,23 +108,24 @@ void uv__wait_children(uv_loop_t* loop) { int status; int options; pid_t pid; - QUEUE pending; - QUEUE* q; - QUEUE* h; + struct uv__queue pending; + struct uv__queue* q; + struct uv__queue* h; - QUEUE_INIT(&pending); + uv__queue_init(&pending); h = &loop->process_handles; - q = QUEUE_HEAD(h); + q = uv__queue_head(h); while (q != h) { - process = QUEUE_DATA(q, uv_process_t, queue); - q = QUEUE_NEXT(q); + process = uv__queue_data(q, uv_process_t, queue); + q = uv__queue_next(q); #ifndef UV_USE_SIGCHLD if ((process->flags & UV_HANDLE_REAP) == 0) continue; options = 0; process->flags &= ~UV_HANDLE_REAP; + loop->nfds--; #else options = WNOHANG; #endif @@ -128,18 +149,18 @@ void uv__wait_children(uv_loop_t* loop) { assert(pid == process->pid); process->status = status; - QUEUE_REMOVE(&process->queue); - QUEUE_INSERT_TAIL(&pending, &process->queue); + uv__queue_remove(&process->queue); + uv__queue_insert_tail(&pending, &process->queue); } h = &pending; - q = QUEUE_HEAD(h); + q = uv__queue_head(h); while (q != h) { - process = QUEUE_DATA(q, uv_process_t, queue); - q = QUEUE_NEXT(q); + process = uv__queue_data(q, uv_process_t, queue); + q = uv__queue_next(q); - QUEUE_REMOVE(&process->queue); - QUEUE_INIT(&process->queue); + uv__queue_remove(&process->queue); + uv__queue_init(&process->queue); uv__handle_stop(process); if (process->exit_cb == NULL) @@ -155,13 +176,18 @@ void uv__wait_children(uv_loop_t* loop) { process->exit_cb(process, exit_status, term_signal); } - assert(QUEUE_EMPTY(&pending)); + assert(uv__queue_empty(&pending)); } /* * Used for initializing stdio streams like options.stdin_stream. Returns * zero on success. See also the cleanup section in uv_spawn(). */ +#if !(defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)) +/* 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. + */ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) { int mask; int fd; @@ -248,11 +274,6 @@ static void uv__write_errno(int error_fd) { } -#if !(defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)) -/* 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. - */ static void uv__process_child_init(const uv_process_options_t* options, int stdio_count, int (*pipes)[2], @@ -384,7 +405,6 @@ static void uv__process_child_init(const uv_process_options_t* options, uv__write_errno(error_fd); } -#endif #if defined(__APPLE__) @@ -665,7 +685,7 @@ static int uv__spawn_resolve_and_spawn(const uv_process_options_t* options, if (options->file == NULL) return ENOENT; - /* The environment for the child process is that of the parent unless overriden + /* The environment for the child process is that of the parent unless overridden * by options->env */ char** env = environ; if (options->env != NULL) @@ -931,6 +951,7 @@ static int uv__spawn_and_init_child( return err; } +#endif /* ISN'T TARGET_OS_TV || TARGET_OS_WATCH */ int uv_spawn(uv_loop_t* loop, uv_process_t* process, @@ -957,7 +978,7 @@ int uv_spawn(uv_loop_t* loop, UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS))); uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS); - QUEUE_INIT(&process->queue); + uv__queue_init(&process->queue); process->status = 0; stdio_count = options->stdio_count; @@ -1012,11 +1033,15 @@ int uv_spawn(uv_loop_t* loop, process->flags |= UV_HANDLE_REAP; loop->flags |= UV_LOOP_REAP_CHILDREN; } + /* This prevents uv__io_poll() from bailing out prematurely, being unaware + * that we added an event here for it to react to. We will decrement this + * again after the waitpid call succeeds. */ + loop->nfds++; #endif process->pid = pid; process->exit_cb = options->exit_cb; - QUEUE_INSERT_TAIL(&loop->process_handles, &process->queue); + uv__queue_insert_tail(&loop->process_handles, &process->queue); uv__handle_start(process); } @@ -1078,8 +1103,10 @@ int uv_kill(int pid, int signum) { void uv__process_close(uv_process_t* handle) { - QUEUE_REMOVE(&handle->queue); + uv__queue_remove(&handle->queue); uv__handle_stop(handle); - if (QUEUE_EMPTY(&handle->loop->process_handles)) +#ifdef UV_USE_SIGCHLD + if (uv__queue_empty(&handle->loop->process_handles)) uv_signal_stop(&handle->loop->child_watcher); +#endif } diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/pthread-fixes.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/pthread-fixes.cpp deleted file mode 100644 index 022d79c4e21..00000000000 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/pthread-fixes.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (c) 2013, Sony Mobile Communications AB - * Copyright (c) 2012, Google Inc. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/* Android versions < 4.1 have a broken pthread_sigmask. */ -#include "uv-common.h" - -#include -#include -#include - -int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset) { - static int workaround; - int err; - - if (uv__load_relaxed(&workaround)) { - return sigprocmask(how, set, oset); - } else { - err = pthread_sigmask(how, set, oset); - if (err) { - if (err == EINVAL && sigprocmask(how, set, oset) == 0) { - uv__store_relaxed(&workaround, 1); - return 0; - } else { - return -1; - } - } - } - - return 0; -} diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/random-devurandom.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/random-devurandom.cpp index 05e52a56a36..d6336f2c98c 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/random-devurandom.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/random-devurandom.cpp @@ -40,7 +40,7 @@ int uv__random_readpath(const char* path, void* buf, size_t buflen) { if (fd < 0) return fd; - if (fstat(fd, &s)) { + if (uv__fstat(fd, &s)) { uv__close(fd); return UV__ERR(errno); } diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/random-getrandom.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/random-getrandom.cpp index bcc94089bcb..054eccf1664 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/random-getrandom.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/random-getrandom.cpp @@ -24,8 +24,6 @@ #ifdef __linux__ -#include "linux-syscalls.h" - #define uv__random_getrandom_init() 0 #else /* !__linux__ */ diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/signal.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/signal.cpp index 1133c73a955..63aba5a60e0 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/signal.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/signal.cpp @@ -279,6 +279,8 @@ static int uv__signal_loop_once_init(uv_loop_t* loop) { int uv__signal_loop_fork(uv_loop_t* loop) { + if (loop->signal_pipefd[0] == -1) + return 0; uv__io_stop(loop, &loop->signal_io_watcher, POLLIN); uv__close(loop->signal_pipefd[0]); uv__close(loop->signal_pipefd[1]); @@ -289,16 +291,16 @@ int uv__signal_loop_fork(uv_loop_t* loop) { void uv__signal_loop_cleanup(uv_loop_t* loop) { - QUEUE* q; + struct uv__queue* q; /* Stop all the signal watchers that are still attached to this loop. This * ensures that the (shared) signal tree doesn't contain any invalid entries * entries, and that signal handlers are removed when appropriate. - * It's safe to use QUEUE_FOREACH here because the handles and the handle + * It's safe to use uv__queue_foreach here because the handles and the handle * queue are not modified by uv__signal_stop(). */ - QUEUE_FOREACH(q, &loop->handle_queue) { - uv_handle_t* handle = QUEUE_DATA(q, uv_handle_t, handle_queue); + uv__queue_foreach(q, &loop->handle_queue) { + uv_handle_t* handle = uv__queue_data(q, uv_handle_t, handle_queue); if (handle->type == UV_SIGNAL) uv__signal_stop((uv_signal_t*) handle); diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/spinlock.h b/wpinet/src/main/native/thirdparty/libuv/src/unix/spinlock.h deleted file mode 100644 index a20c83cc601..00000000000 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/spinlock.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (c) 2013, Ben Noordhuis - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef UV_SPINLOCK_H_ -#define UV_SPINLOCK_H_ - -#include "internal.h" /* ACCESS_ONCE, UV_UNUSED */ -#include "atomic-ops.h" - -#define UV_SPINLOCK_INITIALIZER { 0 } - -typedef struct { - int lock; -} uv_spinlock_t; - -UV_UNUSED(static void uv_spinlock_init(uv_spinlock_t* spinlock)); -UV_UNUSED(static void uv_spinlock_lock(uv_spinlock_t* spinlock)); -UV_UNUSED(static void uv_spinlock_unlock(uv_spinlock_t* spinlock)); -UV_UNUSED(static int uv_spinlock_trylock(uv_spinlock_t* spinlock)); - -UV_UNUSED(static void uv_spinlock_init(uv_spinlock_t* spinlock)) { - ACCESS_ONCE(int, spinlock->lock) = 0; -} - -UV_UNUSED(static void uv_spinlock_lock(uv_spinlock_t* spinlock)) { - while (!uv_spinlock_trylock(spinlock)) cpu_relax(); -} - -UV_UNUSED(static void uv_spinlock_unlock(uv_spinlock_t* spinlock)) { - ACCESS_ONCE(int, spinlock->lock) = 0; -} - -UV_UNUSED(static int uv_spinlock_trylock(uv_spinlock_t* spinlock)) { - /* TODO(bnoordhuis) Maybe change to a ticket lock to guarantee fair queueing. - * Not really critical until we have locks that are (frequently) contended - * for by several threads. - */ - return 0 == cmpxchgi(&spinlock->lock, 0, 1); -} - -#endif /* UV_SPINLOCK_H_ */ diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/stream.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/stream.cpp index c6cc50e7099..265ddade7ae 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/stream.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/stream.cpp @@ -60,6 +60,16 @@ struct uv__stream_select_s { }; #endif /* defined(__APPLE__) */ +union uv__cmsg { + struct cmsghdr hdr; + /* This cannot be larger because of the IBMi PASE limitation that + * the total size of control messages cannot exceed 256 bytes. + */ + char pad[256]; +}; + +STATIC_ASSERT(256 == sizeof(union uv__cmsg)); + static void uv__stream_connect(uv_stream_t*); static void uv__write(uv_stream_t* stream); static void uv__read(uv_stream_t* stream); @@ -84,8 +94,8 @@ void uv__stream_init(uv_loop_t* loop, stream->accepted_fd = -1; stream->queued_fds = NULL; stream->delayed_error = 0; - QUEUE_INIT(&stream->write_queue); - QUEUE_INIT(&stream->write_completed_queue); + uv__queue_init(&stream->write_queue); + uv__queue_init(&stream->write_completed_queue); stream->write_queue_size = 0; if (loop->emfile_fd == -1) { @@ -429,15 +439,15 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) { 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); + struct uv__queue* q; + while (!uv__queue_empty(&stream->write_queue)) { + q = uv__queue_head(&stream->write_queue); + uv__queue_remove(q); - req = QUEUE_DATA(q, uv_write_t, queue); + req = uv__queue_data(q, uv_write_t, queue); req->error = error; - QUEUE_INSERT_TAIL(&stream->write_completed_queue, &req->queue); + uv__queue_insert_tail(&stream->write_completed_queue, &req->queue); } } @@ -495,76 +505,34 @@ static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) { } -#if defined(UV_HAVE_KQUEUE) -# define UV_DEC_BACKLOG(w) w->rcount--; -#else -# define UV_DEC_BACKLOG(w) /* no-op */ -#endif /* defined(UV_HAVE_KQUEUE) */ - - void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { uv_stream_t* stream; int err; + int fd; stream = container_of(w, uv_stream_t, io_watcher); assert(events & POLLIN); assert(stream->accepted_fd == -1); assert(!(stream->flags & UV_HANDLE_CLOSING)); - uv__io_start(stream->loop, &stream->io_watcher, POLLIN); - - /* connection_cb can close the server socket while we're - * in the loop so check it on each iteration. - */ - while (uv__stream_fd(stream) != -1) { - assert(stream->accepted_fd == -1); - -#if defined(UV_HAVE_KQUEUE) - if (w->rcount <= 0) - return; -#endif /* defined(UV_HAVE_KQUEUE) */ - - err = uv__accept(uv__stream_fd(stream)); - if (err < 0) { - if (err == UV_EAGAIN || err == UV__ERR(EWOULDBLOCK)) - return; /* Not an error. */ + fd = uv__stream_fd(stream); + err = uv__accept(fd); - if (err == UV_ECONNABORTED) - continue; /* Ignore. Nothing we can do about that. */ + if (err == UV_EMFILE || err == UV_ENFILE) + err = uv__emfile_trick(loop, fd); /* Shed load. */ - if (err == UV_EMFILE || err == UV_ENFILE) { - err = uv__emfile_trick(loop, uv__stream_fd(stream)); - if (err == UV_EAGAIN || err == UV__ERR(EWOULDBLOCK)) - break; - } - - stream->connection_cb(stream, err); - continue; - } - - UV_DEC_BACKLOG(w) - stream->accepted_fd = err; - stream->connection_cb(stream, 0); + if (err < 0) + return; - if (stream->accepted_fd != -1) { - /* The user hasn't yet accepted called uv_accept() */ - uv__io_stop(loop, &stream->io_watcher, POLLIN); - return; - } + stream->accepted_fd = err; + stream->connection_cb(stream, 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); - } - } + if (stream->accepted_fd != -1) + /* The user hasn't yet accepted called uv_accept() */ + uv__io_stop(loop, &stream->io_watcher, POLLIN); } -#undef UV_DEC_BACKLOG - - int uv_accept(uv_stream_t* server, uv_stream_t* client) { int err; @@ -659,13 +627,13 @@ static void uv__drain(uv_stream_t* stream) { uv_shutdown_t* req; int err; - assert(QUEUE_EMPTY(&stream->write_queue)); + assert(uv__queue_empty(&stream->write_queue)); if (!(stream->flags & UV_HANDLE_CLOSING)) { uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT); uv__stream_osx_interrupt_select(stream); } - if (!(stream->flags & UV_HANDLE_SHUTTING)) + if (!uv__is_stream_shutting(stream)) return; req = stream->shutdown_req; @@ -674,7 +642,6 @@ static void uv__drain(uv_stream_t* stream) { if ((stream->flags & UV_HANDLE_CLOSING) || !(stream->flags & UV_HANDLE_SHUT)) { stream->shutdown_req = NULL; - stream->flags &= ~UV_HANDLE_SHUTTING; uv__req_unregister(stream->loop, req); err = 0; @@ -747,7 +714,7 @@ 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); + uv__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 @@ -764,7 +731,7 @@ static void uv__write_req_finish(uv_write_t* req) { /* 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__queue_insert_tail(&stream->write_completed_queue, &req->queue); uv__io_feed(stream->loop, &stream->io_watcher); } @@ -812,18 +779,14 @@ static int uv__try_write(uv_stream_t* stream, if (send_handle != NULL) { int fd_to_send; struct msghdr msg; - struct cmsghdr *cmsg; - union { - char data[64]; - struct cmsghdr alias; - } scratch; + union uv__cmsg cmsg; if (uv__is_closing(send_handle)) return UV_EBADF; fd_to_send = uv__handle_fd((uv_handle_t*) send_handle); - memset(&scratch, 0, sizeof(scratch)); + memset(&cmsg, 0, sizeof(cmsg)); assert(fd_to_send >= 0); @@ -833,20 +796,13 @@ static int uv__try_write(uv_stream_t* stream, msg.msg_iovlen = iovcnt; msg.msg_flags = 0; - msg.msg_control = &scratch.alias; + msg.msg_control = &cmsg.hdr; msg.msg_controllen = CMSG_SPACE(sizeof(fd_to_send)); - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(fd_to_send)); - - /* silence aliasing warning */ - { - void* pv = CMSG_DATA(cmsg); - int* pi = (int*)pv; - *pi = fd_to_send; - } + cmsg.hdr.cmsg_level = SOL_SOCKET; + cmsg.hdr.cmsg_type = SCM_RIGHTS; + cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(fd_to_send)); + memcpy(CMSG_DATA(&cmsg.hdr), &fd_to_send, sizeof(fd_to_send)); do n = sendmsg(uv__stream_fd(stream), &msg, 0); @@ -881,18 +837,25 @@ static int uv__try_write(uv_stream_t* stream, } static void uv__write(uv_stream_t* stream) { - QUEUE* q; + struct uv__queue* q; uv_write_t* req; ssize_t n; + int count; assert(uv__stream_fd(stream) >= 0); + /* Prevent loop starvation when the consumer of this stream read as fast as + * (or faster than) we can write it. This `count` mechanism does not need to + * change even if we switch to edge-triggered I/O. + */ + count = 32; + for (;;) { - if (QUEUE_EMPTY(&stream->write_queue)) + if (uv__queue_empty(&stream->write_queue)) return; - q = QUEUE_HEAD(&stream->write_queue); - req = QUEUE_DATA(q, uv_write_t, queue); + q = uv__queue_head(&stream->write_queue); + req = uv__queue_data(q, uv_write_t, queue); assert(req->handle == stream); n = uv__try_write(stream, @@ -905,10 +868,13 @@ static void uv__write(uv_stream_t* stream) { req->send_handle = NULL; if (uv__write_req_update(stream, req, n)) { uv__write_req_finish(req); - return; /* TODO(bnoordhuis) Start trying to write the next request. */ + if (count-- > 0) + continue; /* Start trying to write the next request. */ + + return; } } else if (n != UV_EAGAIN) - break; + goto error; /* If this is a blocking stream, try again. */ if (stream->flags & UV_HANDLE_BLOCKING_WRITES) @@ -923,6 +889,7 @@ static void uv__write(uv_stream_t* stream) { return; } +error: req->error = n; uv__write_req_finish(req); uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT); @@ -932,19 +899,19 @@ static void uv__write(uv_stream_t* stream) { static void uv__write_callbacks(uv_stream_t* stream) { uv_write_t* req; - QUEUE* q; - QUEUE pq; + struct uv__queue* q; + struct uv__queue pq; - if (QUEUE_EMPTY(&stream->write_completed_queue)) + if (uv__queue_empty(&stream->write_completed_queue)) return; - QUEUE_MOVE(&stream->write_completed_queue, &pq); + uv__queue_move(&stream->write_completed_queue, &pq); - while (!QUEUE_EMPTY(&pq)) { + while (!uv__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); + q = uv__queue_head(&pq); + req = uv__queue_data(q, uv_write_t, queue); + uv__queue_remove(q); uv__req_unregister(stream->loop, req); if (req->bufs != NULL) { @@ -1011,57 +978,38 @@ static int uv__stream_queue_fd(uv_stream_t* stream, int fd) { } -#if defined(__PASE__) -/* on IBMi PASE the control message length can not exceed 256. */ -# define UV__CMSG_FD_COUNT 60 -#else -# define UV__CMSG_FD_COUNT 64 -#endif -#define UV__CMSG_FD_SIZE (UV__CMSG_FD_COUNT * sizeof(int)) - - static int uv__stream_recv_cmsg(uv_stream_t* stream, struct msghdr* msg) { struct cmsghdr* cmsg; + int fd; + int err; + size_t i; + size_t count; for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) { - char* start; - char* end; - int err; - void* pv; - int* pi; - unsigned int i; - unsigned int count; - if (cmsg->cmsg_type != SCM_RIGHTS) { fprintf(stderr, "ignoring non-SCM_RIGHTS ancillary data: %d\n", cmsg->cmsg_type); continue; } - /* silence aliasing warning */ - pv = CMSG_DATA(cmsg); - pi = (int*)pv; - - /* Count available fds */ - start = (char*) cmsg; - end = (char*) cmsg + cmsg->cmsg_len; - count = 0; - while (start + CMSG_LEN(count * sizeof(*pi)) < end) - count++; - assert(start + CMSG_LEN(count * sizeof(*pi)) == end); + assert(cmsg->cmsg_len >= CMSG_LEN(0)); + count = cmsg->cmsg_len - CMSG_LEN(0); + assert(count % sizeof(fd) == 0); + count /= sizeof(fd); for (i = 0; i < count; i++) { + memcpy(&fd, (char*) CMSG_DATA(cmsg) + i * sizeof(fd), sizeof(fd)); /* Already has accepted fd, queue now */ if (stream->accepted_fd != -1) { - err = uv__stream_queue_fd(stream, pi[i]); + err = uv__stream_queue_fd(stream, fd); if (err != 0) { /* Close rest */ for (; i < count; i++) - uv__close(pi[i]); + uv__close(fd); return err; } } else { - stream->accepted_fd = pi[i]; + stream->accepted_fd = fd; } } } @@ -1070,17 +1018,11 @@ static int uv__stream_recv_cmsg(uv_stream_t* stream, struct msghdr* msg) { } -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wgnu-folding-constant" -# pragma clang diagnostic ignored "-Wvla-extension" -#endif - static void uv__read(uv_stream_t* stream) { uv_buf_t buf; ssize_t nread; struct msghdr msg; - char cmsg_space[CMSG_SPACE(UV__CMSG_FD_SIZE)]; + union uv__cmsg cmsg; int count; int err; int is_ipc; @@ -1126,8 +1068,8 @@ static void uv__read(uv_stream_t* stream) { msg.msg_name = NULL; msg.msg_namelen = 0; /* Set up to receive a descriptor even if one isn't in the message */ - msg.msg_controllen = sizeof(cmsg_space); - msg.msg_control = cmsg_space; + msg.msg_controllen = sizeof(cmsg); + msg.msg_control = &cmsg.hdr; do { nread = uv__recvmsg(uv__stream_fd(stream), &msg, 0); @@ -1211,14 +1153,6 @@ static void uv__read(uv_stream_t* stream) { } -#ifdef __clang__ -# pragma clang diagnostic pop -#endif - -#undef UV__CMSG_FD_COUNT -#undef UV__CMSG_FD_SIZE - - int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { assert(stream->type == UV_TCP || stream->type == UV_TTY || @@ -1226,7 +1160,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { if (!(stream->flags & UV_HANDLE_WRITABLE) || stream->flags & UV_HANDLE_SHUT || - stream->flags & UV_HANDLE_SHUTTING || + uv__is_stream_shutting(stream) || uv__is_closing(stream)) { return UV_ENOTCONN; } @@ -1239,10 +1173,9 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { req->handle = stream; req->cb = cb; stream->shutdown_req = req; - stream->flags |= UV_HANDLE_SHUTTING; stream->flags &= ~UV_HANDLE_WRITABLE; - if (QUEUE_EMPTY(&stream->write_queue)) + if (uv__queue_empty(&stream->write_queue)) uv__io_feed(stream->loop, &stream->io_watcher); return 0; @@ -1295,7 +1228,7 @@ static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { uv__write_callbacks(stream); /* Write queue drained. */ - if (QUEUE_EMPTY(&stream->write_queue)) + if (uv__queue_empty(&stream->write_queue)) uv__drain(stream); } } @@ -1338,7 +1271,7 @@ static void uv__stream_connect(uv_stream_t* stream) { stream->connect_req = NULL; uv__req_unregister(stream->loop, req); - if (error < 0 || QUEUE_EMPTY(&stream->write_queue)) { + if (error < 0 || uv__queue_empty(&stream->write_queue)) { uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT); } @@ -1420,7 +1353,7 @@ int uv_write2(uv_write_t* req, req->handle = stream; req->error = 0; req->send_handle = send_handle; - QUEUE_INIT(&req->queue); + uv__queue_init(&req->queue); req->bufs = req->bufsml; if (nbufs > ARRAY_SIZE(req->bufsml)) @@ -1435,7 +1368,7 @@ int uv_write2(uv_write_t* req, stream->write_queue_size += uv__count_bufs(bufs, nbufs); /* Append the request to write_queue. */ - QUEUE_INSERT_TAIL(&stream->write_queue, &req->queue); + uv__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 diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/tcp.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/tcp.cpp index 73fc657a86d..d6c848f4610 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/tcp.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/tcp.cpp @@ -28,16 +28,39 @@ #include -static int new_socket(uv_tcp_t* handle, int domain, unsigned long flags) { - struct sockaddr_storage saddr; +static int maybe_bind_socket(int fd) { + union uv__sockaddr s; socklen_t slen; + + slen = sizeof(s); + memset(&s, 0, sizeof(s)); + + if (getsockname(fd, &s.addr, &slen)) + return UV__ERR(errno); + + if (s.addr.sa_family == AF_INET) + if (s.in.sin_port != 0) + return 0; /* Already bound to a port. */ + + if (s.addr.sa_family == AF_INET6) + if (s.in6.sin6_port != 0) + return 0; /* Already bound to a port. */ + + /* Bind to an arbitrary port. */ + if (bind(fd, &s.addr, slen)) + return UV__ERR(errno); + + return 0; +} + + +static int new_socket(uv_tcp_t* handle, int domain, unsigned int flags) { int sockfd; int err; - err = uv__socket(domain, SOCK_STREAM, 0); - if (err < 0) - return err; - sockfd = err; + sockfd = uv__socket(domain, SOCK_STREAM, 0); + if (sockfd < 0) + return sockfd; err = uv__stream_open((uv_stream_t*) handle, sockfd, flags); if (err) { @@ -45,74 +68,44 @@ static int new_socket(uv_tcp_t* handle, int domain, unsigned long flags) { return err; } - if (flags & UV_HANDLE_BOUND) { - /* Bind this new socket to an arbitrary port */ - slen = sizeof(saddr); - memset(&saddr, 0, sizeof(saddr)); - if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen)) { - uv__close(sockfd); - return UV__ERR(errno); - } - - if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen)) { - uv__close(sockfd); - return UV__ERR(errno); - } - } + if (flags & UV_HANDLE_BOUND) + return maybe_bind_socket(sockfd); return 0; } -static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned long flags) { - struct sockaddr_storage saddr; - socklen_t slen; +static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned int flags) { + int sockfd; + int err; - if (domain == AF_UNSPEC) { - handle->flags |= flags; - return 0; - } + if (domain == AF_UNSPEC) + goto out; - if (uv__stream_fd(handle) != -1) { + sockfd = uv__stream_fd(handle); + if (sockfd == -1) + return new_socket(handle, domain, flags); - if (flags & UV_HANDLE_BOUND) { - - if (handle->flags & UV_HANDLE_BOUND) { - /* It is already bound to a port. */ - handle->flags |= flags; - return 0; - } - - /* Query to see if tcp socket is bound. */ - slen = sizeof(saddr); - memset(&saddr, 0, sizeof(saddr)); - if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen)) - return UV__ERR(errno); - - if ((saddr.ss_family == AF_INET6 && - ((struct sockaddr_in6*) &saddr)->sin6_port != 0) || - (saddr.ss_family == AF_INET && - ((struct sockaddr_in*) &saddr)->sin_port != 0)) { - /* Handle is already bound to a port. */ - handle->flags |= flags; - return 0; - } - - /* Bind to arbitrary port */ - if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen)) - return UV__ERR(errno); - } + if (!(flags & UV_HANDLE_BOUND)) + goto out; - handle->flags |= flags; - return 0; - } + if (handle->flags & UV_HANDLE_BOUND) + goto out; /* Already bound to a port. */ + + err = maybe_bind_socket(sockfd); + if (err) + return err; - return new_socket(handle, domain, flags); +out: + + handle->flags |= flags; + return 0; } int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* tcp, unsigned int flags) { int domain; + int err; /* Use the lower 8 bits for the domain */ domain = flags & 0xFF; @@ -129,9 +122,12 @@ int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* tcp, unsigned int flags) { */ if (domain != AF_UNSPEC) { - int err = maybe_new_socket(tcp, domain, 0); + err = new_socket(tcp, domain, 0); if (err) { - QUEUE_REMOVE(&tcp->handle_queue); + uv__queue_remove(&tcp->handle_queue); + if (tcp->io_watcher.fd != -1) + uv__close(tcp->io_watcher.fd); + tcp->io_watcher.fd = -1; return err; } } @@ -256,7 +252,7 @@ int uv__tcp_connect(uv_connect_t* req, uv__req_init(handle->loop, req, UV_CONNECT); req->cb = cb; req->handle = (uv_stream_t*) handle; - QUEUE_INIT(&req->queue); + uv__queue_init(&req->queue); handle->connect_req = req; uv__io_start(handle->loop, &handle->io_watcher, POLLOUT); @@ -317,7 +313,7 @@ int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) { struct linger l = { 1, 0 }; /* Disallow setting SO_LINGER to zero due to some platform inconsistencies */ - if (handle->flags & UV_HANDLE_SHUTTING) + if (uv__is_stream_shutting(handle)) return UV_EINVAL; fd = uv__stream_fd(handle); @@ -338,24 +334,12 @@ int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) { int uv__tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { - static int single_accept_cached = -1; - unsigned long flags; - int single_accept; + unsigned int flags; int err; if (tcp->delayed_error) return tcp->delayed_error; - single_accept = uv__load_relaxed(&single_accept_cached); - if (single_accept == -1) { - const char* val = getenv("UV_TCP_SINGLE_ACCEPT"); - single_accept = (val != NULL && atoi(val) != 0); /* Off by default. */ - uv__store_relaxed(&single_accept_cached, single_accept); - } - - if (single_accept) - tcp->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT; - flags = 0; #if defined(__MVS__) /* on zOS the listen call does not bind automatically @@ -460,10 +444,6 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) { int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) { - if (enable) - handle->flags &= ~UV_HANDLE_TCP_SINGLE_ACCEPT; - else - handle->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT; return 0; } diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/thread.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/thread.cpp index 392a0715a85..f8600947e3e 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/thread.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/thread.cpp @@ -41,125 +41,19 @@ #include /* gnu_get_libc_version() */ #endif -#undef NANOSEC -#define NANOSEC ((uint64_t) 1e9) - -#if defined(PTHREAD_BARRIER_SERIAL_THREAD) -STATIC_ASSERT(sizeof(uv_barrier_t) == sizeof(pthread_barrier_t)); +#if defined(__linux__) +# include +# define uv__cpu_set_t cpu_set_t +#elif defined(__FreeBSD__) +# include +# include +# include +# define uv__cpu_set_t cpuset_t #endif -/* Note: guard clauses should match uv_barrier_t's in include/uv/unix.h. */ -#if defined(_AIX) || \ - defined(__OpenBSD__) || \ - !defined(PTHREAD_BARRIER_SERIAL_THREAD) -int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { - struct _uv_barrier* b; - int rc; - - if (barrier == NULL || count == 0) - return UV_EINVAL; - - b = (_uv_barrier*)uv__malloc(sizeof(*b)); - if (b == NULL) - return UV_ENOMEM; - - b->in = 0; - b->out = 0; - b->threshold = count; - - rc = uv_mutex_init(&b->mutex); - if (rc != 0) - goto error2; - - rc = uv_cond_init(&b->cond); - if (rc != 0) - goto error; - - barrier->b = b; - return 0; - -error: - uv_mutex_destroy(&b->mutex); -error2: - uv__free(b); - return rc; -} - -int uv_barrier_wait(uv_barrier_t* barrier) { - struct _uv_barrier* b; - int last; - - if (barrier == NULL || barrier->b == NULL) - return UV_EINVAL; - - b = barrier->b; - /* Lock the mutex*/ - uv_mutex_lock(&b->mutex); - - if (++b->in == b->threshold) { - b->in = 0; - b->out = b->threshold; - uv_cond_signal(&b->cond); - } else { - do - uv_cond_wait(&b->cond, &b->mutex); - while (b->in != 0); - } - - last = (--b->out == 0); - uv_cond_signal(&b->cond); - - uv_mutex_unlock(&b->mutex); - return last; -} - -void uv_barrier_destroy(uv_barrier_t* barrier) { - struct _uv_barrier* b; - - b = barrier->b; - uv_mutex_lock(&b->mutex); - - assert(b->in == 0); - while (b->out != 0) - uv_cond_wait(&b->cond, &b->mutex); - - if (b->in != 0) - abort(); - - uv_mutex_unlock(&b->mutex); - uv_mutex_destroy(&b->mutex); - uv_cond_destroy(&b->cond); - - uv__free(barrier->b); - barrier->b = NULL; -} - -#else - -int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { - return UV__ERR(pthread_barrier_init(barrier, NULL, count)); -} - - -int uv_barrier_wait(uv_barrier_t* barrier) { - int rc; - - rc = pthread_barrier_wait(barrier); - if (rc != 0) - if (rc != PTHREAD_BARRIER_SERIAL_THREAD) - abort(); - - return rc == PTHREAD_BARRIER_SERIAL_THREAD; -} - - -void uv_barrier_destroy(uv_barrier_t* barrier) { - if (pthread_barrier_destroy(barrier)) - abort(); -} - -#endif +#undef NANOSEC +#define NANOSEC ((uint64_t) 1e9) /* Musl's PTHREAD_STACK_MIN is 2 KB on all architectures, which is * too small to safely receive signals on. @@ -276,6 +170,106 @@ int uv_thread_create_ex(uv_thread_t* tid, return UV__ERR(err); } +#if UV__CPU_AFFINITY_SUPPORTED + +int uv_thread_setaffinity(uv_thread_t* tid, + char* cpumask, + char* oldmask, + size_t mask_size) { + int i; + int r; + uv__cpu_set_t cpuset; + int cpumasksize; + + cpumasksize = uv_cpumask_size(); + if (cpumasksize < 0) + return cpumasksize; + if (mask_size < (size_t)cpumasksize) + return UV_EINVAL; + + if (oldmask != NULL) { + r = uv_thread_getaffinity(tid, oldmask, mask_size); + if (r < 0) + return r; + } + + CPU_ZERO(&cpuset); + for (i = 0; i < cpumasksize; i++) + if (cpumask[i]) + CPU_SET(i, &cpuset); + +#if defined(__ANDROID__) + if (sched_setaffinity(pthread_gettid_np(*tid), sizeof(cpuset), &cpuset)) + r = errno; + else + r = 0; +#else + r = pthread_setaffinity_np(*tid, sizeof(cpuset), &cpuset); +#endif + + return UV__ERR(r); +} + + +int uv_thread_getaffinity(uv_thread_t* tid, + char* cpumask, + size_t mask_size) { + int r; + int i; + uv__cpu_set_t cpuset; + int cpumasksize; + + cpumasksize = uv_cpumask_size(); + if (cpumasksize < 0) + return cpumasksize; + if (mask_size < (size_t)cpumasksize) + return UV_EINVAL; + + CPU_ZERO(&cpuset); +#if defined(__ANDROID__) + if (sched_getaffinity(pthread_gettid_np(*tid), sizeof(cpuset), &cpuset)) + r = errno; + else + r = 0; +#else + r = pthread_getaffinity_np(*tid, sizeof(cpuset), &cpuset); +#endif + if (r) + return UV__ERR(r); + for (i = 0; i < cpumasksize; i++) + cpumask[i] = !!CPU_ISSET(i, &cpuset); + + return 0; +} +#else +int uv_thread_setaffinity(uv_thread_t* tid, + char* cpumask, + char* oldmask, + size_t mask_size) { + return UV_ENOTSUP; +} + + +int uv_thread_getaffinity(uv_thread_t* tid, + char* cpumask, + size_t mask_size) { + return UV_ENOTSUP; +} +#endif /* defined(__linux__) || defined(UV_BSD_H) */ + +int uv_thread_getcpu(void) { +#if UV__CPU_AFFINITY_SUPPORTED + int cpu; + + cpu = sched_getcpu(); + if (cpu < 0) + return UV__ERR(errno); + + return cpu; +#else + return UV_ENOTSUP; +#endif +} uv_thread_t uv_thread_self(void) { return pthread_self(); @@ -577,7 +571,7 @@ static void uv__custom_sem_post(uv_sem_t* sem_) { uv_mutex_lock(&sem->mutex); sem->value++; if (sem->value == 1) - uv_cond_signal(&sem->cond); + uv_cond_signal(&sem->cond); /* Release one to replace us. */ uv_mutex_unlock(&sem->mutex); } diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/tty.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/tty.cpp index ed81e26a8dc..1304c6d8685 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/tty.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/tty.cpp @@ -21,7 +21,6 @@ #include "uv.h" #include "internal.h" -#include "spinlock.h" #include #include @@ -30,6 +29,8 @@ #include #include +#include + #if defined(__MVS__) && !defined(IMAXBEL) #define IMAXBEL 0 #endif @@ -64,7 +65,7 @@ static int isreallyatty(int file) { static int orig_termios_fd = -1; static struct termios orig_termios; -static uv_spinlock_t termios_spinlock = UV_SPINLOCK_INITIALIZER; +static std::atomic termios_spinlock; int uv__tcsetattr(int fd, int how, const struct termios *term) { int rc; @@ -81,7 +82,7 @@ int uv__tcsetattr(int fd, int how, const struct termios *term) { static int uv__tty_is_peripheral(const int fd) { int result; -#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#if defined(__linux__) || defined(__FreeBSD__) int dummy; result = ioctl(fd, TIOCGPTN, &dummy) != 0; @@ -114,7 +115,7 @@ static int uv__tty_is_peripheral(const int fd) { } /* Lookup stat structure behind the file descriptor. */ - if (fstat(fd, &sb) != 0) + if (uv__fstat(fd, &sb) != 0) abort(); /* Assert character device. */ @@ -223,7 +224,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int unused) { int rc = r; if (newfd != -1) uv__close(newfd); - QUEUE_REMOVE(&tty->handle_queue); + uv__queue_remove(&tty->handle_queue); do r = fcntl(fd, F_SETFL, saved_flags); while (r == -1 && errno == EINTR); @@ -281,6 +282,7 @@ static void uv__tty_make_raw(struct termios* tio) { int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { struct termios tmp; + int expected; int fd; int rc; @@ -297,12 +299,16 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { return UV__ERR(errno); /* This is used for uv_tty_reset_mode() */ - uv_spinlock_lock(&termios_spinlock); + do + expected = 0; + while (!atomic_compare_exchange_strong(&termios_spinlock, &expected, 1)); + if (orig_termios_fd == -1) { orig_termios = tty->orig_termios; orig_termios_fd = fd; } - uv_spinlock_unlock(&termios_spinlock); + + atomic_store(&termios_spinlock, 0); } tmp = tty->orig_termios; @@ -361,7 +367,7 @@ uv_handle_type uv_guess_handle(uv_file file) { if (isatty(file)) return UV_TTY; - if (fstat(file, &s)) { + if (uv__fstat(file, &s)) { #if defined(__PASE__) /* On ibmi receiving RST from TCP instead of FIN immediately puts fd into * an error state. fstat will return EINVAL, getsockname will also return @@ -446,14 +452,15 @@ int uv_tty_reset_mode(void) { int err; saved_errno = errno; - if (!uv_spinlock_trylock(&termios_spinlock)) + + if (atomic_exchange(&termios_spinlock, 1)) return UV_EBUSY; /* In uv_tty_set_mode(). */ err = 0; if (orig_termios_fd != -1) err = uv__tcsetattr(orig_termios_fd, TCSANOW, &orig_termios); - uv_spinlock_unlock(&termios_spinlock); + atomic_store(&termios_spinlock, 0); errno = saved_errno; return err; diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/udp.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/udp.cpp index a130aeaa595..cbee16b22a3 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/unix/udp.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/udp.cpp @@ -40,12 +40,6 @@ # define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP #endif -union uv__sockaddr { - struct sockaddr_in6 in6; - struct sockaddr_in in; - struct sockaddr addr; -}; - static void uv__udp_run_completed(uv_udp_t* handle); static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents); static void uv__udp_recvmsg(uv_udp_t* handle); @@ -54,36 +48,6 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, int domain, unsigned int flags); -#if HAVE_MMSG - -#define UV__MMSG_MAXWIDTH 20 - -static int uv__udp_recvmmsg(uv_udp_t* handle, uv_buf_t* buf); -static void uv__udp_sendmmsg(uv_udp_t* handle); - -static int uv__recvmmsg_avail; -static int uv__sendmmsg_avail; -static uv_once_t once = UV_ONCE_INIT; - -static void uv__udp_mmsg_init(void) { - int ret; - int s; - s = uv__socket(AF_INET, SOCK_DGRAM, 0); - if (s < 0) - return; - ret = uv__sendmmsg(s, NULL, 0); - if (ret == 0 || errno != ENOSYS) { - uv__sendmmsg_avail = 1; - uv__recvmmsg_avail = 1; - } else { - ret = uv__recvmmsg(s, NULL, 0); - if (ret == 0 || errno != ENOSYS) - uv__recvmmsg_avail = 1; - } - uv__close(s); -} - -#endif void uv__udp_close(uv_udp_t* handle) { uv__io_close(handle->loop, &handle->io_watcher); @@ -98,18 +62,18 @@ void uv__udp_close(uv_udp_t* handle) { void uv__udp_finish_close(uv_udp_t* handle) { uv_udp_send_t* req; - QUEUE* q; + struct uv__queue* q; assert(!uv__io_active(&handle->io_watcher, POLLIN | POLLOUT)); assert(handle->io_watcher.fd == -1); - while (!QUEUE_EMPTY(&handle->write_queue)) { - q = QUEUE_HEAD(&handle->write_queue); - QUEUE_REMOVE(q); + while (!uv__queue_empty(&handle->write_queue)) { + q = uv__queue_head(&handle->write_queue); + uv__queue_remove(q); - req = QUEUE_DATA(q, uv_udp_send_t, queue); + req = uv__queue_data(q, uv_udp_send_t, queue); req->status = UV_ECANCELED; - QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue); + uv__queue_insert_tail(&handle->write_completed_queue, &req->queue); } uv__udp_run_completed(handle); @@ -126,16 +90,16 @@ void uv__udp_finish_close(uv_udp_t* handle) { static void uv__udp_run_completed(uv_udp_t* handle) { uv_udp_send_t* req; - QUEUE* q; + struct uv__queue* q; assert(!(handle->flags & UV_HANDLE_UDP_PROCESSING)); handle->flags |= UV_HANDLE_UDP_PROCESSING; - while (!QUEUE_EMPTY(&handle->write_completed_queue)) { - q = QUEUE_HEAD(&handle->write_completed_queue); - QUEUE_REMOVE(q); + while (!uv__queue_empty(&handle->write_completed_queue)) { + q = uv__queue_head(&handle->write_completed_queue); + uv__queue_remove(q); - req = QUEUE_DATA(q, uv_udp_send_t, queue); + req = uv__queue_data(q, uv_udp_send_t, queue); uv__req_unregister(handle->loop, req); handle->send_queue_size -= uv__count_bufs(req->bufs, req->nbufs); @@ -157,7 +121,7 @@ static void uv__udp_run_completed(uv_udp_t* handle) { req->send_cb(req, req->status); } - if (QUEUE_EMPTY(&handle->write_queue)) { + if (uv__queue_empty(&handle->write_queue)) { /* Pending queue and completion queue empty, stop watcher. */ uv__io_stop(handle->loop, &handle->io_watcher, POLLOUT); if (!uv__io_active(&handle->io_watcher, POLLIN)) @@ -183,11 +147,11 @@ static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents) { } } -#if HAVE_MMSG static int uv__udp_recvmmsg(uv_udp_t* handle, uv_buf_t* buf) { - struct sockaddr_in6 peers[UV__MMSG_MAXWIDTH]; - struct iovec iov[UV__MMSG_MAXWIDTH]; - struct uv__mmsghdr msgs[UV__MMSG_MAXWIDTH]; +#if defined(__linux__) || defined(__FreeBSD__) + struct sockaddr_in6 peers[20]; + struct iovec iov[ARRAY_SIZE(peers)]; + struct mmsghdr msgs[ARRAY_SIZE(peers)]; ssize_t nread; uv_buf_t chunk_buf; size_t chunks; @@ -212,7 +176,7 @@ static int uv__udp_recvmmsg(uv_udp_t* handle, uv_buf_t* buf) { } do - nread = uv__recvmmsg(handle->io_watcher.fd, msgs, chunks); + nread = recvmmsg(handle->io_watcher.fd, msgs, chunks, 0, NULL); while (nread == -1 && errno == EINTR); if (nread < 1) { @@ -240,8 +204,10 @@ static int uv__udp_recvmmsg(uv_udp_t* handle, uv_buf_t* buf) { handle->recv_cb(handle, 0, buf, NULL, UV_UDP_MMSG_FREE); } return nread; +#else /* __linux__ || ____FreeBSD__ */ + return UV_ENOSYS; +#endif /* __linux__ || ____FreeBSD__ */ } -#endif static void uv__udp_recvmsg(uv_udp_t* handle) { struct sockaddr_storage peer; @@ -268,14 +234,12 @@ static void uv__udp_recvmsg(uv_udp_t* handle) { } assert(buf.base != NULL); -#if HAVE_MMSG if (uv_udp_using_recvmmsg(handle)) { nread = uv__udp_recvmmsg(handle, &buf); if (nread > 0) count -= nread; continue; } -#endif memset(&h, 0, sizeof(h)); memset(&peer, 0, sizeof(peer)); @@ -311,25 +275,25 @@ static void uv__udp_recvmsg(uv_udp_t* handle) { && handle->recv_cb != NULL); } -#if HAVE_MMSG -static void uv__udp_sendmmsg(uv_udp_t* handle) { +static void uv__udp_sendmsg(uv_udp_t* handle) { +#if defined(__linux__) || defined(__FreeBSD__) uv_udp_send_t* req; - struct uv__mmsghdr h[UV__MMSG_MAXWIDTH]; - struct uv__mmsghdr *p; - QUEUE* q; + struct mmsghdr h[20]; + struct mmsghdr* p; + struct uv__queue* q; ssize_t npkts; size_t pkts; size_t i; - if (QUEUE_EMPTY(&handle->write_queue)) + if (uv__queue_empty(&handle->write_queue)) return; write_queue_drain: - for (pkts = 0, q = QUEUE_HEAD(&handle->write_queue); - pkts < UV__MMSG_MAXWIDTH && q != &handle->write_queue; - ++pkts, q = QUEUE_HEAD(q)) { + for (pkts = 0, q = uv__queue_head(&handle->write_queue); + pkts < ARRAY_SIZE(h) && q != &handle->write_queue; + ++pkts, q = uv__queue_head(q)) { assert(q != NULL); - req = QUEUE_DATA(q, uv_udp_send_t, queue); + req = uv__queue_data(q, uv_udp_send_t, queue); assert(req != NULL); p = &h[pkts]; @@ -355,22 +319,22 @@ static void uv__udp_sendmmsg(uv_udp_t* handle) { } do - npkts = uv__sendmmsg(handle->io_watcher.fd, h, pkts); + npkts = sendmmsg(handle->io_watcher.fd, h, pkts, 0); while (npkts == -1 && errno == EINTR); if (npkts < 1) { if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS) return; - for (i = 0, q = QUEUE_HEAD(&handle->write_queue); + for (i = 0, q = uv__queue_head(&handle->write_queue); i < pkts && q != &handle->write_queue; - ++i, q = QUEUE_HEAD(&handle->write_queue)) { + ++i, q = uv__queue_head(&handle->write_queue)) { assert(q != NULL); - req = QUEUE_DATA(q, uv_udp_send_t, queue); + req = uv__queue_data(q, uv_udp_send_t, queue); assert(req != NULL); req->status = UV__ERR(errno); - QUEUE_REMOVE(&req->queue); - QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue); + uv__queue_remove(&req->queue); + uv__queue_insert_tail(&handle->write_completed_queue, &req->queue); } uv__io_feed(handle->loop, &handle->io_watcher); return; @@ -379,11 +343,11 @@ static void uv__udp_sendmmsg(uv_udp_t* handle) { /* Safety: npkts known to be >0 below. Hence cast from ssize_t * to size_t safe. */ - for (i = 0, q = QUEUE_HEAD(&handle->write_queue); + for (i = 0, q = uv__queue_head(&handle->write_queue); i < (size_t)npkts && q != &handle->write_queue; - ++i, q = QUEUE_HEAD(&handle->write_queue)) { + ++i, q = uv__queue_head(&handle->write_queue)) { assert(q != NULL); - req = QUEUE_DATA(q, uv_udp_send_t, queue); + req = uv__queue_data(q, uv_udp_send_t, queue); assert(req != NULL); req->status = req->bufs[0].len; @@ -393,37 +357,25 @@ static void uv__udp_sendmmsg(uv_udp_t* handle) { * why we don't handle partial writes. Just pop the request * off the write queue and onto the completed queue, done. */ - QUEUE_REMOVE(&req->queue); - QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue); + uv__queue_remove(&req->queue); + uv__queue_insert_tail(&handle->write_completed_queue, &req->queue); } /* couldn't batch everything, continue sending (jump to avoid stack growth) */ - if (!QUEUE_EMPTY(&handle->write_queue)) + if (!uv__queue_empty(&handle->write_queue)) goto write_queue_drain; uv__io_feed(handle->loop, &handle->io_watcher); - return; -} -#endif - -static void uv__udp_sendmsg(uv_udp_t* handle) { +#else /* __linux__ || ____FreeBSD__ */ uv_udp_send_t* req; struct msghdr h; - QUEUE* q; + struct uv__queue* q; ssize_t size; -#if HAVE_MMSG - uv_once(&once, uv__udp_mmsg_init); - if (uv__sendmmsg_avail) { - uv__udp_sendmmsg(handle); - return; - } -#endif - - while (!QUEUE_EMPTY(&handle->write_queue)) { - q = QUEUE_HEAD(&handle->write_queue); + while (!uv__queue_empty(&handle->write_queue)) { + q = uv__queue_head(&handle->write_queue); assert(q != NULL); - req = QUEUE_DATA(q, uv_udp_send_t, queue); + req = uv__queue_data(q, uv_udp_send_t, queue); assert(req != NULL); memset(&h, 0, sizeof h); @@ -462,10 +414,11 @@ static void uv__udp_sendmsg(uv_udp_t* handle) { * why we don't handle partial writes. Just pop the request * off the write queue and onto the completed queue, done. */ - QUEUE_REMOVE(&req->queue); - QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue); + uv__queue_remove(&req->queue); + uv__queue_insert_tail(&handle->write_completed_queue, &req->queue); uv__io_feed(handle->loop, &handle->io_watcher); } +#endif /* __linux__ || ____FreeBSD__ */ } /* On the BSDs, SO_REUSEPORT implies SO_REUSEADDR but with some additional @@ -495,7 +448,8 @@ static int uv__set_reuse(int fd) { if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes))) return UV__ERR(errno); } -#elif defined(SO_REUSEPORT) && !defined(__linux__) && !defined(__GNU__) +#elif defined(SO_REUSEPORT) && !defined(__linux__) && !defined(__GNU__) && \ + !defined(__sun__) if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes))) return UV__ERR(errno); #else @@ -775,7 +729,7 @@ int uv__udp_send(uv_udp_send_t* req, memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0])); handle->send_queue_size += uv__count_bufs(req->bufs, req->nbufs); handle->send_queue_count++; - QUEUE_INSERT_TAIL(&handle->write_queue, &req->queue); + uv__queue_insert_tail(&handle->write_queue, &req->queue); uv__handle_start(handle); if (empty_queue && !(handle->flags & UV_HANDLE_UDP_PROCESSING)) { @@ -785,7 +739,7 @@ int uv__udp_send(uv_udp_send_t* req, * away. In such cases the `io_watcher` has to be queued for asynchronous * write. */ - if (!QUEUE_EMPTY(&handle->write_queue)) + if (!uv__queue_empty(&handle->write_queue)) uv__io_start(handle->loop, &handle->io_watcher, POLLOUT); } else { uv__io_start(handle->loop, &handle->io_watcher, POLLOUT); @@ -1053,19 +1007,17 @@ int uv__udp_init_ex(uv_loop_t* loop, handle->send_queue_size = 0; handle->send_queue_count = 0; uv__io_init(&handle->io_watcher, uv__udp_io, fd); - QUEUE_INIT(&handle->write_queue); - QUEUE_INIT(&handle->write_completed_queue); + uv__queue_init(&handle->write_queue); + uv__queue_init(&handle->write_completed_queue); return 0; } int uv_udp_using_recvmmsg(const uv_udp_t* handle) { -#if HAVE_MMSG - if (handle->flags & UV_HANDLE_UDP_RECVMMSG) { - uv_once(&once, uv__udp_mmsg_init); - return uv__recvmmsg_avail; - } +#if defined(__linux__) || defined(__FreeBSD__) + if (handle->flags & UV_HANDLE_UDP_RECVMMSG) + return 1; #endif return 0; } diff --git a/wpinet/src/main/native/thirdparty/libuv/src/uv-common.cpp b/wpinet/src/main/native/thirdparty/libuv/src/uv-common.cpp index c9a32c03367..5c6d8415540 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/uv-common.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/uv-common.cpp @@ -128,6 +128,39 @@ int uv_replace_allocator(uv_malloc_func malloc_func, return 0; } + +void uv_os_free_passwd(uv_passwd_t* pwd) { + if (pwd == NULL) + return; + + /* On unix, the memory for name, shell, and homedir are allocated in a single + * uv__malloc() call. The base of the pointer is stored in pwd->username, so + * that is the field that needs to be freed. + */ + uv__free(pwd->username); +#ifdef _WIN32 + uv__free(pwd->homedir); +#endif + pwd->username = NULL; + pwd->shell = NULL; + pwd->homedir = NULL; +} + + +void uv_os_free_group(uv_group_t *grp) { + if (grp == NULL) + return; + + /* The memory for is allocated in a single uv__malloc() call. The base of the + * pointer is stored in grp->members, so that is the only field that needs to + * be freed. + */ + uv__free(grp->members); + grp->members = NULL; + grp->groupname = NULL; +} + + #define XX(uc, lc) case UV_##uc: return sizeof(uv_##lc##_t); size_t uv_handle_size(uv_handle_type type) { @@ -500,17 +533,17 @@ int uv_udp_recv_stop(uv_udp_t* handle) { void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) { - QUEUE queue; - QUEUE* q; + struct uv__queue queue; + struct uv__queue* q; uv_handle_t* h; - QUEUE_MOVE(&loop->handle_queue, &queue); - while (!QUEUE_EMPTY(&queue)) { - q = QUEUE_HEAD(&queue); - h = QUEUE_DATA(q, uv_handle_t, handle_queue); + uv__queue_move(&loop->handle_queue, &queue); + while (!uv__queue_empty(&queue)) { + q = uv__queue_head(&queue); + h = uv__queue_data(q, uv_handle_t, handle_queue); - QUEUE_REMOVE(q); - QUEUE_INSERT_TAIL(&loop->handle_queue, q); + uv__queue_remove(q); + uv__queue_insert_tail(&loop->handle_queue, q); if (h->flags & UV_HANDLE_INTERNAL) continue; walk_cb(h, arg); @@ -520,14 +553,14 @@ void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) { static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) { const char* type; - QUEUE* q; + struct uv__queue* q; uv_handle_t* h; if (loop == NULL) loop = uv_default_loop(); - QUEUE_FOREACH(q, &loop->handle_queue) { - h = QUEUE_DATA(q, uv_handle_t, handle_queue); + uv__queue_foreach(q, &loop->handle_queue) { + h = uv__queue_data(q, uv_handle_t, handle_queue); if (only_active && !uv__is_active(h)) continue; @@ -650,14 +683,22 @@ static unsigned int* uv__get_nbufs(uv_fs_t* req) { void uv__fs_scandir_cleanup(uv_fs_t* req) { uv__dirent_t** dents; + unsigned int* nbufs; + unsigned int i; + unsigned int n; - unsigned int* nbufs = uv__get_nbufs(req); + if (req->result >= 0) { + dents = (uv__dirent_t**)(req->ptr); + nbufs = uv__get_nbufs(req); - dents = (uv__dirent_t**)(req->ptr); - if (*nbufs > 0 && *nbufs != (unsigned int) req->result) - (*nbufs)--; - for (; *nbufs < (unsigned int) req->result; (*nbufs)++) - uv__fs_scandir_free(dents[*nbufs]); + i = 0; + if (*nbufs > 0) + i = *nbufs - 1; + + n = (unsigned int) req->result; + for (; i < n; i++) + uv__fs_scandir_free(dents[i]); + } uv__fs_scandir_free(req->ptr); req->ptr = NULL; @@ -814,7 +855,7 @@ uv_loop_t* uv_loop_new(void) { int uv_loop_close(uv_loop_t* loop) { - QUEUE* q; + struct uv__queue* q; uv_handle_t* h; #ifndef NDEBUG void* saved_data; @@ -823,8 +864,8 @@ int uv_loop_close(uv_loop_t* loop) { if (uv__has_active_reqs(loop)) return UV_EBUSY; - QUEUE_FOREACH(q, &loop->handle_queue) { - h = QUEUE_DATA(q, uv_handle_t, handle_queue); + uv__queue_foreach(q, &loop->handle_queue) { + h = uv__queue_data(q, uv_handle_t, handle_queue); if (!(h->flags & UV_HANDLE_INTERNAL)) return UV_EBUSY; } @@ -888,12 +929,17 @@ void uv_os_free_environ(uv_env_item_t* envitems, int count) { void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { +#ifdef __linux__ + (void) &count; + uv__free(cpu_infos); +#else int i; for (i = 0; i < count; i++) uv__free(cpu_infos[i].model); uv__free(cpu_infos); +#endif /* __linux__ */ } @@ -905,9 +951,9 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { __attribute__((destructor)) #endif void uv_library_shutdown(void) { - static int was_shutdown; + static std::atomic was_shutdown; - if (uv__load_relaxed(&was_shutdown)) + if (uv__exchange_int_relaxed(&was_shutdown, 1)) return; uv__process_title_cleanup(); @@ -918,7 +964,6 @@ void uv_library_shutdown(void) { #else uv__threadpool_cleanup(); #endif - uv__store_relaxed(&was_shutdown, 1); } @@ -964,6 +1009,15 @@ void uv__metrics_set_provider_entry_time(uv_loop_t* loop) { } +int uv_metrics_info(uv_loop_t* loop, uv_metrics_t* metrics) { + memcpy(metrics, + &uv__get_loop_metrics(loop)->metrics, + sizeof(*metrics)); + + return 0; +} + + uint64_t uv_metrics_idle_time(uv_loop_t* loop) { uv__loop_metrics_t* loop_metrics; uint64_t entry_time; diff --git a/wpinet/src/main/native/thirdparty/libuv/src/uv-common.h b/wpinet/src/main/native/thirdparty/libuv/src/uv-common.h index 6001b0cf68d..5dce8eaf270 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/uv-common.h +++ b/wpinet/src/main/native/thirdparty/libuv/src/uv-common.h @@ -30,12 +30,9 @@ #include #include #include +#include -#if defined(_MSC_VER) && _MSC_VER < 1600 -# include "uv/stdint-msvc2008.h" -#else -# include -#endif +#include #include "uv.h" #include "uv/tree.h" @@ -53,19 +50,25 @@ extern int snprintf(char*, size_t, const char*, ...); #endif #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#define ARRAY_END(a) ((a) + ARRAY_SIZE(a)) #define container_of(ptr, type, member) \ ((type *) ((char *) (ptr) - offsetof(type, member))) +/* C11 defines static_assert to be a macro which calls _Static_assert. */ +#if defined(static_assert) +#define STATIC_ASSERT(expr) static_assert(expr, #expr) +#else #define STATIC_ASSERT(expr) \ void uv__static_assert(int static_assert_failed[1 - 2 * !(expr)]) +#endif -#if defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 7) -#define uv__load_relaxed(p) __atomic_load_n(p, __ATOMIC_RELAXED) -#define uv__store_relaxed(p, v) __atomic_store_n(p, v, __ATOMIC_RELAXED) +#ifdef _MSC_VER +#define uv__exchange_int_relaxed(p, v) \ + InterlockedExchangeNoFence((LONG volatile*)(p), v) #else -#define uv__load_relaxed(p) (*p) -#define uv__store_relaxed(p, v) do *p = v; while (0) +#define uv__exchange_int_relaxed(p, v) \ + std::atomic_exchange_explicit((std::atomic*)(p), v, std::memory_order_relaxed) #endif #define UV__UDP_DGRAM_MAXSIZE (64 * 1024) @@ -83,7 +86,6 @@ enum { /* Used by streams. */ UV_HANDLE_LISTENING = 0x00000040, UV_HANDLE_CONNECTION = 0x00000080, - UV_HANDLE_SHUTTING = 0x00000100, UV_HANDLE_SHUT = 0x00000200, UV_HANDLE_READ_PARTIAL = 0x00000400, UV_HANDLE_READ_EOF = 0x00000800, @@ -263,6 +265,14 @@ void uv__threadpool_cleanup(void); #define uv__is_closing(h) \ (((h)->flags & (UV_HANDLE_CLOSING | UV_HANDLE_CLOSED)) != 0) +#if defined(_WIN32) +# define uv__is_stream_shutting(h) \ + (h->stream.conn.shutdown_req != NULL) +#else +# define uv__is_stream_shutting(h) \ + (h->shutdown_req != NULL) +#endif + #define uv__handle_start(h) \ do { \ if (((h)->flags & UV_HANDLE_ACTIVE) != 0) break; \ @@ -311,7 +321,7 @@ void uv__threadpool_cleanup(void); (h)->loop = (loop_); \ (h)->type = (type_); \ (h)->flags = UV_HANDLE_REF; /* Ref the loop when active. */ \ - QUEUE_INSERT_TAIL(&(loop_)->handle_queue, &(h)->handle_queue); \ + uv__queue_insert_tail(&(loop_)->handle_queue, &(h)->handle_queue); \ uv__handle_platform_init(h); \ } \ while (0) @@ -347,6 +357,21 @@ void uv__threadpool_cleanup(void); #define uv__get_loop_metrics(loop) \ (&uv__get_internal_fields(loop)->loop_metrics) +#define uv__metrics_inc_loop_count(loop) \ + do { \ + uv__get_loop_metrics(loop)->metrics.loop_count++; \ + } while (0) + +#define uv__metrics_inc_events(loop, e) \ + do { \ + uv__get_loop_metrics(loop)->metrics.events += (e); \ + } while (0) + +#define uv__metrics_inc_events_waiting(loop, e) \ + do { \ + uv__get_loop_metrics(loop)->metrics.events_waiting += (e); \ + } while (0) + /* Allocator prototypes */ void *uv__calloc(size_t count, size_t size); char *uv__strdup(const char* s); @@ -360,6 +385,7 @@ typedef struct uv__loop_metrics_s uv__loop_metrics_t; typedef struct uv__loop_internal_fields_s uv__loop_internal_fields_t; struct uv__loop_metrics_s { + uv_metrics_t metrics; uint64_t provider_entry_time; uint64_t provider_idle_time; uv_mutex_t lock; @@ -368,9 +394,38 @@ struct uv__loop_metrics_s { void uv__metrics_update_idle_time(uv_loop_t* loop); void uv__metrics_set_provider_entry_time(uv_loop_t* loop); +#ifdef __linux__ +struct uv__iou { + uint32_t* sqhead; + uint32_t* sqtail; + uint32_t* sqarray; + uint32_t sqmask; + uint32_t* sqflags; + uint32_t* cqhead; + uint32_t* cqtail; + uint32_t cqmask; + void* sq; /* pointer to munmap() on event loop teardown */ + void* cqe; /* pointer to array of struct uv__io_uring_cqe */ + void* sqe; /* pointer to array of struct uv__io_uring_sqe */ + size_t sqlen; + size_t cqlen; + size_t maxlen; + size_t sqelen; + int ringfd; + uint32_t in_flight; + uint32_t flags; +}; +#endif /* __linux__ */ + struct uv__loop_internal_fields_s { unsigned int flags; uv__loop_metrics_t loop_metrics; + int current_timeout; +#ifdef __linux__ + struct uv__iou ctl; + struct uv__iou iou; + void* inv; /* used by uv__platform_invalidate_fd() */ +#endif /* __linux__ */ }; #endif /* UV_COMMON_H_ */ diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/core.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/core.cpp index 0752edff3eb..87ade7ad652 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/win/core.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/win/core.cpp @@ -247,6 +247,9 @@ int uv_loop_init(uv_loop_t* loop) { err = uv_mutex_init(&lfields->loop_metrics.lock); if (err) goto fail_metrics_mutex_init; + memset(&lfields->loop_metrics.metrics, + 0, + sizeof(lfields->loop_metrics.metrics)); /* To prevent uninitialized memory access, loop->time must be initialized * to zero before calling uv_update_time for the first time. @@ -254,8 +257,8 @@ int uv_loop_init(uv_loop_t* loop) { loop->time = 0; uv_update_time(loop); - QUEUE_INIT(&loop->wq); - QUEUE_INIT(&loop->handle_queue); + uv__queue_init(&loop->wq); + uv__queue_init(&loop->handle_queue); loop->active_reqs.count = 0; loop->active_handles = 0; @@ -281,9 +284,6 @@ int uv_loop_init(uv_loop_t* loop) { memset(&loop->poll_peer_sockets, 0, sizeof loop->poll_peer_sockets); - loop->active_tcp_streams = 0; - loop->active_udp_streams = 0; - loop->timer_counter = 0; loop->stop_flag = 0; @@ -360,7 +360,7 @@ void uv__loop_close(uv_loop_t* loop) { } uv_mutex_lock(&loop->wq_mutex); - assert(QUEUE_EMPTY(&loop->wq) && "thread pool work queue not empty!"); + assert(uv__queue_empty(&loop->wq) && "thread pool work queue not empty!"); assert(!uv__has_active_reqs(loop)); uv_mutex_unlock(&loop->wq_mutex); uv_mutex_destroy(&loop->wq_mutex); @@ -426,6 +426,7 @@ int uv_backend_timeout(const uv_loop_t* loop) { static void uv__poll_wine(uv_loop_t* loop, DWORD timeout) { + uv__loop_internal_fields_t* lfields; DWORD bytes; ULONG_PTR key; OVERLAPPED* overlapped; @@ -435,9 +436,10 @@ static void uv__poll_wine(uv_loop_t* loop, DWORD timeout) { uint64_t user_timeout; int reset_timeout; + lfields = uv__get_internal_fields(loop); timeout_time = loop->time + timeout; - if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) { + if (lfields->flags & UV_METRICS_IDLE_TIME) { reset_timeout = 1; user_timeout = timeout; timeout = 0; @@ -452,6 +454,12 @@ static void uv__poll_wine(uv_loop_t* loop, DWORD timeout) { if (timeout != 0) uv__metrics_set_provider_entry_time(loop); + /* Store the current timeout in a location that's globally accessible so + * other locations like uv__work_done() can determine whether the queue + * of events in the callback were waiting when poll was called. + */ + lfields->current_timeout = timeout; + GetQueuedCompletionStatus(loop->iocp, &bytes, &key, @@ -459,6 +467,8 @@ static void uv__poll_wine(uv_loop_t* loop, DWORD timeout) { timeout); if (reset_timeout != 0) { + if (overlapped && timeout == 0) + uv__metrics_inc_events_waiting(loop, 1); timeout = user_timeout; reset_timeout = 0; } @@ -471,6 +481,8 @@ static void uv__poll_wine(uv_loop_t* loop, DWORD timeout) { uv__metrics_update_idle_time(loop); if (overlapped) { + uv__metrics_inc_events(loop, 1); + /* Package was dequeued */ req = uv__overlapped_to_req(overlapped); uv__insert_pending_req(loop, req); @@ -505,6 +517,7 @@ static void uv__poll_wine(uv_loop_t* loop, DWORD timeout) { static void uv__poll(uv_loop_t* loop, DWORD timeout) { + uv__loop_internal_fields_t* lfields; BOOL success; uv_req_t* req; OVERLAPPED_ENTRY overlappeds[128]; @@ -513,11 +526,13 @@ static void uv__poll(uv_loop_t* loop, DWORD timeout) { int repeat; uint64_t timeout_time; uint64_t user_timeout; + uint64_t actual_timeout; int reset_timeout; + lfields = uv__get_internal_fields(loop); timeout_time = loop->time + timeout; - if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) { + if (lfields->flags & UV_METRICS_IDLE_TIME) { reset_timeout = 1; user_timeout = timeout; timeout = 0; @@ -526,12 +541,20 @@ static void uv__poll(uv_loop_t* loop, DWORD timeout) { } for (repeat = 0; ; repeat++) { + actual_timeout = timeout; + /* Only need to set the provider_entry_time if timeout != 0. The function * will return early if the loop isn't configured with UV_METRICS_IDLE_TIME. */ if (timeout != 0) uv__metrics_set_provider_entry_time(loop); + /* Store the current timeout in a location that's globally accessible so + * other locations like uv__work_done() can determine whether the queue + * of events in the callback were waiting when poll was called. + */ + lfields->current_timeout = timeout; + success = pGetQueuedCompletionStatusEx(loop->iocp, overlappeds, ARRAY_SIZE(overlappeds), @@ -545,9 +568,9 @@ static void uv__poll(uv_loop_t* loop, DWORD timeout) { } /* Placed here because on success the loop will break whether there is an - * empty package or not, or if GetQueuedCompletionStatus returned early then - * the timeout will be updated and the loop will run again. In either case - * the idle time will need to be updated. + * empty package or not, or if pGetQueuedCompletionStatusEx returned early + * then the timeout will be updated and the loop will run again. In either + * case the idle time will need to be updated. */ uv__metrics_update_idle_time(loop); @@ -557,6 +580,10 @@ static void uv__poll(uv_loop_t* loop, DWORD timeout) { * meant only to wake us up. */ if (overlappeds[i].lpOverlapped) { + uv__metrics_inc_events(loop, 1); + if (actual_timeout == 0) + uv__metrics_inc_events_waiting(loop, 1); + req = uv__overlapped_to_req(overlappeds[i].lpOverlapped); uv__insert_pending_req(loop, req); } @@ -600,10 +627,16 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { if (!r) uv_update_time(loop); - while (r != 0 && loop->stop_flag == 0) { + /* Maintain backwards compatibility by processing timers before entering the + * while loop for UV_RUN_DEFAULT. Otherwise timers only need to be executed + * once, which should be done after polling in order to maintain proper + * execution order of the conceptual event loop. */ + if (mode == UV_RUN_DEFAULT && r != 0 && loop->stop_flag == 0) { uv_update_time(loop); uv__run_timers(loop); + } + while (r != 0 && loop->stop_flag == 0) { can_sleep = loop->pending_reqs_tail == NULL && loop->idle_handles == NULL; uv__process_reqs(loop); @@ -614,6 +647,8 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { if ((mode == UV_RUN_ONCE && can_sleep) || mode == UV_RUN_DEFAULT) timeout = uv_backend_timeout(loop); + uv__metrics_inc_loop_count(loop); + if (pGetQueuedCompletionStatusEx) uv__poll(loop, timeout); else @@ -634,18 +669,8 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { uv__check_invoke(loop); uv__process_endgames(loop); - if (mode == UV_RUN_ONCE) { - /* UV_RUN_ONCE implies forward progress: at least one callback must have - * been invoked when it returns. uv__io_poll() can return without doing - * I/O (meaning: no callbacks) when its timeout expires - which means we - * have pending timers that satisfy the forward progress constraint. - * - * UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from - * the check. - */ - uv_update_time(loop); - uv__run_timers(loop); - } + uv_update_time(loop); + uv__run_timers(loop); r = uv__loop_alive(loop); if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT) diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/fs.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/fs.cpp index 71c9b1693bb..f415ddc2c39 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/win/fs.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/win/fs.cpp @@ -38,6 +38,8 @@ #include "handle-inl.h" #include "fs-fd-hash-inl.h" +#include + #pragma comment(lib, "Advapi32.lib") #define UV_FS_FREE_PATHS 0x0002 @@ -145,26 +147,97 @@ void uv__fs_init(void) { } +static int32_t fs__decode_wtf8_char(const char** input) { + uint32_t code_point; + uint8_t b1; + uint8_t b2; + uint8_t b3; + uint8_t b4; + + b1 = **input; + if (b1 <= 0x7F) + return b1; /* ASCII code point */ + if (b1 < 0xC2) + return -1; /* invalid: continuation byte */ + code_point = b1; + + b2 = *++*input; + if ((b2 & 0xC0) != 0x80) + return -1; /* invalid: not a continuation byte */ + code_point = (code_point << 6) | (b2 & 0x3F); + if (b1 <= 0xDF) + return 0x7FF & code_point; /* two-byte character */ + + b3 = *++*input; + if ((b3 & 0xC0) != 0x80) + return -1; /* invalid: not a continuation byte */ + code_point = (code_point << 6) | (b3 & 0x3F); + if (b1 <= 0xEF) + return 0xFFFF & code_point; /* three-byte character */ + + b4 = *++*input; + if ((b4 & 0xC0) != 0x80) + return -1; /* invalid: not a continuation byte */ + code_point = (code_point << 6) | (b4 & 0x3F); + if (b1 <= 0xF4) + if (code_point <= 0x10FFFF) + return code_point; /* four-byte character */ + + /* code point too large */ + return -1; +} + + +static ssize_t fs__get_length_wtf8(const char* source_ptr) { + size_t w_target_len = 0; + int32_t code_point; + + do { + code_point = fs__decode_wtf8_char(&source_ptr); + if (code_point < 0) + return -1; + if (code_point > 0xFFFF) + w_target_len++; + w_target_len++; + } while (*source_ptr++); + return w_target_len; +} + + +static void fs__wtf8_to_wide(const char* source_ptr, WCHAR* w_target) { + int32_t code_point; + + do { + code_point = fs__decode_wtf8_char(&source_ptr); + /* fs__get_length_wtf8 should have been called and checked first. */ + assert(code_point >= 0); + if (code_point > 0x10000) { + assert(code_point < 0x10FFFF); + *w_target++ = (((code_point - 0x10000) >> 10) + 0xD800); + *w_target++ = ((code_point - 0x10000) & 0x3FF) + 0xDC00; + } else { + *w_target++ = code_point; + } + } while (*source_ptr++); +} + + INLINE static int fs__capture_path(uv_fs_t* req, const char* path, const char* new_path, const int copy_path) { - char* buf; - char* pos; - ssize_t buf_sz = 0, path_len = 0, pathw_len = 0, new_pathw_len = 0; + WCHAR* buf; + WCHAR* pos; + size_t buf_sz = 0; + size_t path_len = 0; + ssize_t pathw_len = 0; + ssize_t new_pathw_len = 0; /* new_path can only be set if path is also set. */ assert(new_path == NULL || path != NULL); if (path != NULL) { - pathw_len = MultiByteToWideChar(CP_UTF8, - 0, - path, - -1, - NULL, - 0); - if (pathw_len == 0) { - return GetLastError(); - } - + pathw_len = fs__get_length_wtf8(path); + if (pathw_len < 0) + return ERROR_INVALID_NAME; buf_sz += pathw_len * sizeof(WCHAR); } @@ -174,16 +247,9 @@ INLINE static int fs__capture_path(uv_fs_t* req, const char* path, } if (new_path != NULL) { - new_pathw_len = MultiByteToWideChar(CP_UTF8, - 0, - new_path, - -1, - NULL, - 0); - if (new_pathw_len == 0) { - return GetLastError(); - } - + new_pathw_len = fs__get_length_wtf8(new_path); + if (new_pathw_len < 0) + return ERROR_INVALID_NAME; buf_sz += new_pathw_len * sizeof(WCHAR); } @@ -195,7 +261,7 @@ INLINE static int fs__capture_path(uv_fs_t* req, const char* path, return 0; } - buf = (char*) uv__malloc(buf_sz); + buf = (WCHAR *)uv__malloc(buf_sz); if (buf == NULL) { return ERROR_OUTOFMEMORY; } @@ -203,29 +269,17 @@ INLINE static int fs__capture_path(uv_fs_t* req, const char* path, pos = buf; if (path != NULL) { - DWORD r = MultiByteToWideChar(CP_UTF8, - 0, - path, - -1, - (WCHAR*) pos, - pathw_len); - assert(r == (DWORD) pathw_len); - req->file.pathw = (WCHAR*) pos; - pos += r * sizeof(WCHAR); + fs__wtf8_to_wide(path, pos); + req->file.pathw = pos; + pos += pathw_len; } else { req->file.pathw = NULL; } if (new_path != NULL) { - DWORD r = MultiByteToWideChar(CP_UTF8, - 0, - new_path, - -1, - (WCHAR*) pos, - new_pathw_len); - assert(r == (DWORD) new_pathw_len); - req->fs.info.new_pathw = (WCHAR*) pos; - pos += r * sizeof(WCHAR); + fs__wtf8_to_wide(new_path, pos); + req->fs.info.new_pathw = pos; + pos += new_pathw_len; } else { req->fs.info.new_pathw = NULL; } @@ -233,8 +287,8 @@ INLINE static int fs__capture_path(uv_fs_t* req, const char* path, req->path = path; if (path != NULL && copy_path) { memcpy(pos, path, path_len); - assert(path_len == buf_sz - (pos - buf)); - req->path = pos; + assert(path_len == buf_sz - (pos - buf) * sizeof(WCHAR)); + req->path = (char*) pos; } req->flags |= UV_FS_FREE_PATHS; @@ -260,57 +314,115 @@ INLINE static void uv__fs_req_init(uv_loop_t* loop, uv_fs_t* req, } -static int fs__wide_to_utf8(WCHAR* w_source_ptr, - DWORD w_source_len, - char** target_ptr, - uint64_t* target_len_ptr) { - int r; - int target_len; - char* target; - target_len = WideCharToMultiByte(CP_UTF8, - 0, - w_source_ptr, - w_source_len, - NULL, - 0, - NULL, - NULL); +static int32_t fs__get_surrogate_value(const WCHAR* w_source_ptr, + size_t w_source_len) { + WCHAR u; + WCHAR next; - if (target_len == 0) { - return -1; + u = w_source_ptr[0]; + if (u >= 0xD800 && u <= 0xDBFF && w_source_len > 1) { + next = w_source_ptr[1]; + if (next >= 0xDC00 && next <= 0xDFFF) + return 0x10000 + ((u - 0xD800) << 10) + (next - 0xDC00); } + return u; +} + + +static size_t fs__get_length_wide(const WCHAR* w_source_ptr, + size_t w_source_len) { + size_t target_len; + int32_t code_point; - if (target_len_ptr != NULL) { - *target_len_ptr = target_len; + target_len = 0; + for (; w_source_len; w_source_len--, w_source_ptr++) { + code_point = fs__get_surrogate_value(w_source_ptr, w_source_len); + /* Can be invalid UTF-8 but must be valid WTF-8. */ + assert(code_point >= 0); + if (code_point < 0x80) + target_len += 1; + else if (code_point < 0x800) + target_len += 2; + else if (code_point < 0x10000) + target_len += 3; + else { + target_len += 4; + w_source_ptr++; + w_source_len--; + } } + return target_len; +} - if (target_ptr == NULL) { - return 0; + +static int fs__wide_to_wtf8(WCHAR* w_source_ptr, + size_t w_source_len, + char** target_ptr, + size_t* target_len_ptr) { + size_t target_len; + char* target; + int32_t code_point; + + /* If *target_ptr is provided, then *target_len_ptr must be its length + * (excluding space for null), otherwise we will compute the target_len_ptr + * length and may return a new allocation in *target_ptr if target_ptr is + * provided. */ + if (target_ptr == NULL || *target_ptr == NULL) { + target_len = fs__get_length_wide(w_source_ptr, w_source_len); + if (target_len_ptr != NULL) + *target_len_ptr = target_len; + } else { + target_len = *target_len_ptr; } - target = (char*)uv__malloc(target_len + 1); - if (target == NULL) { - SetLastError(ERROR_OUTOFMEMORY); - return -1; + if (target_ptr == NULL) + return 0; + + if (*target_ptr == NULL) { + target = (char *)uv__malloc(target_len + 1); + if (target == NULL) { + SetLastError(ERROR_OUTOFMEMORY); + return -1; + } + *target_ptr = target; + } else { + target = *target_ptr; + } + + for (; w_source_len; w_source_len--, w_source_ptr++) { + code_point = fs__get_surrogate_value(w_source_ptr, w_source_len); + /* Can be invalid UTF-8 but must be valid WTF-8. */ + assert(code_point >= 0); + + if (code_point < 0x80) { + *target++ = code_point; + } else if (code_point < 0x800) { + *target++ = 0xC0 | (code_point >> 6); + *target++ = 0x80 | (code_point & 0x3F); + } else if (code_point < 0x10000) { + *target++ = 0xE0 | (code_point >> 12); + *target++ = 0x80 | ((code_point >> 6) & 0x3F); + *target++ = 0x80 | (code_point & 0x3F); + } else { + *target++ = 0xF0 | (code_point >> 18); + *target++ = 0x80 | ((code_point >> 12) & 0x3F); + *target++ = 0x80 | ((code_point >> 6) & 0x3F); + *target++ = 0x80 | (code_point & 0x3F); + w_source_ptr++; + w_source_len--; + } } + assert((size_t) (target - *target_ptr) == target_len); + + *target++ = '\0'; - r = WideCharToMultiByte(CP_UTF8, - 0, - w_source_ptr, - w_source_len, - target, - target_len, - NULL, - NULL); - assert(r == target_len); - target[target_len] = '\0'; - *target_ptr = target; return 0; } -INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr, - uint64_t* target_len_ptr) { +INLINE static int fs__readlink_handle(HANDLE handle, + char** target_ptr, + size_t* target_len_ptr) { char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; REPARSE_DATA_BUFFER* reparse_data = (REPARSE_DATA_BUFFER*) buffer; WCHAR* w_target; @@ -440,7 +552,8 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr, return -1; } - return fs__wide_to_utf8(w_target, w_target_len, target_ptr, target_len_ptr); + assert(target_ptr == NULL || *target_ptr == NULL); + return fs__wide_to_wtf8(w_target, w_target_len, target_ptr, target_len_ptr); } @@ -1430,7 +1543,8 @@ void fs__scandir(uv_fs_t* req) { uv__dirent_t* dirent; size_t wchar_len; - size_t utf8_len; + size_t wtf8_len; + char* wtf8; /* Obtain a pointer to the current directory entry. */ position += next_entry_offset; @@ -1457,11 +1571,8 @@ void fs__scandir(uv_fs_t* req) { info->FileName[1] == L'.') continue; - /* Compute the space required to store the filename as UTF-8. */ - utf8_len = WideCharToMultiByte( - CP_UTF8, 0, &info->FileName[0], wchar_len, NULL, 0, NULL, NULL); - if (utf8_len == 0) - goto win32_error; + /* Compute the space required to store the filename as WTF-8. */ + wtf8_len = fs__get_length_wide(&info->FileName[0], wchar_len); /* Resize the dirent array if needed. */ if (dirents_used >= dirents_size) { @@ -1481,26 +1592,17 @@ void fs__scandir(uv_fs_t* req) { * includes room for the first character of the filename, but `utf8_len` * doesn't count the NULL terminator at this point. */ - dirent = (uv__dirent_t*)uv__malloc(sizeof *dirent + utf8_len); + dirent = (uv__dirent_t*)uv__malloc(sizeof *dirent + wtf8_len); if (dirent == NULL) goto out_of_memory_error; dirents[dirents_used++] = dirent; /* Convert file name to UTF-8. */ - if (WideCharToMultiByte(CP_UTF8, - 0, - &info->FileName[0], - wchar_len, - &dirent->d_name[0], - utf8_len, - NULL, - NULL) == 0) + wtf8 = &dirent->d_name[0]; + if (fs__wide_to_wtf8(&info->FileName[0], wchar_len, &wtf8, &wtf8_len) == -1) goto win32_error; - /* Add a null terminator to the filename. */ - dirent->d_name[utf8_len] = '\0'; - /* Fill out the type field. */ if (info->FileAttributes & FILE_ATTRIBUTE_DEVICE) dirent->d_type = UV__DT_CHAR; @@ -1709,11 +1811,37 @@ void fs__closedir(uv_fs_t* req) { INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf, int do_lstat) { + size_t target_length = 0; + FILE_FS_DEVICE_INFORMATION device_info; FILE_ALL_INFORMATION file_info; FILE_FS_VOLUME_INFORMATION volume_info; NTSTATUS nt_status; IO_STATUS_BLOCK io_status; + nt_status = pNtQueryVolumeInformationFile(handle, + &io_status, + &device_info, + sizeof device_info, + FileFsDeviceInformation); + + /* Buffer overflow (a warning status code) is expected here. */ + if (NT_ERROR(nt_status)) { + SetLastError(pRtlNtStatusToDosError(nt_status)); + return -1; + } + + /* If it's NUL device set fields as reasonable as possible and return. */ + if (device_info.DeviceType == FILE_DEVICE_NULL) { + memset(statbuf, 0, sizeof(uv_stat_t)); + statbuf->st_mode = _S_IFCHR; + statbuf->st_mode |= (_S_IREAD | _S_IWRITE) | ((_S_IREAD | _S_IWRITE) >> 3) | + ((_S_IREAD | _S_IWRITE) >> 6); + statbuf->st_nlink = 1; + statbuf->st_blksize = 4096; + statbuf->st_rdev = FILE_DEVICE_NULL << 16; + return 0; + } + nt_status = pNtQueryInformationFile(handle, &io_status, &file_info, @@ -1779,9 +1907,10 @@ INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf, * to be treated as a regular file. The higher level lstat function will * detect this failure and retry without do_lstat if appropriate. */ - if (fs__readlink_handle(handle, NULL, &statbuf->st_size) != 0) + if (fs__readlink_handle(handle, NULL, &target_length) != 0) return -1; statbuf->st_mode |= S_IFLNK; + statbuf->st_size = target_length; } if (statbuf->st_mode == 0) { @@ -1918,6 +2047,37 @@ INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) { } +INLINE static int fs__fstat_handle(int fd, HANDLE handle, uv_stat_t* statbuf) { + DWORD file_type; + + /* Each file type is processed differently. */ + file_type = uv_guess_handle(fd); + switch (file_type) { + /* Disk files use the existing logic from fs__stat_handle. */ + case UV_FILE: + return fs__stat_handle(handle, statbuf, 0); + + /* Devices and pipes are processed identically. There is no more information + * for them from any API. Fields are set as reasonably as possible and the + * function returns. */ + case UV_TTY: + case UV_NAMED_PIPE: + memset(statbuf, 0, sizeof(uv_stat_t)); + statbuf->st_mode = file_type == UV_TTY ? _S_IFCHR : _S_IFIFO; + statbuf->st_nlink = 1; + statbuf->st_rdev = (file_type == UV_TTY ? FILE_DEVICE_CONSOLE : FILE_DEVICE_NAMED_PIPE) << 16; + statbuf->st_ino = (uintptr_t) handle; + return 0; + + /* If file type is unknown it is an error. */ + case UV_UNKNOWN_HANDLE: + default: + SetLastError(ERROR_INVALID_HANDLE); + return -1; + } +} + + static void fs__stat(uv_fs_t* req) { fs__stat_prepare_path(req->file.pathw); fs__stat_impl(req, 0); @@ -1943,7 +2103,7 @@ static void fs__fstat(uv_fs_t* req) { return; } - if (fs__stat_handle(handle, &req->statbuf, 0) != 0) { + if (fs__fstat_handle(fd, handle, &req->statbuf) != 0) { SET_REQ_WIN32_ERROR(req, GetLastError()); return; } @@ -2224,7 +2384,7 @@ static void fs__fchmod(uv_fs_t* req) { SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status)); goto fchmod_cleanup; } - /* Remeber to clear the flag later on */ + /* Remember to clear the flag later on */ clear_archive_flag = 1; } else { clear_archive_flag = 0; @@ -2606,8 +2766,12 @@ static void fs__readlink(uv_fs_t* req) { return; } + assert(req->ptr == NULL); if (fs__readlink_handle(handle, (char**) &req->ptr, NULL) != 0) { - SET_REQ_WIN32_ERROR(req, GetLastError()); + DWORD error = GetLastError(); + SET_REQ_WIN32_ERROR(req, error); + if (error == ERROR_NOT_A_REPARSE_POINT) + req->result = UV_EINVAL; CloseHandle(handle); return; } @@ -2662,7 +2826,8 @@ static ssize_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) { return -1; } - r = fs__wide_to_utf8(w_realpath_ptr, w_realpath_len, realpath_ptr, NULL); + assert(*realpath_ptr == NULL); + r = fs__wide_to_wtf8(w_realpath_ptr, w_realpath_len, realpath_ptr, NULL); uv__free(w_realpath_buf); return r; } @@ -2682,6 +2847,7 @@ static void fs__realpath(uv_fs_t* req) { return; } + assert(req->ptr == NULL); if (fs__realpath_handle(handle, (char**) &req->ptr) == -1) { CloseHandle(handle); SET_REQ_WIN32_ERROR(req, GetLastError()); diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/handle-inl.h b/wpinet/src/main/native/thirdparty/libuv/src/win/handle-inl.h index 5c843c241ef..4722e85790a 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/win/handle-inl.h +++ b/wpinet/src/main/native/thirdparty/libuv/src/win/handle-inl.h @@ -75,7 +75,7 @@ #define uv__handle_close(handle) \ do { \ - QUEUE_REMOVE(&(handle)->handle_queue); \ + uv__queue_remove(&(handle)->handle_queue); \ uv__active_handle_rm((uv_handle_t*) (handle)); \ \ (handle)->flags |= UV_HANDLE_CLOSED; \ diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/internal.h b/wpinet/src/main/native/thirdparty/libuv/src/win/internal.h index 89c72b8a1a6..9672fbc6826 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/win/internal.h +++ b/wpinet/src/main/native/thirdparty/libuv/src/win/internal.h @@ -168,18 +168,8 @@ void uv__process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle, uv_req_t* req); void uv__process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle, uv_write_t* req); -/* - * uv__process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working - * TODO: find a way to remove it - */ -void uv__process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle, - uv_req_t* raw_req); -/* - * uv__process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working - * TODO: find a way to remove it - */ -void uv__process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle, - uv_connect_t* req); +#define uv__process_tty_accept_req(loop, handle, req) abort() +#define uv__process_tty_connect_req(loop, handle, req) abort() void uv__process_tty_shutdown_req(uv_loop_t* loop, uv_tty_t* stream, uv_shutdown_t* req); @@ -267,7 +257,6 @@ void uv__util_init(void); uint64_t uv__hrtime(unsigned int scale); __declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall); -int uv__getpwuid_r(uv_passwd_t* pwd); int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8); int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16); diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/pipe.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/pipe.cpp index f413a72dab5..258d6a684c6 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/win/pipe.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/win/pipe.cpp @@ -57,7 +57,7 @@ static const int pipe_prefix_len = sizeof(pipe_prefix) - 1; typedef struct { uv__ipc_socket_xfer_type_t xfer_type; uv__ipc_socket_xfer_info_t xfer_info; - QUEUE member; + struct uv__queue member; } uv__ipc_xfer_queue_item_t; /* IPC frame header flags. */ @@ -113,7 +113,7 @@ int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) { handle->name = NULL; handle->pipe.conn.ipc_remote_pid = 0; handle->pipe.conn.ipc_data_frame.payload_remaining = 0; - QUEUE_INIT(&handle->pipe.conn.ipc_xfer_queue); + uv__queue_init(&handle->pipe.conn.ipc_xfer_queue); handle->pipe.conn.ipc_xfer_queue_length = 0; handle->ipc = ipc; handle->pipe.conn.non_overlapped_writes_tail = NULL; @@ -639,13 +639,13 @@ void uv__pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { if (handle->flags & UV_HANDLE_CONNECTION) { /* Free pending sockets */ - while (!QUEUE_EMPTY(&handle->pipe.conn.ipc_xfer_queue)) { - QUEUE* q; + while (!uv__queue_empty(&handle->pipe.conn.ipc_xfer_queue)) { + struct uv__queue* q; SOCKET socket; - q = QUEUE_HEAD(&handle->pipe.conn.ipc_xfer_queue); - QUEUE_REMOVE(q); - xfer_queue_item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member); + q = uv__queue_head(&handle->pipe.conn.ipc_xfer_queue); + uv__queue_remove(q); + xfer_queue_item = uv__queue_data(q, uv__ipc_xfer_queue_item_t, member); /* Materialize socket and close it */ socket = WSASocketW(FROM_PROTOCOL_INFO, @@ -696,20 +696,48 @@ void uv_pipe_pending_instances(uv_pipe_t* handle, int count) { /* Creates a pipe server. */ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { + return uv_pipe_bind2(handle, name, strlen(name), 0); +} + + +int uv_pipe_bind2(uv_pipe_t* handle, + const char* name, + size_t namelen, + unsigned int flags) { uv_loop_t* loop = handle->loop; int i, err, nameSize; uv_pipe_accept_t* req; - if (handle->flags & UV_HANDLE_BOUND) { + if (flags & ~UV_PIPE_NO_TRUNCATE) { + return UV_EINVAL; + } + + if (name == NULL) { return UV_EINVAL; } - if (!name) { + if (namelen == 0) { return UV_EINVAL; } + + if (*name == '\0') { + return UV_EINVAL; + } + + if (flags & UV_PIPE_NO_TRUNCATE) { + if (namelen > 256) { + return UV_EINVAL; + } + } + + if (handle->flags & UV_HANDLE_BOUND) { + return UV_EINVAL; + } + if (uv__is_closing(handle)) { return UV_EINVAL; } + if (!(handle->flags & UV_HANDLE_PIPESERVER)) { handle->pipe.serv.pending_instances = default_pending_pipe_instances; } @@ -794,15 +822,17 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) { /* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. We wait * up to 30 seconds for the pipe to become available with WaitNamedPipe. */ - while (WaitNamedPipeW(handle->name, 30000)) { + while (WaitNamedPipeW(req->u.connect.name, 30000)) { /* The pipe is now available, try to connect. */ - pipeHandle = open_named_pipe(handle->name, &duplex_flags); + pipeHandle = open_named_pipe(req->u.connect.name, &duplex_flags); if (pipeHandle != INVALID_HANDLE_VALUE) break; SwitchToThread(); } + uv__free(req->u.connect.name); + req->u.connect.name = NULL; if (pipeHandle != INVALID_HANDLE_VALUE) { SET_REQ_SUCCESS(req); req->u.connect.pipeHandle = pipeHandle; @@ -818,18 +848,53 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) { } -void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, - const char* name, uv_connect_cb cb) { +void uv_pipe_connect(uv_connect_t* req, + uv_pipe_t* handle, + const char* name, + uv_connect_cb cb) { + uv_pipe_connect2(req, handle, name, strlen(name), 0, cb); +} + + +int uv_pipe_connect2(uv_connect_t* req, + uv_pipe_t* handle, + const char* name, + size_t namelen, + unsigned int flags, + uv_connect_cb cb) { uv_loop_t* loop = handle->loop; int err, nameSize; HANDLE pipeHandle = INVALID_HANDLE_VALUE; DWORD duplex_flags; + if (flags & ~UV_PIPE_NO_TRUNCATE) { + return UV_EINVAL; + } + + if (name == NULL) { + return UV_EINVAL; + } + + if (namelen == 0) { + return UV_EINVAL; + } + + if (*name == '\0') { + return UV_EINVAL; + } + + if (flags & UV_PIPE_NO_TRUNCATE) { + if (namelen > 256) { + return UV_EINVAL; + } + } + UV_REQ_INIT(req, UV_CONNECT); req->handle = (uv_stream_t*) handle; req->cb = cb; req->u.connect.pipeHandle = INVALID_HANDLE_VALUE; req->u.connect.duplex_flags = 0; + req->u.connect.name = NULL; if (handle->flags & UV_HANDLE_PIPESERVER) { err = ERROR_INVALID_PARAMETER; @@ -861,10 +926,19 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, pipeHandle = open_named_pipe(handle->name, &duplex_flags); if (pipeHandle == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_PIPE_BUSY) { + req->u.connect.name = (WCHAR *)uv__malloc(nameSize); + if (!req->u.connect.name) { + uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); + } + + memcpy(req->u.connect.name, handle->name, nameSize); + /* Wait for the server to make a pipe instance available. */ if (!QueueUserWorkItem(&pipe_connect_thread_proc, req, WT_EXECUTELONGFUNCTION)) { + uv__free(req->u.connect.name); + req->u.connect.name = NULL; err = GetLastError(); goto error; } @@ -872,7 +946,7 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, REGISTER_HANDLE_REQ(loop, handle, req); handle->reqs_pending++; - return; + return 0; } err = GetLastError(); @@ -885,7 +959,7 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, uv__insert_pending_req(loop, (uv_req_t*) req); handle->reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); - return; + return 0; error: if (handle->name) { @@ -901,7 +975,7 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, uv__insert_pending_req(loop, (uv_req_t*) req); handle->reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); - return; + return 0; } @@ -1052,28 +1126,29 @@ int uv__pipe_accept(uv_pipe_t* server, uv_stream_t* client) { uv_loop_t* loop = server->loop; uv_pipe_t* pipe_client; uv_pipe_accept_t* req; - QUEUE* q; + struct uv__queue* q; uv__ipc_xfer_queue_item_t* item; int err; if (server->ipc) { - if (QUEUE_EMPTY(&server->pipe.conn.ipc_xfer_queue)) { + if (uv__queue_empty(&server->pipe.conn.ipc_xfer_queue)) { /* No valid pending sockets. */ return WSAEWOULDBLOCK; } - q = QUEUE_HEAD(&server->pipe.conn.ipc_xfer_queue); - QUEUE_REMOVE(q); + q = uv__queue_head(&server->pipe.conn.ipc_xfer_queue); + uv__queue_remove(q); server->pipe.conn.ipc_xfer_queue_length--; - item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member); + item = uv__queue_data(q, uv__ipc_xfer_queue_item_t, member); err = uv__tcp_xfer_import( (uv_tcp_t*) client, item->xfer_type, &item->xfer_info); + + uv__free(item); + if (err != 0) return err; - uv__free(item); - } else { pipe_client = (uv_pipe_t*) client; uv__pipe_connection_init(pipe_client); @@ -1640,9 +1715,13 @@ static DWORD uv__pipe_get_ipc_remote_pid(uv_pipe_t* handle) { /* If the both ends of the IPC pipe are owned by the same process, * the remote end pid may not yet be set. If so, do it here. * TODO: this is weird; it'd probably better to use a handshake. */ - if (*pid == 0) - *pid = GetCurrentProcessId(); - + if (*pid == 0) { + GetNamedPipeClientProcessId(handle->handle, pid); + if (*pid == GetCurrentProcessId()) { + GetNamedPipeServerProcessId(handle->handle, pid); + } + } + return *pid; } @@ -1814,7 +1893,7 @@ static void uv__pipe_queue_ipc_xfer_info( item->xfer_type = xfer_type; item->xfer_info = *xfer_info; - QUEUE_INSERT_TAIL(&handle->pipe.conn.ipc_xfer_queue, &item->member); + uv__queue_insert_tail(&handle->pipe.conn.ipc_xfer_queue, &item->member); handle->pipe.conn.ipc_xfer_queue_length++; } @@ -2071,9 +2150,9 @@ void uv__process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle, uv__queue_non_overlapped_write(handle); } - if (handle->stream.conn.write_reqs_pending == 0) - if (handle->flags & UV_HANDLE_SHUTTING) - uv__pipe_shutdown(loop, handle, handle->stream.conn.shutdown_req); + if (handle->stream.conn.write_reqs_pending == 0 && + uv__is_stream_shutting(handle)) + uv__pipe_shutdown(loop, handle, handle->stream.conn.shutdown_req); DECREASE_PENDING_REQ_COUNT(handle); } @@ -2128,7 +2207,10 @@ void uv__process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle, if (REQ_SUCCESS(req)) { pipeHandle = req->u.connect.pipeHandle; duplex_flags = req->u.connect.duplex_flags; - err = uv__set_pipe_handle(loop, handle, pipeHandle, -1, duplex_flags); + if (handle->flags & UV_HANDLE_CLOSING) + err = UV_ECANCELED; + else + err = uv__set_pipe_handle(loop, handle, pipeHandle, -1, duplex_flags); if (err) CloseHandle(pipeHandle); } else { @@ -2151,7 +2233,6 @@ void uv__process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle, /* Clear the shutdown_req field so we don't go here again. */ handle->stream.conn.shutdown_req = NULL; - handle->flags &= ~UV_HANDLE_SHUTTING; UNREGISTER_HANDLE_REQ(loop, handle, req); if (handle->flags & UV_HANDLE_CLOSING) { @@ -2344,7 +2425,10 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) { if (pipe->ipc) { assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)); - pipe->pipe.conn.ipc_remote_pid = uv_os_getppid(); + GetNamedPipeClientProcessId(os_handle, &pipe->pipe.conn.ipc_remote_pid); + if (pipe->pipe.conn.ipc_remote_pid == GetCurrentProcessId()) { + GetNamedPipeServerProcessId(os_handle, &pipe->pipe.conn.ipc_remote_pid); + } assert(pipe->pipe.conn.ipc_remote_pid != (DWORD)(uv_pid_t) -1); } return 0; diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/poll.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/poll.cpp index bd531b06792..7fec2b99650 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/win/poll.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/win/poll.cpp @@ -425,9 +425,8 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, return uv_translate_sys_error(WSAGetLastError()); /* Try to obtain a base handle for the socket. This increases this chances that - * we find an AFD handle and are able to use the fast poll mechanism. This will - * always fail on windows XP/2k3, since they don't support the. SIO_BASE_HANDLE - * ioctl. */ + * we find an AFD handle and are able to use the fast poll mechanism. + */ #ifndef NDEBUG base_socket = INVALID_SOCKET; #endif diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/process.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/process.cpp index 8e7835a5e90..a0f55aba003 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/win/process.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/win/process.cpp @@ -34,6 +34,9 @@ #include "internal.h" #include "handle-inl.h" #include "req-inl.h" +#include +#include +#include /* GetModuleBaseNameW */ #define SIGKILL 9 @@ -145,7 +148,6 @@ static void uv__process_init(uv_loop_t* loop, uv_process_t* handle) { handle->exit_signal = 0; handle->wait_handle = INVALID_HANDLE_VALUE; handle->process_handle = INVALID_HANDLE_VALUE; - handle->child_stdio_buffer = NULL; handle->exit_cb_pending = 0; UV_REQ_INIT(&handle->exit_req, UV_PROCESS_EXIT); @@ -948,9 +950,11 @@ int uv_spawn(uv_loop_t* loop, STARTUPINFOW startup; PROCESS_INFORMATION info; DWORD process_flags; + BYTE* child_stdio_buffer; uv__process_init(loop, process); process->exit_cb = options->exit_cb; + child_stdio_buffer = NULL; if (options->flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) { return UV_ENOTSUP; @@ -1041,7 +1045,7 @@ int uv_spawn(uv_loop_t* loop, } } - err = uv__stdio_create(loop, options, &process->child_stdio_buffer); + err = uv__stdio_create(loop, options, &child_stdio_buffer); if (err) goto done; @@ -1060,12 +1064,12 @@ int uv_spawn(uv_loop_t* loop, startup.lpTitle = NULL; startup.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; - startup.cbReserved2 = uv__stdio_size(process->child_stdio_buffer); - startup.lpReserved2 = (BYTE*) process->child_stdio_buffer; + startup.cbReserved2 = uv__stdio_size(child_stdio_buffer); + startup.lpReserved2 = (BYTE*) child_stdio_buffer; - startup.hStdInput = uv__stdio_handle(process->child_stdio_buffer, 0); - startup.hStdOutput = uv__stdio_handle(process->child_stdio_buffer, 1); - startup.hStdError = uv__stdio_handle(process->child_stdio_buffer, 2); + startup.hStdInput = uv__stdio_handle(child_stdio_buffer, 0); + startup.hStdOutput = uv__stdio_handle(child_stdio_buffer, 1); + startup.hStdError = uv__stdio_handle(child_stdio_buffer, 2); process_flags = CREATE_UNICODE_ENVIRONMENT; @@ -1179,10 +1183,10 @@ int uv_spawn(uv_loop_t* loop, uv__free(env); uv__free(alloc_path); - if (process->child_stdio_buffer != NULL) { + if (child_stdio_buffer != NULL) { /* Clean up child stdio handles. */ - uv__stdio_destroy(process->child_stdio_buffer); - process->child_stdio_buffer = NULL; + uv__stdio_destroy(child_stdio_buffer); + child_stdio_buffer = NULL; } return uv_translate_sys_error(err); @@ -1194,7 +1198,120 @@ static int uv__kill(HANDLE process_handle, int signum) { return UV_EINVAL; } + /* Create a dump file for the targeted process, if the registry key + * `HKLM:Software\Microsoft\Windows\Windows Error Reporting\LocalDumps` + * exists. The location of the dumps can be influenced by the `DumpFolder` + * sub-key, which has a default value of `%LOCALAPPDATA%\CrashDumps`, see [0] + * for more detail. Note that if the dump folder does not exist, we attempt + * to create it, to match behavior with WER itself. + * [0]: https://learn.microsoft.com/en-us/windows/win32/wer/collecting-user-mode-dumps */ + if (signum == SIGQUIT) { + HKEY registry_key; + DWORD pid, ret; + WCHAR basename[MAX_PATH]; + + /* Get target process name. */ + GetModuleBaseNameW(process_handle, NULL, &basename[0], sizeof(basename)); + + /* Get PID of target process. */ + pid = GetProcessId(process_handle); + + /* Get LocalDumps directory path. */ + ret = RegOpenKeyExW( + HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\LocalDumps", + 0, + KEY_QUERY_VALUE, + ®istry_key); + if (ret == ERROR_SUCCESS) { + HANDLE hDumpFile = NULL; + WCHAR dump_folder[MAX_PATH], dump_name[MAX_PATH]; + DWORD dump_folder_len = sizeof(dump_folder), key_type = 0; + ret = RegGetValueW(registry_key, + NULL, + L"DumpFolder", + RRF_RT_ANY, + &key_type, + (PVOID) dump_folder, + &dump_folder_len); + if (ret != ERROR_SUCCESS) { + /* Default value for `dump_folder` is `%LOCALAPPDATA%\CrashDumps`. */ + WCHAR* localappdata; + SHGetKnownFolderPath(*((const KNOWNFOLDERID*)&FOLDERID_LocalAppData), 0, NULL, &localappdata); + _snwprintf_s(dump_folder, + sizeof(dump_folder), + _TRUNCATE, + L"%ls\\CrashDumps", + localappdata); + CoTaskMemFree(localappdata); + } + RegCloseKey(registry_key); + + /* Create dump folder if it doesn't already exist. */ + CreateDirectoryW(dump_folder, NULL); + + /* Construct dump filename from process name and PID. */ + _snwprintf_s(dump_name, + sizeof(dump_name), + _TRUNCATE, + L"%ls\\%ls.%d.dmp", + dump_folder, + basename, + pid); + + hDumpFile = CreateFileW(dump_name, + GENERIC_WRITE, + 0, + NULL, + CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hDumpFile != INVALID_HANDLE_VALUE) { + DWORD dump_options, sym_options; + FILE_DISPOSITION_INFO DeleteOnClose = { TRUE }; + + /* If something goes wrong while writing it out, delete the file. */ + SetFileInformationByHandle(hDumpFile, + FileDispositionInfo, + &DeleteOnClose, + sizeof(DeleteOnClose)); + + /* Tell wine to dump ELF modules as well. */ + sym_options = SymGetOptions(); + SymSetOptions(sym_options | 0x40000000); + +/* MiniDumpWithAvxXStateContext might be undef in server2012r2 or mingw < 12 */ +#ifndef MiniDumpWithAvxXStateContext +#define MiniDumpWithAvxXStateContext 0x00200000 +#endif + /* We default to a fairly complete dump. In the future, we may want to + * allow clients to customize what kind of dump to create. */ + dump_options = MiniDumpWithFullMemory | + MiniDumpIgnoreInaccessibleMemory | + MiniDumpWithAvxXStateContext; + + if (MiniDumpWriteDump(process_handle, + pid, + hDumpFile, + (MINIDUMP_TYPE)dump_options, + NULL, + NULL, + NULL)) { + /* Don't delete the file on close if we successfully wrote it out. */ + FILE_DISPOSITION_INFO DontDeleteOnClose = { FALSE }; + SetFileInformationByHandle(hDumpFile, + FileDispositionInfo, + &DontDeleteOnClose, + sizeof(DontDeleteOnClose)); + } + SymSetOptions(sym_options); + CloseHandle(hDumpFile); + } + } + } + switch (signum) { + case SIGQUIT: case SIGTERM: case SIGKILL: case SIGINT: { diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/stream.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/stream.cpp index 292bf588da6..7bf9ca388cb 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/win/stream.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/win/stream.cpp @@ -204,7 +204,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) { uv_loop_t* loop = handle->loop; if (!(handle->flags & UV_HANDLE_WRITABLE) || - handle->flags & UV_HANDLE_SHUTTING || + uv__is_stream_shutting(handle) || uv__is_closing(handle)) { return UV_ENOTCONN; } @@ -214,7 +214,6 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) { req->cb = cb; handle->flags &= ~UV_HANDLE_WRITABLE; - handle->flags |= UV_HANDLE_SHUTTING; handle->stream.conn.shutdown_req = req; handle->reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/tcp.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/tcp.cpp index 4cccee42922..d8da4d941a5 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/win/tcp.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/win/tcp.cpp @@ -29,14 +29,6 @@ #include "req-inl.h" -/* - * Threshold of active tcp streams for which to preallocate tcp read buffers. - * (Due to node slab allocator performing poorly under this pattern, - * the optimization is temporarily disabled (threshold=0). This will be - * revisited once node allocator is improved.) - */ -const unsigned int uv_active_tcp_streams_threshold = 0; - /* * Number of simultaneous pending AcceptEx calls. */ @@ -183,14 +175,14 @@ int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, unsigned int flags) { sock = socket(domain, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) { err = WSAGetLastError(); - QUEUE_REMOVE(&handle->handle_queue); + uv__queue_remove(&handle->handle_queue); return uv_translate_sys_error(err); } err = uv__tcp_set_socket(handle->loop, handle, sock, domain, 0); if (err) { closesocket(sock); - QUEUE_REMOVE(&handle->handle_queue); + uv__queue_remove(&handle->handle_queue); return uv_translate_sys_error(err); } @@ -214,7 +206,6 @@ void uv__process_tcp_shutdown_req(uv_loop_t* loop, uv_tcp_t* stream, uv_shutdown assert(stream->flags & UV_HANDLE_CONNECTION); stream->stream.conn.shutdown_req = NULL; - stream->flags &= ~UV_HANDLE_SHUTTING; UNREGISTER_HANDLE_REQ(loop, stream, req); err = 0; @@ -274,7 +265,6 @@ void uv__tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { } uv__handle_close(handle); - loop->active_tcp_streams--; } @@ -484,26 +474,9 @@ static void uv__tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) { req = &handle->read_req; memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); - /* - * Preallocate a read buffer if the number of active streams is below - * the threshold. - */ - if (loop->active_tcp_streams < uv_active_tcp_streams_threshold) { - handle->flags &= ~UV_HANDLE_ZERO_READ; - handle->tcp.conn.read_buffer = uv_buf_init(NULL, 0); - handle->alloc_cb((uv_handle_t*) handle, 65536, &handle->tcp.conn.read_buffer); - if (handle->tcp.conn.read_buffer.base == NULL || - handle->tcp.conn.read_buffer.len == 0) { - handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &handle->tcp.conn.read_buffer); - return; - } - assert(handle->tcp.conn.read_buffer.base != NULL); - buf = handle->tcp.conn.read_buffer; - } else { - handle->flags |= UV_HANDLE_ZERO_READ; - buf.base = (char*) &uv_zero_; - buf.len = 0; - } + handle->flags |= UV_HANDLE_ZERO_READ; + buf.base = (char*) &uv_zero_; + buf.len = 0; /* Prepare the overlapped structure. */ memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped)); @@ -550,7 +523,7 @@ int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) { struct linger l = { 1, 0 }; /* Disallow setting SO_LINGER to zero due to some platform inconsistencies */ - if (handle->flags & UV_HANDLE_SHUTTING) + if (uv__is_stream_shutting(handle)) return UV_EINVAL; if (0 != setsockopt(handle->socket, SOL_SOCKET, SO_LINGER, (const char*)&l, sizeof(l))) @@ -654,7 +627,6 @@ int uv__tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { int uv__tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { - uv_loop_t* loop = server->loop; int err = 0; int family; @@ -716,8 +688,6 @@ int uv__tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { } } - loop->active_tcp_streams++; - return err; } @@ -1163,7 +1133,7 @@ void uv__process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle, closesocket(handle->socket); handle->socket = INVALID_SOCKET; } - if (handle->flags & UV_HANDLE_SHUTTING) + if (uv__is_stream_shutting(handle)) uv__process_tcp_shutdown_req(loop, handle, handle->stream.conn.shutdown_req); @@ -1248,7 +1218,6 @@ void uv__process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, 0) == 0) { uv__connection_init((uv_stream_t*)handle); handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; - loop->active_tcp_streams++; } else { err = WSAGetLastError(); } @@ -1331,7 +1300,6 @@ int uv__tcp_xfer_import(uv_tcp_t* tcp, tcp->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; } - tcp->loop->active_tcp_streams++; return 0; } @@ -1432,7 +1400,7 @@ static void uv__tcp_try_cancel_reqs(uv_tcp_t* tcp) { uv_tcp_non_ifs_lsp_ipv4; /* If there are non-ifs LSPs then try to obtain a base handle for the socket. - * This will always fail on Windows XP/3k. */ + */ if (non_ifs_lsp) { DWORD bytes; if (WSAIoctl(socket, diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/thread.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/thread.cpp index 9ad60c9164c..03b33e9b4de 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/win/thread.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/win/thread.cpp @@ -180,6 +180,81 @@ int uv_thread_create_ex(uv_thread_t* tid, return UV_EIO; } +int uv_thread_setaffinity(uv_thread_t* tid, + char* cpumask, + char* oldmask, + size_t mask_size) { + int i; + HANDLE hproc; + DWORD_PTR procmask; + DWORD_PTR sysmask; + DWORD_PTR threadmask; + DWORD_PTR oldthreadmask; + int cpumasksize; + + cpumasksize = uv_cpumask_size(); + assert(cpumasksize > 0); + if (mask_size < (size_t)cpumasksize) + return UV_EINVAL; + + hproc = GetCurrentProcess(); + if (!GetProcessAffinityMask(hproc, &procmask, &sysmask)) + return uv_translate_sys_error(GetLastError()); + + threadmask = 0; + for (i = 0; i < cpumasksize; i++) { + if (cpumask[i]) { + if (procmask & (1LL << i)) + threadmask |= 1LL << i; + else + return UV_EINVAL; + } + } + + oldthreadmask = SetThreadAffinityMask(*tid, threadmask); + if (oldthreadmask == 0) + return uv_translate_sys_error(GetLastError()); + + if (oldmask != NULL) { + for (i = 0; i < cpumasksize; i++) + oldmask[i] = (oldthreadmask >> i) & 1; + } + + return 0; +} + +int uv_thread_getaffinity(uv_thread_t* tid, + char* cpumask, + size_t mask_size) { + int i; + HANDLE hproc; + DWORD_PTR procmask; + DWORD_PTR sysmask; + DWORD_PTR threadmask; + int cpumasksize; + + cpumasksize = uv_cpumask_size(); + assert(cpumasksize > 0); + if (mask_size < (size_t)cpumasksize) + return UV_EINVAL; + + hproc = GetCurrentProcess(); + if (!GetProcessAffinityMask(hproc, &procmask, &sysmask)) + return uv_translate_sys_error(GetLastError()); + + threadmask = SetThreadAffinityMask(*tid, procmask); + if (threadmask == 0 || SetThreadAffinityMask(*tid, threadmask) == 0) + return uv_translate_sys_error(GetLastError()); + + for (i = 0; i < cpumasksize; i++) + cpumask[i] = (threadmask >> i) & 1; + + return 0; +} + +int uv_thread_getcpu(void) { + return GetCurrentProcessorNumber(); +} uv_thread_t uv_thread_self(void) { uv_thread_t key; @@ -374,6 +449,7 @@ void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) { abort(); } + int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { if (SleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6))) return 0; @@ -383,69 +459,6 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { } -int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { - int err; - - barrier->n = count; - barrier->count = 0; - - err = uv_mutex_init(&barrier->mutex); - if (err) - return err; - - err = uv_sem_init(&barrier->turnstile1, 0); - if (err) - goto error2; - - err = uv_sem_init(&barrier->turnstile2, 1); - if (err) - goto error; - - return 0; - -error: - uv_sem_destroy(&barrier->turnstile1); -error2: - uv_mutex_destroy(&barrier->mutex); - return err; - -} - - -void uv_barrier_destroy(uv_barrier_t* barrier) { - uv_sem_destroy(&barrier->turnstile2); - uv_sem_destroy(&barrier->turnstile1); - uv_mutex_destroy(&barrier->mutex); -} - - -int uv_barrier_wait(uv_barrier_t* barrier) { - int serial_thread; - - uv_mutex_lock(&barrier->mutex); - if (++barrier->count == barrier->n) { - uv_sem_wait(&barrier->turnstile2); - uv_sem_post(&barrier->turnstile1); - } - uv_mutex_unlock(&barrier->mutex); - - uv_sem_wait(&barrier->turnstile1); - uv_sem_post(&barrier->turnstile1); - - uv_mutex_lock(&barrier->mutex); - serial_thread = (--barrier->count == 0); - if (serial_thread) { - uv_sem_wait(&barrier->turnstile1); - uv_sem_post(&barrier->turnstile2); - } - uv_mutex_unlock(&barrier->mutex); - - uv_sem_wait(&barrier->turnstile2); - uv_sem_post(&barrier->turnstile2); - return serial_thread; -} - - int uv_key_create(uv_key_t* key) { key->tls_index = TlsAlloc(); if (key->tls_index == TLS_OUT_OF_INDEXES) diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/tty.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/tty.cpp index 9753784dc01..9bb3d9e830c 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/win/tty.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/win/tty.cpp @@ -25,12 +25,7 @@ #include #include #include - -#if defined(_MSC_VER) && _MSC_VER < 1600 -# include "uv/stdint-msvc2008.h" -#else -# include -#endif +#include #ifndef COMMON_LVB_REVERSE_VIDEO # define COMMON_LVB_REVERSE_VIDEO 0x4000 @@ -179,14 +174,14 @@ void uv__console_init(void) { 0); if (uv__tty_console_handle != INVALID_HANDLE_VALUE) { CONSOLE_SCREEN_BUFFER_INFO sb_info; - QueueUserWorkItem(uv__tty_console_resize_message_loop_thread, - NULL, - WT_EXECUTELONGFUNCTION); uv_mutex_init(&uv__tty_console_resize_mutex); if (GetConsoleScreenBufferInfo(uv__tty_console_handle, &sb_info)) { uv__tty_console_width = sb_info.dwSize.X; uv__tty_console_height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1; } + QueueUserWorkItem(uv__tty_console_resize_message_loop_thread, + NULL, + WT_EXECUTELONGFUNCTION); } } @@ -2243,11 +2238,11 @@ void uv__process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle, handle->stream.conn.write_reqs_pending--; - if (handle->stream.conn.write_reqs_pending == 0) - if (handle->flags & UV_HANDLE_SHUTTING) - uv__process_tty_shutdown_req(loop, - handle, - handle->stream.conn.shutdown_req); + if (handle->stream.conn.write_reqs_pending == 0 && + uv__is_stream_shutting(handle)) + uv__process_tty_shutdown_req(loop, + handle, + handle->stream.conn.shutdown_req); DECREASE_PENDING_REQ_COUNT(handle); } @@ -2278,7 +2273,6 @@ void uv__process_tty_shutdown_req(uv_loop_t* loop, uv_tty_t* stream, uv_shutdown assert(req); stream->stream.conn.shutdown_req = NULL; - stream->flags &= ~UV_HANDLE_SHUTTING; UNREGISTER_HANDLE_REQ(loop, stream, req); /* TTY shutdown is really just a no-op */ @@ -2308,26 +2302,6 @@ void uv__tty_endgame(uv_loop_t* loop, uv_tty_t* handle) { } -/* - * uv__process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working - * TODO: find a way to remove it - */ -void uv__process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle, - uv_req_t* raw_req) { - abort(); -} - - -/* - * uv__process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working - * TODO: find a way to remove it - */ -void uv__process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle, - uv_connect_t* req) { - abort(); -} - - int uv_tty_reset_mode(void) { /* Not necessary to do anything. */ return 0; @@ -2433,7 +2407,6 @@ static void uv__tty_console_signal_resize(void) { height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1; uv_mutex_lock(&uv__tty_console_resize_mutex); - assert(uv__tty_console_width != -1 && uv__tty_console_height != -1); if (width != uv__tty_console_width || height != uv__tty_console_height) { uv__tty_console_width = width; uv__tty_console_height = height; diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/udp.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/udp.cpp index eaebc1eda8f..eab53842d4f 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/win/udp.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/win/udp.cpp @@ -29,11 +29,6 @@ #include "req-inl.h" -/* - * Threshold of active udp streams for which to preallocate udp read buffers. - */ -const unsigned int uv_active_udp_streams_threshold = 0; - /* A zero-size buffer for use by uv_udp_read */ static char uv_zero_[] = ""; int uv_udp_getpeername(const uv_udp_t* handle, @@ -151,14 +146,14 @@ int uv__udp_init_ex(uv_loop_t* loop, sock = socket(domain, SOCK_DGRAM, 0); if (sock == INVALID_SOCKET) { err = WSAGetLastError(); - QUEUE_REMOVE(&handle->handle_queue); + uv__queue_remove(&handle->handle_queue); return uv_translate_sys_error(err); } err = uv__udp_set_socket(handle->loop, handle, sock, domain); if (err) { closesocket(sock); - QUEUE_REMOVE(&handle->handle_queue); + uv__queue_remove(&handle->handle_queue); return uv_translate_sys_error(err); } } @@ -276,84 +271,35 @@ static void uv__udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) { req = &handle->recv_req; memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); - /* - * Preallocate a read buffer if the number of active streams is below - * the threshold. - */ - if (loop->active_udp_streams < uv_active_udp_streams_threshold) { - handle->flags &= ~UV_HANDLE_ZERO_READ; - - handle->recv_buffer = uv_buf_init(NULL, 0); - handle->alloc_cb((uv_handle_t*) handle, UV__UDP_DGRAM_MAXSIZE, &handle->recv_buffer); - if (handle->recv_buffer.base == NULL || handle->recv_buffer.len == 0) { - handle->recv_cb(handle, UV_ENOBUFS, &handle->recv_buffer, NULL, 0); - return; - } - assert(handle->recv_buffer.base != NULL); - - buf = handle->recv_buffer; - memset(&handle->recv_from, 0, sizeof handle->recv_from); - handle->recv_from_len = sizeof handle->recv_from; - flags = 0; - - result = handle->func_wsarecvfrom(handle->socket, - (WSABUF*) &buf, - 1, - &bytes, - &flags, - (struct sockaddr*) &handle->recv_from, - &handle->recv_from_len, - &req->u.io.overlapped, - NULL); - - if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { - /* Process the req without IOCP. */ - handle->flags |= UV_HANDLE_READ_PENDING; - req->u.io.overlapped.InternalHigh = bytes; - handle->reqs_pending++; - uv__insert_pending_req(loop, req); - } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { - /* The req will be processed with IOCP. */ - handle->flags |= UV_HANDLE_READ_PENDING; - handle->reqs_pending++; - } else { - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(req, WSAGetLastError()); - uv__insert_pending_req(loop, req); - handle->reqs_pending++; - } + handle->flags |= UV_HANDLE_ZERO_READ; + + buf.base = (char*) uv_zero_; + buf.len = 0; + flags = MSG_PEEK; + result = handle->func_wsarecv(handle->socket, + (WSABUF*) &buf, + 1, + &bytes, + &flags, + &req->u.io.overlapped, + NULL); + + if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { + /* Process the req without IOCP. */ + handle->flags |= UV_HANDLE_READ_PENDING; + req->u.io.overlapped.InternalHigh = bytes; + handle->reqs_pending++; + uv__insert_pending_req(loop, req); + } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { + /* The req will be processed with IOCP. */ + handle->flags |= UV_HANDLE_READ_PENDING; + handle->reqs_pending++; } else { - handle->flags |= UV_HANDLE_ZERO_READ; - - buf.base = (char*) uv_zero_; - buf.len = 0; - flags = MSG_PEEK; - - result = handle->func_wsarecv(handle->socket, - (WSABUF*) &buf, - 1, - &bytes, - &flags, - &req->u.io.overlapped, - NULL); - - if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { - /* Process the req without IOCP. */ - handle->flags |= UV_HANDLE_READ_PENDING; - req->u.io.overlapped.InternalHigh = bytes; - handle->reqs_pending++; - uv__insert_pending_req(loop, req); - } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { - /* The req will be processed with IOCP. */ - handle->flags |= UV_HANDLE_READ_PENDING; - handle->reqs_pending++; - } else { - /* Make this req pending reporting an error. */ - SET_REQ_ERROR(req, WSAGetLastError()); - uv__insert_pending_req(loop, req); - handle->reqs_pending++; - } + /* Make this req pending reporting an error. */ + SET_REQ_ERROR(req, WSAGetLastError()); + uv__insert_pending_req(loop, req); + handle->reqs_pending++; } } @@ -376,7 +322,6 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, handle->flags |= UV_HANDLE_READING; INCREASE_ACTIVE_COUNT(loop, handle); - loop->active_udp_streams++; handle->recv_cb = recv_cb; handle->alloc_cb = alloc_cb; @@ -393,7 +338,6 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, int uv__udp_recv_stop(uv_udp_t* handle) { if (handle->flags & UV_HANDLE_READING) { handle->flags &= ~UV_HANDLE_READING; - handle->loop->active_udp_streams--; DECREASE_ACTIVE_COUNT(loop, handle); } @@ -497,57 +441,68 @@ void uv__process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, DWORD bytes, err, flags; struct sockaddr_storage from; int from_len; + int count; + + /* Prevent loop starvation when the data comes in as fast as + * (or faster than) we can read it. */ + count = 32; + + do { + /* Do at most `count` nonblocking receive. */ + buf = uv_buf_init(NULL, 0); + handle->alloc_cb((uv_handle_t*) handle, UV__UDP_DGRAM_MAXSIZE, &buf); + if (buf.base == NULL || buf.len == 0) { + handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0); + goto done; + } - /* Do a nonblocking receive. - * TODO: try to read multiple datagrams at once. FIONREAD maybe? */ - buf = uv_buf_init(NULL, 0); - handle->alloc_cb((uv_handle_t*) handle, UV__UDP_DGRAM_MAXSIZE, &buf); - if (buf.base == NULL || buf.len == 0) { - handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0); - goto done; - } - assert(buf.base != NULL); - - memset(&from, 0, sizeof from); - from_len = sizeof from; + memset(&from, 0, sizeof from); + from_len = sizeof from; - flags = 0; + flags = 0; - if (WSARecvFrom(handle->socket, - (WSABUF*)&buf, - 1, - &bytes, - &flags, - (struct sockaddr*) &from, - &from_len, - NULL, - NULL) != SOCKET_ERROR) { + if (WSARecvFrom(handle->socket, + (WSABUF*)&buf, + 1, + &bytes, + &flags, + (struct sockaddr*) &from, + &from_len, + NULL, + NULL) != SOCKET_ERROR) { - /* Message received */ - handle->recv_cb(handle, bytes, &buf, (const struct sockaddr*) &from, 0); - } else { - err = WSAGetLastError(); - if (err == WSAEMSGSIZE) { - /* Message truncated */ - handle->recv_cb(handle, - bytes, - &buf, - (const struct sockaddr*) &from, - UV_UDP_PARTIAL); - } else if (err == WSAEWOULDBLOCK) { - /* Kernel buffer empty */ - handle->recv_cb(handle, 0, &buf, NULL, 0); - } else if (err == WSAECONNRESET || err == WSAENETRESET) { - /* WSAECONNRESET/WSANETRESET is ignored because this just indicates - * that a previous sendto operation failed. - */ - handle->recv_cb(handle, 0, &buf, NULL, 0); + /* Message received */ + err = ERROR_SUCCESS; + handle->recv_cb(handle, bytes, &buf, (const struct sockaddr*) &from, 0); } else { - /* Any other error that we want to report back to the user. */ - uv_udp_recv_stop(handle); - handle->recv_cb(handle, uv_translate_sys_error(err), &buf, NULL, 0); + err = WSAGetLastError(); + if (err == WSAEMSGSIZE) { + /* Message truncated */ + handle->recv_cb(handle, + bytes, + &buf, + (const struct sockaddr*) &from, + UV_UDP_PARTIAL); + } else if (err == WSAEWOULDBLOCK) { + /* Kernel buffer empty */ + handle->recv_cb(handle, 0, &buf, NULL, 0); + } else if (err == WSAECONNRESET || err == WSAENETRESET) { + /* WSAECONNRESET/WSANETRESET is ignored because this just indicates + * that a previous sendto operation failed. + */ + handle->recv_cb(handle, 0, &buf, NULL, 0); + } else { + /* Any other error that we want to report back to the user. */ + uv_udp_recv_stop(handle); + handle->recv_cb(handle, uv_translate_sys_error(err), &buf, NULL, 0); + } } } + while (err == ERROR_SUCCESS && + count-- > 0 && + /* The recv_cb callback may decide to pause or close the handle. */ + (handle->flags & UV_HANDLE_READING) && + !(handle->flags & UV_HANDLE_READ_PENDING)); } done: diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/util.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/util.cpp index d9888aec795..55ca35d3169 100644 --- a/wpinet/src/main/native/thirdparty/libuv/src/win/util.cpp +++ b/wpinet/src/main/native/thirdparty/libuv/src/win/util.cpp @@ -129,9 +129,6 @@ int uv_exepath(char* buffer, size_t* size_ptr) { goto error; } - /* utf16_len contains the length, *not* including the terminating null. */ - utf16_buffer[utf16_len] = L'\0'; - /* Convert to UTF-8 */ utf8_len = WideCharToMultiByte(CP_UTF8, 0, @@ -159,6 +156,51 @@ int uv_exepath(char* buffer, size_t* size_ptr) { } +static int uv__cwd(WCHAR** buf, DWORD *len) { + WCHAR* p; + DWORD n; + DWORD t; + + t = GetCurrentDirectoryW(0, NULL); + for (;;) { + if (t == 0) + return uv_translate_sys_error(GetLastError()); + + /* |t| is the size of the buffer _including_ nul. */ + p = (WCHAR *)uv__malloc(t * sizeof(*p)); + if (p == NULL) + return UV_ENOMEM; + + /* |n| is the size of the buffer _excluding_ nul but _only on success_. + * If |t| was too small because another thread changed the working + * directory, |n| is the size the buffer should be _including_ nul. + * It therefore follows we must resize when n >= t and fail when n == 0. + */ + n = GetCurrentDirectoryW(t, p); + if (n > 0) + if (n < t) + break; + + uv__free(p); + t = n; + } + + /* The returned directory should not have a trailing slash, unless it points + * at a drive root, like c:\. Remove it if needed. + */ + t = n - 1; + if (p[t] == L'\\' && !(n == 3 && p[1] == L':')) { + p[t] = L'\0'; + n = t; + } + + *buf = p; + *len = n; + + return 0; +} + + int uv_cwd(char* buffer, size_t* size) { DWORD utf16_len; WCHAR *utf16_buffer; @@ -168,30 +210,9 @@ int uv_cwd(char* buffer, size_t* size) { return UV_EINVAL; } - utf16_len = GetCurrentDirectoryW(0, NULL); - if (utf16_len == 0) { - return uv_translate_sys_error(GetLastError()); - } - utf16_buffer = (WCHAR*)uv__malloc(utf16_len * sizeof(WCHAR)); - if (utf16_buffer == NULL) { - return UV_ENOMEM; - } - - utf16_len = GetCurrentDirectoryW(utf16_len, utf16_buffer); - if (utf16_len == 0) { - uv__free(utf16_buffer); - return uv_translate_sys_error(GetLastError()); - } - - /* utf16_len contains the length, *not* including the terminating null. */ - utf16_buffer[utf16_len] = L'\0'; - - /* The returned directory should not have a trailing slash, unless it points - * at a drive root, like c:\. Remove it if needed. */ - if (utf16_buffer[utf16_len - 1] == L'\\' && - !(utf16_len == 3 && utf16_buffer[1] == L':')) { - utf16_len--; - utf16_buffer[utf16_len] = L'\0'; + r = uv__cwd(&utf16_buffer, &utf16_len); + if (r < 0) { + return r; } /* Check how much space we need */ @@ -234,8 +255,9 @@ int uv_cwd(char* buffer, size_t* size) { int uv_chdir(const char* dir) { WCHAR *utf16_buffer; - size_t utf16_len, new_utf16_len; + DWORD utf16_len; WCHAR drive_letter, env_var[4]; + int r; if (dir == NULL) { return UV_EINVAL; @@ -270,32 +292,22 @@ int uv_chdir(const char* dir) { return uv_translate_sys_error(GetLastError()); } + /* uv__cwd() will return a new buffer. */ + uv__free(utf16_buffer); + utf16_buffer = NULL; + /* Windows stores the drive-local path in an "hidden" environment variable, * which has the form "=C:=C:\Windows". SetCurrentDirectory does not update * this, so we'll have to do it. */ - new_utf16_len = GetCurrentDirectoryW(utf16_len, utf16_buffer); - if (new_utf16_len > utf16_len ) { - uv__free(utf16_buffer); - utf16_buffer = (WCHAR*)uv__malloc(new_utf16_len * sizeof(WCHAR)); - if (utf16_buffer == NULL) { - /* When updating the environment variable fails, return UV_OK anyway. - * We did successfully change current working directory, only updating - * hidden env variable failed. */ - return 0; - } - new_utf16_len = GetCurrentDirectoryW(new_utf16_len, utf16_buffer); - } - if (utf16_len == 0) { - uv__free(utf16_buffer); + r = uv__cwd(&utf16_buffer, &utf16_len); + if (r == UV_ENOMEM) { + /* When updating the environment variable fails, return UV_OK anyway. + * We did successfully change current working directory, only updating + * hidden env variable failed. */ return 0; } - - /* The returned directory should not have a trailing slash, unless it points - * at a drive root, like c:\. Remove it if needed. */ - if (utf16_buffer[utf16_len - 1] == L'\\' && - !(utf16_len == 3 && utf16_buffer[1] == L':')) { - utf16_len--; - utf16_buffer[utf16_len] = L'\0'; + if (r < 0) { + return r; } if (utf16_len < 2 || utf16_buffer[1] != L':') { @@ -338,7 +350,7 @@ uint64_t uv_get_free_memory(void) { memory_status.dwLength = sizeof(memory_status); if (!GlobalMemoryStatusEx(&memory_status)) { - return -1; + return 0; } return (uint64_t)memory_status.ullAvailPhys; @@ -350,7 +362,7 @@ uint64_t uv_get_total_memory(void) { memory_status.dwLength = sizeof(memory_status); if (!GlobalMemoryStatusEx(&memory_status)) { - return -1; + return 0; } return (uint64_t)memory_status.ullTotalPhys; @@ -362,6 +374,11 @@ uint64_t uv_get_constrained_memory(void) { } +uint64_t uv_get_available_memory(void) { + return uv_get_free_memory(); +} + + uv_pid_t uv_os_getpid(void) { return GetCurrentProcessId(); } @@ -495,11 +512,43 @@ int uv_get_process_title(char* buffer, size_t size) { } +/* https://github.com/libuv/libuv/issues/1674 */ +int uv_clock_gettime(uv_clock_id clock_id, uv_timespec64_t* ts) { + FILETIME ft; + int64_t t; + + if (ts == NULL) + return UV_EFAULT; + + switch (clock_id) { + case UV_CLOCK_MONOTONIC: + uv__once_init(); + t = uv__hrtime(UV__NANOSEC); + ts->tv_sec = t / 1000000000; + ts->tv_nsec = t % 1000000000; + return 0; + case UV_CLOCK_REALTIME: + GetSystemTimePreciseAsFileTime(&ft); + /* In 100-nanosecond increments from 1601-01-01 UTC because why not? */ + t = (int64_t) ft.dwHighDateTime << 32 | ft.dwLowDateTime; + /* Convert to UNIX epoch, 1970-01-01. Still in 100 ns increments. */ + t -= 116444736000000000ll; + /* Now convert to seconds and nanoseconds. */ + ts->tv_sec = t / 10000000; + ts->tv_nsec = t % 10000000 * 100; + return 0; + } + + return UV_EINVAL; +} + + uint64_t uv_hrtime(void) { uv__once_init(); return uv__hrtime(UV__NANOSEC); } + uint64_t uv__hrtime(unsigned int scale) { LARGE_INTEGER counter; double scaled_freq; @@ -686,71 +735,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) { } -static int is_windows_version_or_greater(DWORD os_major, - DWORD os_minor, - WORD service_pack_major, - WORD service_pack_minor) { - OSVERSIONINFOEX osvi; - DWORDLONG condition_mask = 0; - int op = VER_GREATER_EQUAL; - - /* Initialize the OSVERSIONINFOEX structure. */ - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - osvi.dwMajorVersion = os_major; - osvi.dwMinorVersion = os_minor; - osvi.wServicePackMajor = service_pack_major; - osvi.wServicePackMinor = service_pack_minor; - - /* Initialize the condition mask. */ - VER_SET_CONDITION(condition_mask, VER_MAJORVERSION, op); - VER_SET_CONDITION(condition_mask, VER_MINORVERSION, op); - VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMAJOR, op); - VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMINOR, op); - - /* Perform the test. */ - return (int) VerifyVersionInfo( - &osvi, - VER_MAJORVERSION | VER_MINORVERSION | - VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, - condition_mask); -} - - -static int address_prefix_match(int family, - struct sockaddr* address, - struct sockaddr* prefix_address, - int prefix_len) { - uint8_t* address_data; - uint8_t* prefix_address_data; - int i; - - assert(address->sa_family == family); - assert(prefix_address->sa_family == family); - - if (family == AF_INET6) { - address_data = (uint8_t*) &(((struct sockaddr_in6 *) address)->sin6_addr); - prefix_address_data = - (uint8_t*) &(((struct sockaddr_in6 *) prefix_address)->sin6_addr); - } else { - address_data = (uint8_t*) &(((struct sockaddr_in *) address)->sin_addr); - prefix_address_data = - (uint8_t*) &(((struct sockaddr_in *) prefix_address)->sin_addr); - } - - for (i = 0; i < prefix_len >> 3; i++) { - if (address_data[i] != prefix_address_data[i]) - return 0; - } - - if (prefix_len % 8) - return prefix_address_data[i] == - (address_data[i] & (0xff << (8 - prefix_len % 8))); - - return 1; -} - - int uv_interface_addresses(uv_interface_address_t** addresses_ptr, int* count_ptr) { IP_ADAPTER_ADDRESSES* win_address_buf; @@ -763,26 +747,13 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, uv_interface_address_t* uv_address; int count; - - int is_vista_or_greater; ULONG flags; *addresses_ptr = NULL; *count_ptr = 0; - is_vista_or_greater = is_windows_version_or_greater(6, 0, 0, 0); - if (is_vista_or_greater) { - flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | - GAA_FLAG_SKIP_DNS_SERVER; - } else { - /* We need at least XP SP1. */ - if (!is_windows_version_or_greater(5, 1, 1, 0)) - return UV_ENOTSUP; - - flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | - GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_PREFIX; - } - + flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | + GAA_FLAG_SKIP_DNS_SERVER; /* Fetch the size of the adapters reported by windows, and then get the list * itself. */ @@ -947,37 +918,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, sa = unicast_address->Address.lpSockaddr; - /* XP has no OnLinkPrefixLength field. */ - if (is_vista_or_greater) { - prefix_len = - ((IP_ADAPTER_UNICAST_ADDRESS_LH*) unicast_address)->OnLinkPrefixLength; - } else { - /* Prior to Windows Vista the FirstPrefix pointed to the list with - * single prefix for each IP address assigned to the adapter. - * Order of FirstPrefix does not match order of FirstUnicastAddress, - * so we need to find corresponding prefix. - */ - IP_ADAPTER_PREFIX* prefix; - prefix_len = 0; - - for (prefix = adapter->FirstPrefix; prefix; prefix = prefix->Next) { - /* We want the longest matching prefix. */ - if (prefix->Address.lpSockaddr->sa_family != sa->sa_family || - prefix->PrefixLength <= prefix_len) - continue; - - if (address_prefix_match(sa->sa_family, sa, - prefix->Address.lpSockaddr, prefix->PrefixLength)) { - prefix_len = prefix->PrefixLength; - } - } - - /* If there is no matching prefix information, return a single-host - * subnet mask (e.g. 255.255.255.255 for IPv4). - */ - if (!prefix_len) - prefix_len = (sa->sa_family == AF_INET6) ? 128 : 32; - } + prefix_len = + ((IP_ADAPTER_UNICAST_ADDRESS_LH*) unicast_address)->OnLinkPrefixLength; memset(uv_address, 0, sizeof *uv_address); @@ -1102,8 +1044,8 @@ int uv_os_homedir(char* buffer, size_t* size) { if (r != UV_ENOENT) return r; - /* USERPROFILE is not set, so call uv__getpwuid_r() */ - r = uv__getpwuid_r(&pwd); + /* USERPROFILE is not set, so call uv_os_get_passwd() */ + r = uv_os_get_passwd(&pwd); if (r != 0) { return r; @@ -1190,17 +1132,6 @@ int uv_os_tmpdir(char* buffer, size_t* size) { } -void uv_os_free_passwd(uv_passwd_t* pwd) { - if (pwd == NULL) - return; - - uv__free(pwd->username); - uv__free(pwd->homedir); - pwd->username = NULL; - pwd->homedir = NULL; -} - - /* * Converts a UTF-16 string into a UTF-8 one. The resulting string is * null-terminated. @@ -1297,7 +1228,7 @@ int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16) { } -int uv__getpwuid_r(uv_passwd_t* pwd) { +static int uv__getpwuid_r(uv_passwd_t* pwd) { HANDLE token; wchar_t username[UNLEN + 1]; wchar_t *path; @@ -1375,6 +1306,16 @@ int uv_os_get_passwd(uv_passwd_t* pwd) { } +int uv_os_get_passwd2(uv_passwd_t* pwd, uv_uid_t uid) { + return UV_ENOTSUP; +} + + +int uv_os_get_group(uv_group_t* grp, uv_uid_t gid) { + return UV_ENOTSUP; +} + + int uv_os_environ(uv_env_item_t** envitems, int* count) { wchar_t* env; wchar_t* penv; @@ -1778,6 +1719,22 @@ int uv_os_uname(uv_utsname_t* buffer) { RegCloseKey(registry_key); if (r == ERROR_SUCCESS) { + /* Windows 11 shares dwMajorVersion with Windows 10 + * this workaround tries to disambiguate that by checking + * if the dwBuildNumber is from Windows 11 releases (>= 22000). + * + * This workaround replaces the ProductName key value + * from "Windows 10 *" to "Windows 11 *" */ + if (os_info.dwMajorVersion == 10 && + os_info.dwBuildNumber >= 22000 && + product_name_w_size >= ARRAY_SIZE(L"Windows 10")) { + /* If ProductName starts with "Windows 10" */ + if (wcsncmp(product_name_w, L"Windows 10", ARRAY_SIZE(L"Windows 10") - 1) == 0) { + /* Bump 10 to 11 */ + product_name_w[9] = '1'; + } + } + version_size = WideCharToMultiByte(CP_UTF8, 0, product_name_w,