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) { if (sexp_pollfdsp(ctx, pollfds) && sexp_pollfds_num_fds(pollfds) > 0) {
pfds = sexp_pollfds_fds(pollfds); pfds = sexp_pollfds_fds(pollfds);
k = poll(sexp_pollfds_fds(pollfds), sexp_pollfds_num_fds(pollfds), 0); 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) { 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 */ if (pfds[i].revents > 0) { /* free all threads blocked on this fd */
k--; k--;
@ -601,24 +600,10 @@ sexp sexp_scheduler (sexp ctx, sexp self, sexp_sint_t n, sexp root_thread) {
usecs += sexp_context_timeval(res).tv_usec - tval.tv_usec; usecs += sexp_context_timeval(res).tv_usec - tval.tv_usec;
} }
} }
/* either wait on an fd, or just sleep */ /* take a nap to avoid busy looping */
pollfds = sexp_global(ctx, SEXP_G_THREADS_POLL_FDS); usleep(usecs);
if ((sexp_portp(sexp_context_event(res)) || sexp_fixnump(sexp_context_event(res))) sexp_context_waitp(res) = 0;
&& sexp_pollfdsp(ctx, pollfds)) { sexp_context_timeoutp(res) = 1;
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 {
usleep(usecs);
sexp_context_waitp(res) = 0;
sexp_context_timeoutp(res) = 1;
}
} }
sexp_gc_release1(ctx); sexp_gc_release1(ctx);