/* Fetch next ready thread. */ struct thread * thread_fetch (struct lib_globals *zg, struct thread *fetch) { struct thread_master *m = zg->master; int num; struct thread *thread; struct thread *next; pal_sock_set_t readfd; pal_sock_set_t writefd; pal_sock_set_t exceptfd; struct pal_timeval timer_now; struct pal_timeval timer_val; struct pal_timeval *timer_wait; struct pal_timeval timer_nowait; int i; #ifdef RTOS_DEFAULT_WAIT_TIME /* 1 sec might not be optimized */ timer_nowait.tv_sec = 1; timer_nowait.tv_usec = 0; #else timer_nowait.tv_sec = 0; timer_nowait.tv_usec = 0; #endif /* RTOS_DEFAULT_WAIT_TIME */ /* Set the global VR context to PVR. */ zg->vr_in_cxt = ipi_vr_get_privileged(zg); while (1) { /* Pending read is exception. */ if ((thread = thread_trim_head (&m->read_pend)) != NULL) return thread_run (m, thread, fetch); /* Check ready queue. */ if ((thread = thread_trim_head (&m->queue_high)) != NULL) return thread_run (m, thread, fetch); if ((thread = thread_trim_head (&m->queue_middle)) != NULL) return thread_run (m, thread, fetch); if ((thread = thread_trim_head (&m->queue_low)) != NULL) return thread_run (m, thread, fetch); /* Check all of available events. */ /* Check events. */ while ((thread = thread_trim_head (&m->event)) != NULL) thread_enqueue_high (m, thread); /* Check timer. */ pal_time_tzcurrent (&timer_now, NULL); for (i = 0; i < THREAD_TIMER_SLOT; i++) for (thread = m->timer[i].head; thread; thread = next) { next = thread->next; if (timeval_cmp (timer_now, thread->u.sands) >= 0) { thread_list_delete (&m->timer[i], thread); thread_enqueue_middle (m, thread); } #ifndef TIMER_NO_SORT else break; #endif /* TIMER_NO_SORT */ } /* Structure copy. */ readfd = m->readfd; writefd = m->writefd; exceptfd = m->exceptfd; /* Check any thing to be execute. */ if (m->queue_high.head || m->queue_middle.head || m->queue_low.head) timer_wait = &timer_nowait; else timer_wait = thread_timer_wait (m, &timer_val); /* First check for sockets. Return immediately. */ num = pal_sock_select (m->max_fd + 1, &readfd, &writefd, &exceptfd, timer_wait); /* Error handling. */ if (num < 0) { if (errno == EINTR) continue; return NULL; } /* File descriptor is readable/writable. */ if (num > 0) { /* High priority read thead. */ thread_process_fd (m, &m->read_high, &readfd, &m->readfd); /* Normal priority read thead. */ thread_process_fd (m, &m->read, &readfd, &m->readfd); /* Write thead. */ thread_process_fd (m, &m->write, &writefd, &m->writefd); } /* Low priority events. */ if ((thread = thread_trim_head (&m->event_low)) != NULL) thread_enqueue_low (m, thread); } }
/* Fetch next ready thread. */ struct thread * thread_fetch_return (struct thread_master *master, struct thread *fetch) { struct thread_master *m = master; int num; struct thread *thread; struct thread *next; fd_set readfd; fd_set writefd; fd_set exceptfd; struct pal_timeval timer_now; struct pal_timeval timer_val; struct pal_timeval *timer_wait; struct pal_timeval timer_nowait; int i; timer_nowait.tv_sec = 0; timer_nowait.tv_usec = 0; /* Pending read is exception. */ if ((thread = thread_trim_head (&m->read_pend)) != NULL) return thread_run (m, thread, fetch); /* Check ready queue. */ if ((thread = thread_trim_head (&m->queue_high)) != NULL) return thread_run (m, thread, fetch); if ((thread = thread_trim_head (&m->queue_middle)) != NULL) return thread_run (m, thread, fetch); if ((thread = thread_trim_head (&m->queue_low)) != NULL) return thread_run (m, thread, fetch); /* Check all of available events. */ /* Check events. */ while ((thread = thread_trim_head (&m->event)) != NULL) thread_enqueue_high (m, thread); /* Check timer. */ pal_time_tzcurrent (&timer_now, NULL); for (i = 0; i < THREAD_TIMER_SLOT; i++) for (thread = m->timer[i].head; thread; thread = next) { next = thread->next; if (timeval_cmp (timer_now, thread->u.sands) >= 0) { thread_list_delete (&m->timer[i], thread); thread_enqueue_middle (m, thread); } #ifndef TIMER_NO_SORT else break; #endif /* TIMER_NO_SORT */ } /* Structure copy. */ readfd = m->readfd; writefd = m->writefd; exceptfd = m->exceptfd; /* Check any thing to be execute. */ if (m->queue_high.head || m->queue_middle.head || m->queue_low.head) timer_wait = &timer_nowait; else timer_wait = thread_timer_wait (m, &timer_val); timer_wait = &timer_nowait; /* First check for sockets. Return immediately. */ num = select (m->max_fd + 1, &readfd, &writefd, &exceptfd, timer_wait); /* Error handling. */ if (num < 0) { return NULL; } /* File descriptor is readable/writable. */ if (num > 0) { /* High priority read thead. */ thread_process_fd (m, &m->read_high, &readfd, &m->readfd); /* Normal priority read thead. */ thread_process_fd (m, &m->read, &readfd, &m->readfd); /* Write thead. */ thread_process_fd (m, &m->write, &writefd, &m->writefd); } /* Low priority events. */ if ((thread = thread_trim_head (&m->event_low)) != NULL) thread_enqueue_low (m, thread); return NULL; }