From 4a9883e92f856bf7db773e0ddc72f17a8662b75a Mon Sep 17 00:00:00 2001 From: kosaki Date: Fri, 6 May 2011 14:58:38 +0000 Subject: * thread.c (rb_wait_for_single_fd): use ppoll() instead of poll() if possible. based on a patch from Eric Wong. [ruby-core:36003]. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@31450 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 +++++ configure.in | 2 +- thread.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 57 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index fbde80a1db..1c86367fbb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Fri May 6 23:29:47 2011 KOSAKI Motohiro + + * 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 * configure.in: remove nanosleep check. we no longer use it. diff --git a/configure.in b/configure.in index 4520fb23e3..2de22a3f7d 100644 --- a/configure.in +++ b/configure.in @@ -1310,7 +1310,7 @@ AC_CHECK_FUNCS(fmod killpg wait4 waitpid fork spawnv syscall __syscall chroot ge 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, diff --git a/thread.c b/thread.c index 1a3dabeb96..ed22e68030 100644 --- a/thread.c +++ b/thread.c @@ -2715,12 +2715,41 @@ rb_thread_fd_select(int max, rb_fdset_t * read, rb_fdset_t * write, rb_fdset_t * #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 @@ rb_wait_for_single_fd(int fd, int events, struct timeval *tv) { 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 @@ retry: #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; } -- cgit v1.2.3