thread.c: refactor a loop

* thread.c (do_select): replace switch and goto with a loop to
  suppress maybe-uninitialized warnings by gcc6.
* thread.c (set_unblock_function, rb_wait_for_single_fd): ditto.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51319 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2015-07-21 12:21:35 +00:00
parent 155f3845be
commit 0fceffce7e
2 changed files with 85 additions and 81 deletions

View File

@ -1,3 +1,10 @@
Tue Jul 21 21:21:33 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
* thread.c (do_select): replace switch and goto with a loop to
suppress maybe-uninitialized warnings by gcc6.
* thread.c (set_unblock_function, rb_wait_for_single_fd): ditto.
Tue Jul 21 20:32:33 2015 SHIBATA Hiroshi <hsbt@ruby-lang.org> Tue Jul 21 20:32:33 2015 SHIBATA Hiroshi <hsbt@ruby-lang.org>
* test/ruby/test_range.rb: Add test for Range#hash * test/ruby/test_range.rb: Add test for Range#hash

119
thread.c
View File

@ -368,7 +368,7 @@ static int
set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *arg, set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *arg,
struct rb_unblock_callback *old, int fail_if_interrupted) struct rb_unblock_callback *old, int fail_if_interrupted)
{ {
check_ints: do {
if (fail_if_interrupted) { if (fail_if_interrupted) {
if (RUBY_VM_INTERRUPTED_ANY(th)) { if (RUBY_VM_INTERRUPTED_ANY(th)) {
return FALSE; return FALSE;
@ -379,15 +379,12 @@ set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *arg,
} }
native_mutex_lock(&th->interrupt_lock); native_mutex_lock(&th->interrupt_lock);
if (RUBY_VM_INTERRUPTED_ANY(th)) { } while (RUBY_VM_INTERRUPTED_ANY(th) &&
native_mutex_unlock(&th->interrupt_lock); (native_mutex_unlock(&th->interrupt_lock), TRUE));
goto check_ints;
}
else {
if (old) *old = th->unblock; if (old) *old = th->unblock;
th->unblock.func = func; th->unblock.func = func;
th->unblock.arg = arg; th->unblock.arg = arg;
}
native_mutex_unlock(&th->interrupt_lock); native_mutex_unlock(&th->interrupt_lock);
return TRUE; return TRUE;
@ -3462,6 +3459,32 @@ rb_fd_set(int fd, rb_fdset_t *set)
#endif #endif
static inline int
retryable(int e)
{
if (e == EINTR) return TRUE;
#ifdef ERESTART
if (e == ERESTART) return TRUE;
#endif
return FALSE;
}
#define restore_fdset(fds1, fds2) \
((fds1) ? rb_fd_dup(fds1, fds2) : (void)0)
static inline void
update_timeval(struct timeval *timeout, double limit)
{
if (timeout) {
double d = limit - timeofday();
timeout->tv_sec = (time_t)d;
timeout->tv_usec = (int)((d-(double)timeout->tv_sec)*1e6);
if (timeout->tv_sec < 0) timeout->tv_sec = 0;
if (timeout->tv_usec < 0) timeout->tv_usec = 0;
}
}
static int static int
do_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, do_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds,
rb_fdset_t *exceptfds, struct timeval *timeout) rb_fdset_t *exceptfds, struct timeval *timeout)
@ -3475,6 +3498,13 @@ do_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds,
struct timeval wait_rest; struct timeval wait_rest;
rb_thread_t *th = GET_THREAD(); rb_thread_t *th = GET_THREAD();
#define do_select_update() \
(restore_fdset(readfds, &orig_read), \
restore_fdset(writefds, &orig_write), \
restore_fdset(exceptfds, &orig_except), \
update_timeval(timeout, limit), \
TRUE)
if (timeout) { if (timeout) {
limit = timeofday(); limit = timeofday();
limit += (double)timeout->tv_sec+(double)timeout->tv_usec*1e-6; limit += (double)timeout->tv_sec+(double)timeout->tv_usec*1e-6;
@ -3489,7 +3519,7 @@ do_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds,
if (exceptfds) if (exceptfds)
rb_fd_init_copy(&orig_except, exceptfds); rb_fd_init_copy(&orig_except, exceptfds);
retry: do {
lerrno = 0; lerrno = 0;
BLOCKING_REGION({ BLOCKING_REGION({
@ -3499,36 +3529,7 @@ do_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds,
}, ubf_select, th, FALSE); }, ubf_select, th, FALSE);
RUBY_VM_CHECK_INTS_BLOCKING(th); RUBY_VM_CHECK_INTS_BLOCKING(th);
} while (result < 0 && retryable(errno = lerrno) && do_select_update());
errno = lerrno;
if (result < 0) {
switch (errno) {
case EINTR:
#ifdef ERESTART
case ERESTART:
#endif
if (readfds)
rb_fd_dup(readfds, &orig_read);
if (writefds)
rb_fd_dup(writefds, &orig_write);
if (exceptfds)
rb_fd_dup(exceptfds, &orig_except);
if (timeout) {
double d = limit - timeofday();
wait_rest.tv_sec = (time_t)d;
wait_rest.tv_usec = (int)((d-(double)wait_rest.tv_sec)*1e6);
if (wait_rest.tv_sec < 0) wait_rest.tv_sec = 0;
if (wait_rest.tv_usec < 0) wait_rest.tv_usec = 0;
}
goto retry;
default:
break;
}
}
if (readfds) if (readfds)
rb_fd_term(&orig_read); rb_fd_term(&orig_read);
@ -3643,6 +3644,19 @@ ppoll(struct pollfd *fds, nfds_t nfds,
} }
#endif #endif
static inline void
update_timespec(struct timespec *timeout, double limit)
{
if (timeout) {
double d = limit - timeofday();
timeout->tv_sec = (long)d;
timeout->tv_nsec = (long)((d-(double)timeout->tv_sec)*1e9);
if (timeout->tv_sec < 0) timeout->tv_sec = 0;
if (timeout->tv_nsec < 0) timeout->tv_nsec = 0;
}
}
/* /*
* returns a mask of events * returns a mask of events
*/ */
@ -3656,6 +3670,10 @@ rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
struct timespec *timeout = NULL; struct timespec *timeout = NULL;
rb_thread_t *th = GET_THREAD(); rb_thread_t *th = GET_THREAD();
#define poll_update() \
(update_timespec(timeout, limit), \
TRUE)
if (tv) { if (tv) {
ts.tv_sec = tv->tv_sec; ts.tv_sec = tv->tv_sec;
ts.tv_nsec = tv->tv_usec * 1000; ts.tv_nsec = tv->tv_usec * 1000;
@ -3667,7 +3685,7 @@ rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
fds.fd = fd; fds.fd = fd;
fds.events = (short)events; fds.events = (short)events;
retry: do {
lerrno = 0; lerrno = 0;
BLOCKING_REGION({ BLOCKING_REGION({
result = ppoll(&fds, 1, timeout, NULL); result = ppoll(&fds, 1, timeout, NULL);
@ -3675,28 +3693,7 @@ retry:
}, ubf_select, th, FALSE); }, ubf_select, th, FALSE);
RUBY_VM_CHECK_INTS_BLOCKING(th); RUBY_VM_CHECK_INTS_BLOCKING(th);
} while (result < 0 && retryable(errno = lerrno) && poll_update());
if (result < 0) {
errno = lerrno;
switch (errno) {
case EINTR:
#ifdef ERESTART
case ERESTART:
#endif
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;
}
return -1;
}
if (fds.revents & POLLNVAL) { if (fds.revents & POLLNVAL) {
errno = EBADF; errno = EBADF;