diff --git a/SUPPORTED_PLATFORMS.md b/SUPPORTED_PLATFORMS.md index 0c1dd4e2..014ffd1d 100644 --- a/SUPPORTED_PLATFORMS.md +++ b/SUPPORTED_PLATFORMS.md @@ -2,10 +2,10 @@ | System | Support type | Supported versions | Notes | |---|---|---|---| -| GNU/Linux | Tier 1 | Linux >= 2.6.32 with glibc >= 2.12 | | +| GNU/Linux | Tier 1 | Linux >= 3.10 with glibc >= 2.17 | | | macOS | Tier 1 | macOS >= 10.15 | Current and previous macOS release | | Windows | Tier 1 | >= Windows 8 | VS 2015 and later are supported | -| FreeBSD | Tier 1 | >= 10 | | +| FreeBSD | Tier 2 | >= 12 | | | AIX | Tier 2 | >= 6 | Maintainers: @libuv/aix | | IBM i | Tier 2 | >= IBM i 7.2 | Maintainers: @libuv/ibmi | | z/OS | Tier 2 | >= V2R2 | Maintainers: @libuv/zos | diff --git a/src/unix/freebsd.c b/src/unix/freebsd.c index b254b950..191bc8bc 100644 --- a/src/unix/freebsd.c +++ b/src/unix/freebsd.c @@ -269,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/src/unix/internal.h b/src/unix/internal.h index 9f32ebb0..395ba89b 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h @@ -411,22 +411,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); diff --git a/src/unix/linux.c b/src/unix/linux.c index 18dd5029..bbeb283d 100644 --- a/src/unix/linux.c +++ b/src/unix/linux.c @@ -55,22 +55,6 @@ # 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_copy_file_range # if defined(__x86_64__) # define __NR_copy_file_range 326 @@ -1796,89 +1780,3 @@ int uv_fs_event_stop(uv_fs_event_t* handle) { void uv__fs_event_close(uv_fs_event_t* handle) { uv_fs_event_stop(handle); } - - -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 -} - - -static void uv__recvmmsg_unpoison(struct uv__mmsghdr* mmsg, int rc) { - struct uv__mmsghdr* m; - struct msghdr* h; - struct iovec* v; - size_t j; - int i; - - for (i = 0; i < rc; i++) { - m = mmsg + i; - uv__msan_unpoison(m, sizeof(*m)); - - h = &m->msg_hdr; - if (h->msg_name != NULL) - uv__msan_unpoison(h->msg_name, h->msg_namelen); - - if (h->msg_iov != NULL) - uv__msan_unpoison(h->msg_iov, h->msg_iovlen * sizeof(*h->msg_iov)); - - for (j = 0; j < h->msg_iovlen; j++) { - v = h->msg_iov + j; - uv__msan_unpoison(v->iov_base, v->iov_len); - } - - if (h->msg_control != NULL) - uv__msan_unpoison(h->msg_control, h->msg_controllen); - } -} - - -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); - uv__recvmmsg_unpoison(mmsg, rc); - if (rc == -1) - if (errno == EINVAL) - errno = ENOSYS; - - return rc; -#elif defined(__NR_recvmmsg) - int rc; - - rc = syscall(__NR_recvmmsg, fd, mmsg, vlen, /* flags */ 0, /* timeout */ 0); - uv__recvmmsg_unpoison(mmsg, rc); - - return rc; -#else - return errno = ENOSYS, -1; -#endif -} diff --git a/src/unix/udp.c b/src/unix/udp.c index 4d985b88..74a60131 100644 --- a/src/unix/udp.c +++ b/src/unix/udp.c @@ -54,36 +54,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); @@ -183,11 +153,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__) || defined(__FreeBSD_kernel__) + 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 +182,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 +210,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__ || __FreeBSD_kernel__ */ + return UV_ENOSYS; +#endif /* __linux__ || ____FreeBSD__ || __FreeBSD_kernel__ */ } -#endif static void uv__udp_recvmsg(uv_udp_t* handle) { struct sockaddr_storage peer; @@ -268,14 +240,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,11 +281,11 @@ 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__) || defined(__FreeBSD_kernel__) uv_udp_send_t* req; - struct uv__mmsghdr h[UV__MMSG_MAXWIDTH]; - struct uv__mmsghdr *p; + struct mmsghdr h[20]; + struct mmsghdr* p; QUEUE* q; ssize_t npkts; size_t pkts; @@ -326,7 +296,7 @@ static void uv__udp_sendmmsg(uv_udp_t* handle) { write_queue_drain: for (pkts = 0, q = QUEUE_HEAD(&handle->write_queue); - pkts < UV__MMSG_MAXWIDTH && q != &handle->write_queue; + pkts < ARRAY_SIZE(h) && q != &handle->write_queue; ++pkts, q = QUEUE_HEAD(q)) { assert(q != NULL); req = QUEUE_DATA(q, uv_udp_send_t, queue); @@ -355,7 +325,7 @@ write_queue_drain: } 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) { @@ -401,24 +371,12 @@ write_queue_drain: if (!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__ || __FreeBSD_kernel__ */ uv_udp_send_t* req; struct msghdr h; 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); assert(q != NULL); @@ -466,6 +424,7 @@ static void uv__udp_sendmsg(uv_udp_t* handle) { QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue); uv__io_feed(handle->loop, &handle->io_watcher); } +#endif /* __linux__ || ____FreeBSD__ || __FreeBSD_kernel__ */ } /* On the BSDs, SO_REUSEPORT implies SO_REUSEADDR but with some additional @@ -1061,11 +1020,9 @@ int uv__udp_init_ex(uv_loop_t* loop, 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__) || defined(__FreeBSD_kernel__) + if (handle->flags & UV_HANDLE_UDP_RECVMMSG) + return 1; #endif return 0; }