* thread.c (do_select): fix to iterate select().

on cygwin/mswin32, iterate in unblocking region.
* thread.c (rb_thread_select): don't iterate on this function.
  (iterate in do_select).



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11722 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ko1 2007-02-14 04:02:12 +00:00
Родитель da06c63c66
Коммит f2586498f3
2 изменённых файлов: 85 добавлений и 91 удалений

Просмотреть файл

@ -1,3 +1,11 @@
Wed Feb 14 12:58:38 2007 Koichi Sasada <ko1@atdot.net>
* thread.c (do_select): fix to iterate select().
on cygwin/mswin32, iterate in unblocking region.
* thread.c (rb_thread_select): don't iterate on this function.
(iterate in do_select).
Wed Feb 14 11:39:18 2007 Koichi Sasada <ko1@atdot.net>
* thread.c (set_unblock_function): fix function interface.

168
thread.c
Просмотреть файл

@ -1641,80 +1641,120 @@ static int
do_select(int n, fd_set *read, fd_set *write, fd_set *except,
struct timeval *timeout)
{
int result, lerrno = 0;
#if defined(__CYGWIN__) || defined(_WIN32)
/* polling port */
int result, lerrno;
fd_set orig_read, orig_write, orig_except;
struct timeval wait_100ms, *wait;
wait_100ms.tv_sec = 0;
wait_100ms.tv_usec = 100 * 1000; /* 100 ms */
wait = (timeout == 0 || cmp_tv(&wait_100ms, timeout) > 0) ? &wait_100ms : timeout;
#ifndef linux
double limit;
struct timeval wait_rest;
do {
if (read) orig_read = *read;
if (write) orig_write = *write;
if (except) orig_except = *except;
if (timeout) {
limit = timeofday() +
(double)timeout->tv_sec+(double)timeout->tv_usec*1e-6;
wait_rest = *timeout;
timeout = &wait_rest;
}
#endif
BLOCKING_REGION({
result = select(n, read, write, except, wait);
if (result < 0) lerrno = errno;
}, 0);
if (read) orig_read = *read;
if (write) orig_write = *write;
if (except) orig_except = *except;
if (result != 0) break;
if (read) *read = orig_read;
if (write) *write = orig_write;
if (except) *except = orig_except;
wait = &wait_100ms;
} while (timeout == 0 || subst(timeout, &wait_100ms));
retry:
lerrno = 0;
#if defined(__CYGWIN__) || defined(_WIN32)
{
/* polling duration: 100ms */
struct timeval wait_100ms, *wait;
wait_100ms.tv_sec = 0;
wait_100ms.tv_usec = 100 * 1000; /* 100 ms */
do {
wait = (timeout == 0 || cmp_tv(&wait_100ms, timeout) > 0) ? &wait_100ms : timeout;
BLOCKING_REGION({
do {
result = select(n, read, write, except, wait);
if (result < 0) lerrno = errno;
if (result != 0) break;
if (read) *read = orig_read;
if (write) *write = orig_write;
if (except) *except = orig_except;
wait = &wait_100ms;
} while (__th->interrupt_flag == 0 && (timeout == 0 || subst(timeout, &wait_100ms)));
}, 0);
} while (result == 0 && (timeout == 0 || subst(timeout, &wait_100ms)));
}
#else
BLOCKING_REGION({
result = select(n, read, write, except, timeout);
if (result < 0) lerrno = errno;
}, ubf_select);
#endif
errno = lerrno;
if (result < 0) {
if (errno == EINTR
#ifdef ERESTART
|| errno == ERESTART
#endif
) {
if (read) *read = orig_read;
if (write) *write = orig_write;
if (except) *except = orig_except;
#ifndef linux
if (timeout) {
double d = limit - timeofday();
wait_rest.tv_sec = (unsigned int)d;
wait_rest.tv_usec = (long)((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;
}
#endif
goto retry;
}
else {
rb_bug("fatal error on select() - errno: %d\n", lerrno);
}
}
return result;
}
static void
rb_thread_wait_fd_rw(int fd, char c)
rb_thread_wait_fd_rw(int fd, int read)
{
int result = 0;
thread_debug("rb_thread_wait_fd_rw (%d, %c)\n", fd, c);
thread_debug("rb_thread_wait_fd_rw(%d, %s)\n", fd, read ? "read" : "write");
while (result <= 0) {
rb_fdset_t set;
rb_fd_init(&set);
FD_SET(fd, &set);
switch(c) {
case 'r':
if (read) {
result = do_select(fd + 1, rb_fd_ptr(&set), 0, 0, 0);
break;
case'w':
}
else {
result = do_select(fd + 1, 0, rb_fd_ptr(&set), 0, 0);
break;
default:
rb_bug("unknown wait type: %c", c);
}
}
thread_debug("rb_thread_wait_fd_rw (%d, %c): done\n", fd, c);
thread_debug("rb_thread_wait_fd_rw(%d, %s): done\n", fd, read ? "read" : "write");
}
void
rb_thread_wait_fd(int fd)
{
rb_thread_wait_fd_rw(fd, 'r');
rb_thread_wait_fd_rw(fd, 1);
}
int
rb_thread_fd_writable(int fd)
{
rb_thread_wait_fd_rw(fd, 'w');
rb_thread_wait_fd_rw(fd, 0);
return Qtrue;
}
@ -1722,13 +1762,6 @@ int
rb_thread_select(int max, fd_set * read, fd_set * write, fd_set * except,
struct timeval *timeout)
{
struct timeval *tvp = timeout;
int n;
#ifndef linux
double limit;
struct timeval tv;
#endif
if (!read && !write && !except) {
if (!timeout) {
rb_thread_sleep_forever();
@ -1737,57 +1770,10 @@ rb_thread_select(int max, fd_set * read, fd_set * write, fd_set * except,
rb_thread_wait_for(*timeout);
return 0;
}
#ifndef linux
if (timeout) {
limit = timeofday() +
(double)timeout->tv_sec + (double)timeout->tv_usec * 1e-6;
else {
return do_select(max, read, write, except, timeout);
}
#endif
#ifndef linux
if (timeout) {
tv = *timeout;
tvp = &tv;
}
#else
tvp = timeout;
#endif
for (;;) {
#ifndef linux
fd_set orig_read, orig_write, orig_except;
if (read) orig_read = *read;
if (write) orig_write = *write;
if (except) orig_except = *except;
#endif
n = do_select(max, read, write, except, tvp);
if (n < 0) {
switch (errno) {
case EINTR:
#ifdef ERESTART
case ERESTART:
#endif
#ifndef linux
if (timeout) {
double d = limit - timeofday();
tv = double2timeval(d);
}
if (read) *read = orig_read;
if (write) *write = orig_write;
if (except) *except = orig_except;
#endif
continue;
default:
break;
}
}
return n;
}
}
/*