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

ruby-changes:19410

From: kosaki <ko1@a...>
Date: Fri, 6 May 2011 23:59:18 +0900 (JST)
Subject: [ruby-changes:19410] Ruby:r31450 (trunk): * thread.c (rb_wait_for_single_fd): use ppoll() instead of poll()

kosaki	2011-05-06 23:58:38 +0900 (Fri, 06 May 2011)

  New Revision: 31450

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=31450

  Log:
    * thread.c (rb_wait_for_single_fd): use ppoll() instead of poll()
      if possible. based on a patch from Eric Wong. [ruby-core:36003].

  Modified files:
    trunk/ChangeLog
    trunk/configure.in
    trunk/thread.c

Index: configure.in
===================================================================
--- configure.in	(revision 31449)
+++ configure.in	(revision 31450)
@@ -1310,7 +1310,7 @@
 	      dlopen sigprocmask sigaction sigsetjmp _setjmp _longjmp\
 	      setsid telldir seekdir fchmod cosh sinh tanh log2 round\
 	      setuid setgid daemon select_large_fdset setenv unsetenv\
-              mktime timegm gmtime_r clock_gettime gettimeofday poll\
+              mktime timegm gmtime_r clock_gettime gettimeofday poll ppoll\
               pread sendfile shutdown sigaltstack dl_iterate_phdr)
 
 AC_CACHE_CHECK(for unsetenv returns a value, rb_cv_unsetenv_return_value,
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 31449)
+++ ChangeLog	(revision 31450)
@@ -1,3 +1,8 @@
+Fri May  6 23:29:47 2011  KOSAKI Motohiro  <kosaki.motohiro@g...>
+
+	* thread.c (rb_wait_for_single_fd): use ppoll() instead of poll()
+	  if possible. based on a patch from Eric Wong. [ruby-core:36003].
+
 Fri May  6 23:13:43 2011  KOSAKI Motohiro  <kosaki.motohiro@g...>
 
 	* configure.in: remove nanosleep check. we no longer use it.
Index: thread.c
===================================================================
--- thread.c	(revision 31449)
+++ thread.c	(revision 31450)
@@ -2715,12 +2715,41 @@
 
 #ifdef USE_POLL
 
-
 /* The same with linux kernel. TODO: make platform independent definition. */
 #define POLLIN_SET (POLLRDNORM | POLLRDBAND | POLLIN | POLLHUP | POLLERR)
 #define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR)
 #define POLLEX_SET (POLLPRI)
 
+#define TIMET_MAX (~(time_t)0 <= 0 ? (time_t)((~(unsigned_time_t)0) >> 1) : (time_t)(~(unsigned_time_t)0))
+#define TIMET_MIN (~(time_t)0 <= 0 ? (time_t)(((unsigned_time_t)1) << (sizeof(time_t) * CHAR_BIT - 1)) : (time_t)0)
+
+#ifndef HAVE_PPOLL
+/* TODO: don't ignore sigmask */
+int ppoll(struct pollfd *fds, nfds_t nfds,
+	  const struct timespec *ts, const sigset_t *sigmask)
+{
+    int timeout_ms;
+
+    if (ts) {
+	int tmp, tmp2;
+
+	if (ts->tv_sec > TIMET_MAX/1000)
+	    timeout_ms = -1;
+	else {
+	    tmp = ts->tv_sec * 1000;
+	    tmp2 = tv->tv_nsec / (1000 * 1000);
+	    if (TIMET_MAX - tmp < tmp2)
+		timeout_ms = -1;
+	    else
+		timeout_ms = tmp + tmp2;
+	}
+    } else
+	timeout = -1;
+
+    return poll(fds, nfds, timeout_ms);
+}
+#endif
+
 /*
  * returns a mask of events
  */
@@ -2729,17 +2758,25 @@
 {
     struct pollfd fds;
     int result, lerrno;
-    double start;
-    int timeout = tv ? tv->tv_sec * 1000 + (tv->tv_usec + 500) / 1000 : -1;
+    double limit = 0;
+    struct timespec ts;
+    struct timespec *timeout = NULL;
 
+    if (tv) {
+	ts.tv_sec = tv->tv_sec;
+	ts.tv_nsec = tv->tv_usec * 1000;
+	limit = timeofday();
+	limit += (double)tv->tv_sec + (double)tv->tv_usec * 1e-6;
+	timeout = &ts;
+    }
+
     fds.fd = fd;
     fds.events = (short)events;
 
 retry:
     lerrno = 0;
-    start = timeofday();
     BLOCKING_REGION({
-	result = poll(&fds, 1, timeout);
+	result = ppoll(&fds, 1, timeout, NULL);
 	if (result < 0) lerrno = errno;
     }, ubf_select, GET_THREAD());
 
@@ -2750,10 +2787,15 @@
 #ifdef ERESTART
 	  case ERESTART:
 #endif
-	    if (timeout > 0) {
-		timeout -= (timeofday() - start) * 1000;
-		if (timeout < 0)
-		    timeout = 0;
+	    if (timeout) {
+		double d = limit - timeofday();
+
+		ts.tv_sec = (long)d;
+		ts.tv_nsec = (long)((d - (double)ts.tv_sec) * 1e9);
+		if (ts.tv_sec < 0)
+		    ts.tv_sec = 0;
+		if (ts.tv_nsec < 0)
+		    ts.tv_nsec = 0;
 	    }
 	    goto retry;
 	}

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

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