static void _sched_init (void) { int i; for (i = 0; i < MAX_PRIORITY; i++) thread_queue_init (&_runq[i]); thread_queue_init (&_waitq); thread_queue_init (&_deadq); _thread_num_wait = 0; _thread_num_dead = 0; _thread_num_runnable = 0; _thread_num_total = 1; #ifdef EXPIRIMENTAL _timerq = timer_queue_allocate (); timer_queue_update (_timerq, timer_queue_time_elapsed (_timerq)); io_init (); #endif }
/* * This is the idle task, that runs at the lowest possible priority. * It's only called when there are no other fibers ready for scheduling. */ void _fiber_event_loop (void) { /* These are all static, to minimize stack usage */ static fd_set readfds; static fd_set writefds; static int nreadfds; static int nwritefds; static int nfds; static thread_t *thr, *next; static TVAL timeout; static struct timeval tv, *ptv; static int rc; for (;;) { timeout = timer_queue_update (_timerq, timer_queue_time_elapsed (_timerq)); if (_thread_num_runnable) return; FD_ZERO (&readfds); FD_ZERO (&writefds); for (thr = (thread_t *) _waitq.thq_head.thr_next; thr != (thread_t *) &_waitq.thq_head; thr = (thread_t *) thr->thr_hdr.thr_next) { if (thr->thr_nfds) { nreadfds = _fd_set_or (&readfds, &thr->thr_rfds); nwritefds = _fd_set_or (&writefds, &thr->thr_wfds); } } nfds = MAX (nreadfds, nwritefds); if (timeout == 0) ptv = NULL; else { tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; ptv = &tv; } rc = select (nfds, &readfds, &writefds, NULL, ptv); if (rc == -1) { if (errno != EINTR) GPF_T1 ("select() returned -1"); continue; } timer_queue_update (_timerq, timer_queue_time_elapsed (_timerq)); if (rc > 0) { /* Wake up waiting fibers for which an event occurred */ for (thr = (thread_t *) _waitq.thq_head.thr_next; thr != (thread_t *) &_waitq.thq_head; thr = next) { next = (thread_t *) thr->thr_hdr.thr_next; if (thr->thr_nfds == 0) continue; if (_fd_set_intersect (&thr->thr_rfds, &readfds) || _fd_set_intersect (&thr->thr_wfds, &writefds)) { _fd_set_and (&thr->thr_rfds, &readfds); _fd_set_and (&thr->thr_wfds, &writefds); thr->thr_event = NULL; thr->thr_retcode = 1; _fiber_status (thr, RUNNABLE); } } } break; } }