зеркало из https://github.com/github/ruby.git
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:
Родитель
155f3845be
Коммит
0fceffce7e
|
@ -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>
|
||||
|
||||
* test/ruby/test_range.rb: Add test for Range#hash
|
||||
|
|
159
thread.c
159
thread.c
|
@ -368,26 +368,23 @@ static int
|
|||
set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *arg,
|
||||
struct rb_unblock_callback *old, int fail_if_interrupted)
|
||||
{
|
||||
check_ints:
|
||||
if (fail_if_interrupted) {
|
||||
if (RUBY_VM_INTERRUPTED_ANY(th)) {
|
||||
return FALSE;
|
||||
do {
|
||||
if (fail_if_interrupted) {
|
||||
if (RUBY_VM_INTERRUPTED_ANY(th)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
RUBY_VM_CHECK_INTS(th);
|
||||
}
|
||||
}
|
||||
else {
|
||||
RUBY_VM_CHECK_INTS(th);
|
||||
}
|
||||
|
||||
native_mutex_lock(&th->interrupt_lock);
|
||||
if (RUBY_VM_INTERRUPTED_ANY(th)) {
|
||||
native_mutex_unlock(&th->interrupt_lock);
|
||||
goto check_ints;
|
||||
}
|
||||
else {
|
||||
if (old) *old = th->unblock;
|
||||
th->unblock.func = func;
|
||||
th->unblock.arg = arg;
|
||||
}
|
||||
native_mutex_lock(&th->interrupt_lock);
|
||||
} while (RUBY_VM_INTERRUPTED_ANY(th) &&
|
||||
(native_mutex_unlock(&th->interrupt_lock), TRUE));
|
||||
|
||||
if (old) *old = th->unblock;
|
||||
th->unblock.func = func;
|
||||
th->unblock.arg = arg;
|
||||
native_mutex_unlock(&th->interrupt_lock);
|
||||
|
||||
return TRUE;
|
||||
|
@ -3462,6 +3459,32 @@ rb_fd_set(int fd, rb_fdset_t *set)
|
|||
|
||||
#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
|
||||
do_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds,
|
||||
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;
|
||||
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) {
|
||||
limit = timeofday();
|
||||
limit += (double)timeout->tv_sec+(double)timeout->tv_usec*1e-6;
|
||||
|
@ -3489,46 +3519,17 @@ do_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds,
|
|||
if (exceptfds)
|
||||
rb_fd_init_copy(&orig_except, exceptfds);
|
||||
|
||||
retry:
|
||||
lerrno = 0;
|
||||
do {
|
||||
lerrno = 0;
|
||||
|
||||
BLOCKING_REGION({
|
||||
BLOCKING_REGION({
|
||||
result = native_fd_select(n, readfds, writefds, exceptfds,
|
||||
timeout, th);
|
||||
if (result < 0) lerrno = errno;
|
||||
}, ubf_select, th, FALSE);
|
||||
|
||||
RUBY_VM_CHECK_INTS_BLOCKING(th);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
RUBY_VM_CHECK_INTS_BLOCKING(th);
|
||||
} while (result < 0 && retryable(errno = lerrno) && do_select_update());
|
||||
|
||||
if (readfds)
|
||||
rb_fd_term(&orig_read);
|
||||
|
@ -3643,6 +3644,19 @@ ppoll(struct pollfd *fds, nfds_t nfds,
|
|||
}
|
||||
#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
|
||||
*/
|
||||
|
@ -3656,6 +3670,10 @@ rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
|
|||
struct timespec *timeout = NULL;
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
|
||||
#define poll_update() \
|
||||
(update_timespec(timeout, limit), \
|
||||
TRUE)
|
||||
|
||||
if (tv) {
|
||||
ts.tv_sec = tv->tv_sec;
|
||||
ts.tv_nsec = tv->tv_usec * 1000;
|
||||
|
@ -3667,36 +3685,15 @@ rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
|
|||
fds.fd = fd;
|
||||
fds.events = (short)events;
|
||||
|
||||
retry:
|
||||
lerrno = 0;
|
||||
BLOCKING_REGION({
|
||||
result = ppoll(&fds, 1, timeout, NULL);
|
||||
if (result < 0) lerrno = errno;
|
||||
}, ubf_select, th, FALSE);
|
||||
do {
|
||||
lerrno = 0;
|
||||
BLOCKING_REGION({
|
||||
result = ppoll(&fds, 1, timeout, NULL);
|
||||
if (result < 0) lerrno = errno;
|
||||
}, ubf_select, th, FALSE);
|
||||
|
||||
RUBY_VM_CHECK_INTS_BLOCKING(th);
|
||||
|
||||
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;
|
||||
}
|
||||
RUBY_VM_CHECK_INTS_BLOCKING(th);
|
||||
} while (result < 0 && retryable(errno = lerrno) && poll_update());
|
||||
|
||||
if (fds.revents & POLLNVAL) {
|
||||
errno = EBADF;
|
||||
|
|
Загрузка…
Ссылка в новой задаче