File 0011-thread-use-poll-in-rb_fd_select.patch of Package ruby2.5
From 625148a428926972214b01eee6a01bbdbb7f93ce Mon Sep 17 00:00:00 2001
From: Michal Suchanek <msuchanek@suse.de>
Date: Tue, 4 Feb 2020 19:40:21 +0100
Subject: [PATCH 11/19] thread: use poll() in rb_fd_select
Signed-off-by: Michal Suchanek <msuchanek@suse.de>
---
thread.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 102 insertions(+)
diff --git a/thread.c b/thread.c
index 7d74f0a060f0..980431236c92 100644
--- a/thread.c
+++ b/thread.c
@@ -3630,6 +3630,107 @@ rb_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src)
memcpy(dst->fdset, src->fdset, size);
}
+#if USE_POLL
+struct rb_pollfdset {
+ int n_fds;
+ struct pollfd *fds;
+};
+
+static void
+pollfdset_init(struct rb_pollfdset *pollfdset)
+{
+ memset(pollfdset, 0, sizeof(*pollfdset));
+}
+
+static void
+pollfdset_term(struct rb_pollfdset *pollfdset)
+{
+ pollfdset->fds = xrealloc(pollfdset->fds, 0);
+ pollfdset->n_fds = 0;
+}
+
+static void
+pollfdset_inc(struct rb_pollfdset *pollfdset)
+{
+ pollfdset->fds = xrealloc(pollfdset->fds,sizeof(*pollfdset->fds) * (pollfdset->n_fds + 1));
+ memset(&pollfdset->fds[pollfdset->n_fds], 0, sizeof(*pollfdset->fds));
+ pollfdset->n_fds++;
+}
+
+static int
+pollfdset_get_index(struct rb_pollfdset *pollfdset, int fd)
+{
+ int i;
+
+ for (i = 0; i < pollfdset->n_fds ; i++)
+ if (pollfdset->fds[i].fd == fd)
+ return i;
+ return -1;
+}
+
+static int
+pollfdset_index(struct rb_pollfdset *pollfdset, int fd)
+{
+ int ret = pollfdset_get_index(pollfdset, fd);
+
+ if (ret < 0) {
+ ret = pollfdset->n_fds;
+ pollfdset_inc(pollfdset);
+ pollfdset->fds[ret].fd = fd;
+ }
+ return ret;
+}
+
+static void
+pollfdset_set_flags(struct rb_pollfdset *pollfdset, int fd, int flags)
+{
+ /* this is tricky - fds might get reallocated as a sideeffect of obtaining the index */
+ int idx = pollfdset_index(pollfdset, fd);
+ pollfdset->fds[idx].events |= flags;
+}
+
+static void
+pollfdset_add(struct rb_pollfdset *pollfdset, rb_fdset_t *fds, int flags)
+{
+ int i;
+
+ for (i = 0; i < fds->maxfd ; i++)
+ if (rb_fd_isset(i, fds))
+ pollfdset_set_flags(pollfdset, i, flags);
+}
+
+static void
+pollfdset_extract(struct rb_pollfdset *pollfdset, rb_fdset_t *fds, int flags)
+{
+ int i;
+
+ rb_fd_zero(fds);
+ for (i = 0; i < pollfdset->n_fds; i++)
+ if (pollfdset->fds[i].revents & (flags | POLLERR_SET))
+ rb_fd_set(pollfdset->fds[i].fd, fds);
+}
+
+int
+rb_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *exceptfds, rb_fdset_t *errorfds, struct timeval *timeout)
+{
+ struct rb_pollfdset pollfdset;
+ int timeout_ms = timeout ? timeout->tv_sec * 1000 + timeout->tv_usec / 1000 : -1;
+ int ret;
+
+ pollfdset_init(&pollfdset);
+ if (readfds) pollfdset_add(&pollfdset, readfds, POLLIN_SET);
+ if (writefds) pollfdset_add(&pollfdset, writefds, POLLOUT_SET);
+ if (exceptfds) pollfdset_add(&pollfdset, exceptfds, POLLEX_SET);
+ if (errorfds) pollfdset_add(&pollfdset, errorfds, POLLERR_SET);
+ ret = poll(pollfdset.fds, pollfdset.n_fds, timeout_ms);
+ if (readfds) pollfdset_extract(&pollfdset, readfds, POLLIN_SET);
+ if (writefds) pollfdset_extract(&pollfdset, writefds, POLLOUT_SET);
+ if (exceptfds) pollfdset_extract(&pollfdset, exceptfds, POLLEX_SET);
+ if (errorfds) pollfdset_extract(&pollfdset, errorfds, POLLERR_SET);
+ pollfdset_term(&pollfdset);
+ return ret;
+}
+#else /* USE_POLL */
int
rb_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *exceptfds, rb_fdset_t *errorfds, struct timeval *timeout)
{
@@ -3650,6 +3751,7 @@ rb_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *excep
rb_fd_zero(errorfds);
return select(n, r, w, e, timeout);
}
+#endif /* USE_POLL */
#define rb_fd_no_init(fds) ((void)((fds)->fdset = 0), (void)((fds)->maxfd = 0))
--
2.26.2