Simplifying scheduler case where the only available thread is waiting on a port.

Instead of a one-time poll, we just use the default small sleep + loop case,
so we use the normal poll next time through the scheduler.
This fixes a potential case where a lone thread waiting on I/O could hang,
discovered by Lorenzo.
This commit is contained in:
Alex Shinn 2013-01-14 17:59:40 +09:00
parent 4089370373
commit 3e241e3a3e

View file

@ -437,7 +437,6 @@ sexp sexp_scheduler (sexp ctx, sexp self, sexp_sint_t n, sexp root_thread) {
if (sexp_pollfdsp(ctx, pollfds) && sexp_pollfds_num_fds(pollfds) > 0) {
pfds = sexp_pollfds_fds(pollfds);
k = poll(sexp_pollfds_fds(pollfds), sexp_pollfds_num_fds(pollfds), 0);
unblock_io_threads:
for (i=sexp_pollfds_num_fds(pollfds)-1; i>=0 && k>0; --i) {
if (pfds[i].revents > 0) { /* free all threads blocked on this fd */
k--;
@ -601,25 +600,11 @@ sexp sexp_scheduler (sexp ctx, sexp self, sexp_sint_t n, sexp root_thread) {
usecs += sexp_context_timeval(res).tv_usec - tval.tv_usec;
}
}
/* either wait on an fd, or just sleep */
pollfds = sexp_global(ctx, SEXP_G_THREADS_POLL_FDS);
if ((sexp_portp(sexp_context_event(res)) || sexp_fixnump(sexp_context_event(res)))
&& sexp_pollfdsp(ctx, pollfds)) {
if ((k = poll(sexp_pollfds_fds(pollfds), sexp_pollfds_num_fds(pollfds), usecs/1000)) > 0) {
pfds = sexp_pollfds_fds(pollfds);
goto unblock_io_threads;
} else {
/* optimistically unblock this so we have a runnable result */
/* TODO: remove the fd from the pollfds */
sexp_context_waitp(res) = sexp_context_timeoutp(res) = 0;
sexp_context_event(res) = SEXP_FALSE;
}
} else {
/* take a nap to avoid busy looping */
usleep(usecs);
sexp_context_waitp(res) = 0;
sexp_context_timeoutp(res) = 1;
}
}
sexp_gc_release1(ctx);
return res;