[前][次][番号順一覧][スレッド一覧]

ruby-changes:52320

From: normal <ko1@a...>
Date: Sat, 25 Aug 2018 04:19:11 +0900 (JST)
Subject: [ruby-changes:52320] normal:r64527 (trunk): thread_pthread.c: use eventfd instead of pipe on Linux

normal	2018-08-25 04:19:01 +0900 (Sat, 25 Aug 2018)

  New Revision: 64527

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=64527

  Log:
    thread_pthread.c: use eventfd instead of pipe on Linux
    
    Based on r64478, any regular user creating more than 1024 pipes
    on Linux will end up with tiny pipes with only a single page
    capacity.  So avoid wasting user resources and use lighter
    eventfd on Linux.
    
    [ruby-core:88563] [Misc #15011]

  Modified files:
    trunk/configure.ac
    trunk/thread.c
    trunk/thread_pthread.c
Index: configure.ac
===================================================================
--- configure.ac	(revision 64526)
+++ configure.ac	(revision 64527)
@@ -983,6 +983,7 @@ AC_CHECK_HEADERS(pwd.h) https://github.com/ruby/ruby/blob/trunk/configure.ac#L983
 AC_CHECK_HEADERS(setjmpex.h)
 AC_CHECK_HEADERS(stdalign.h)
 AC_CHECK_HEADERS(sys/attr.h)
+AC_CHECK_HEADERS(sys/eventfd.h)
 AC_CHECK_HEADERS(sys/fcntl.h)
 AC_CHECK_HEADERS(sys/file.h)
 AC_CHECK_HEADERS(sys/id.h)
@@ -1755,6 +1756,7 @@ AC_CHECK_FUNCS(dup) https://github.com/ruby/ruby/blob/trunk/configure.ac#L1756
 AC_CHECK_FUNCS(dup3)
 AC_CHECK_FUNCS(eaccess)
 AC_CHECK_FUNCS(endgrent)
+AC_CHECK_FUNCS(eventfd)
 AC_CHECK_FUNCS(fchmod)
 AC_CHECK_FUNCS(fchown)
 AC_CHECK_FUNCS(fcntl)
Index: thread_pthread.c
===================================================================
--- thread_pthread.c	(revision 64526)
+++ thread_pthread.c	(revision 64527)
@@ -37,6 +37,13 @@ https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L37
 #include <time.h>
 #include <signal.h>
 
+#if defined(HAVE_SYS_EVENTFD_H) && defined(HAVE_EVENTFD)
+#  define USE_EVENTFD (1)
+#  include <sys/eventfd.h>
+#else
+#  define USE_EVENTFD (0)
+#endif
+
 #if defined(SIGVTALRM) && !defined(__CYGWIN__)
 #  define USE_UBF_LIST 1
 #endif
@@ -1386,13 +1393,17 @@ static struct { https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1393
 static void
 rb_thread_wakeup_timer_thread_fd(int fd)
 {
+#if USE_EVENTFD
+    const uint64_t buff = 1;
+#else
+    const char buff = '!';
+#endif
     ssize_t result;
 
     /* already opened */
     if (fd >= 0) {
-	static const char buff[1] = {'!'};
       retry:
-	if ((result = write(fd, buff, 1)) <= 0) {
+	if ((result = write(fd, &buff, sizeof(buff))) <= 0) {
 	    int e = errno;
 	    switch (e) {
 	      case EINTR: goto retry;
@@ -1505,8 +1516,8 @@ rb_thread_wakeup_timer_thread(int sig) https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1516
     }
 }
 
-#define CLOSE_INVALIDATE(expr) \
-    close_invalidate(&expr,"close_invalidate: "#expr)
+#define CLOSE_INVALIDATE_PAIR(expr) \
+    close_invalidate_pair(expr,"close_invalidate: "#expr)
 static void
 close_invalidate(int *fdp, const char *msg)
 {
@@ -1519,6 +1530,19 @@ close_invalidate(int *fdp, const char *m https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1530
 }
 
 static void
+close_invalidate_pair(int fds[2], const char *msg)
+{
+    if (USE_EVENTFD && fds[0] == fds[1]) {
+        close_invalidate(&fds[0], msg);
+        fds[1] = -1;
+    }
+    else {
+        close_invalidate(&fds[0], msg);
+        close_invalidate(&fds[1], msg);
+    }
+}
+
+static void
 set_nonblock(int fd)
 {
     int oflags;
@@ -1545,6 +1569,18 @@ setup_communication_pipe_internal(int pi https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1569
         return 0;
     }
 
+    /*
+     * Don't bother with eventfd on ancient Linux 2.6.22..2.6.26 which were
+     * missing EFD_* flags, they can fall back to pipe
+     */
+#if USE_EVENTFD && defined(EFD_NONBLOCK) && defined(EFD_CLOEXEC)
+    pipes[0] = pipes[1] = eventfd(0, EFD_NONBLOCK|EFD_CLOEXEC);
+    if (pipes[0] >= 0) {
+        rb_update_max_fd(pipes[0]);
+        return 0;
+    }
+#endif
+
     err = rb_cloexec_pipe(pipes);
     if (err != 0) {
 	rb_warn("pipe creation failed for timer: %s, scheduling broken",
@@ -1612,8 +1648,7 @@ static void https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1648
 ubf_timer_invalidate(void)
 {
 #if UBF_TIMER == UBF_TIMER_PTHREAD
-    CLOSE_INVALIDATE(timer_pthread.low[0]);
-    CLOSE_INVALIDATE(timer_pthread.low[1]);
+    CLOSE_INVALIDATE_PAIR(timer_pthread.low);
 #endif
 }
 
@@ -1669,8 +1704,7 @@ rb_thread_create_timer_thread(void) https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1704
     rb_pid_t owner = signal_self_pipe.owner_process;
 
     if (owner && owner != current) {
-        CLOSE_INVALIDATE(signal_self_pipe.normal[0]);
-        CLOSE_INVALIDATE(signal_self_pipe.normal[1]);
+        CLOSE_INVALIDATE_PAIR(signal_self_pipe.normal);
         ubf_timer_invalidate();
     }
 
Index: thread.c
===================================================================
--- thread.c	(revision 64526)
+++ thread.c	(revision 64527)
@@ -398,6 +398,10 @@ ubf_sigwait(void *ignore) https://github.com/ruby/ruby/blob/trunk/thread.c#L398
 #  define BUSY_WAIT_SIGNALS (0)
 #endif
 
+#ifndef USE_EVENTFD
+#  define USE_EVENTFD (0)
+#endif
+
 #if THREAD_DEBUG
 static int debug_mutex_initialized = 1;
 static rb_nativethread_lock_t debug_mutex;
@@ -4271,9 +4275,12 @@ async_bug_fd(const char *mesg, int errno https://github.com/ruby/ruby/blob/trunk/thread.c#L4275
 static int
 consume_communication_pipe(int fd)
 {
-#define CCP_READ_BUFF_SIZE 1024
+#if USE_EVENTFD
+    uint64_t buff[1];
+#else
     /* buffer can be shared because no one refers to them. */
-    static char buff[CCP_READ_BUFF_SIZE];
+    static char buff[1024];
+#endif
     ssize_t result;
     int ret = FALSE; /* for rb_sigwait_sleep */
 
@@ -4289,7 +4296,7 @@ consume_communication_pipe(int fd) https://github.com/ruby/ruby/blob/trunk/thread.c#L4296
 	result = read(fd, buff, sizeof(buff));
 	if (result > 0) {
 	    ret = TRUE;
-	    if (result < (ssize_t)sizeof(buff)) {
+	    if (USE_EVENTFD || result < (ssize_t)sizeof(buff)) {
 		return ret;
 	    }
 	}

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]