aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-05-15 03:49:21 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-05-15 03:49:21 +0000
commit4e09f414fc6e0bdc5cdf6863f5698464ac3e8a7d (patch)
treeecbe2bb6a6c905833c14bb32eee5710ce90bc451
parenta687547a9a2da9f4139ee079bf38c5b452666d14 (diff)
downloadruby-4e09f414fc6e0bdc5cdf6863f5698464ac3e8a7d.tar.gz
thread.c: enable ppoll for FreeBSD 11.0 and later
FreeBSD 11.0+ supports ppoll, so we may use it after accounting for portability differences in how it treats POLLOUT vs POLLHUP events as mutually exclusive (as documented in the FreeBSD poll(2) manpage). For waiting on high-numbered single FDs, this should put FreeBSD on equal footing with Linux and should allow cheaper FD readiness checking with sleepy GC in the future. * thread.c (USE_POLL, POLLERR_SET): define for FreeBSD 11.0+ (rb_wait_for_single_fd): return all requested events on POLLERR_SET io.c (USE_POLL): define for FreeBSD 11.0+ git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63427 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--io.c17
-rw-r--r--thread.c19
2 files changed, 29 insertions, 7 deletions
diff --git a/io.c b/io.c
index 4c724e6166..4c01726c4c 100644
--- a/io.c
+++ b/io.c
@@ -10643,15 +10643,21 @@ maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp)
}
/* non-Linux poll may not work on all FDs */
-#if defined(HAVE_POLL) && defined(__linux__)
-# define USE_POLL 1
-# define IOWAIT_SYSCALL "poll"
-#else
-# define IOWAIT_SYSCALL "select"
+#if defined(HAVE_POLL)
+# if defined(__linux__)
+# define USE_POLL 1
+# endif
+# if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
+# define USE_POLL 1
+# endif
+#endif
+
+#ifndef USE_POLL
# define USE_POLL 0
#endif
#if USE_POLL
+# define IOWAIT_SYSCALL "poll"
STATIC_ASSERT(pollin_expected, POLLIN == RB_WAITFD_IN);
STATIC_ASSERT(pollout_expected, POLLOUT == RB_WAITFD_OUT);
static int
@@ -10665,6 +10671,7 @@ nogvl_wait_for_single_fd(int fd, short events)
return poll(&fds, 1, -1);
}
#else /* !USE_POLL */
+# define IOWAIT_SYSCALL "select"
static int
nogvl_wait_for_single_fd(int fd, short events)
{
diff --git a/thread.c b/thread.c
index 70338bff38..65872971cb 100644
--- a/thread.c
+++ b/thread.c
@@ -206,8 +206,15 @@ vm_living_thread_num(const rb_vm_t *vm)
* one we know of that supports using poll() in all places select()
* would work.
*/
-#if defined(HAVE_POLL) && defined(__linux__)
-# define USE_POLL
+#if defined(HAVE_POLL)
+# if defined(__linux__)
+# define USE_POLL
+# endif
+# if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
+# define USE_POLL
+ /* FreeBSD does not set POLLOUT when POLLHUP happens */
+# define POLLERR_SET (POLLHUP | POLLERR)
+# endif
#endif
static struct timespec *
@@ -3923,6 +3930,10 @@ rb_thread_fd_select(int max, rb_fdset_t * read, rb_fdset_t * write, rb_fdset_t *
#define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR)
#define POLLEX_SET (POLLPRI)
+#ifndef POLLERR_SET /* defined for FreeBSD for now */
+# define POLLERR_SET (0)
+#endif
+
#ifndef HAVE_PPOLL
/* TODO: don't ignore sigmask */
int
@@ -4004,6 +4015,10 @@ rb_wait_for_single_fd(int fd, int events, struct timeval *timeout)
if (fds.revents & POLLEX_SET)
result |= RB_WAITFD_PRI;
+ /* all requested events are ready if there is an error */
+ if (fds.revents & POLLERR_SET)
+ result |= events;
+
return result;
}
#else /* ! USE_POLL - implement rb_io_poll_fd() using select() */