/* Cancel thread from scheduler. */ void thread_cancel (struct thread *thread) { switch (thread->type) { case THREAD_READ: PAL_SOCK_HANDLESET_CLR (thread->u.fd, &thread->master->readfd); thread_list_delete (&thread->master->read, thread); break; case THREAD_READ_HIGH: PAL_SOCK_HANDLESET_CLR (thread->u.fd, &thread->master->readfd); thread_list_delete (&thread->master->read_high, thread); break; case THREAD_WRITE: pal_assert (PAL_SOCK_HANDLESET_ISSET (thread->u.fd, &thread->master->writefd)); PAL_SOCK_HANDLESET_CLR (thread->u.fd, &thread->master->writefd); thread_list_delete (&thread->master->write, thread); break; case THREAD_TIMER: thread_list_delete (&thread->master->timer[(int)thread->index], thread); break; case THREAD_EVENT: thread_list_delete (&thread->master->event, thread); break; case THREAD_READ_PEND: thread_list_delete (&thread->master->read_pend, thread); break; case THREAD_EVENT_LOW: thread_list_delete (&thread->master->event_low, thread); break; case THREAD_QUEUE: switch (thread->priority) { case THREAD_PRIORITY_HIGH: thread_list_delete (&thread->master->queue_high, thread); break; case THREAD_PRIORITY_MIDDLE: thread_list_delete (&thread->master->queue_middle, thread); break; case THREAD_PRIORITY_LOW: thread_list_delete (&thread->master->queue_low, thread); break; } break; default: break; } thread->type = THREAD_UNUSED; thread_add_unuse (thread->master, thread); }
/* Delete all timer events which has argument value arg. */ void thread_cancel_timer (struct lib_globals *zg, void *arg) { struct thread_master *m = zg->master; struct thread *thread; int i; for (i = 0; i < THREAD_TIMER_SLOT; i++) { thread = m->timer[i].head; while (thread) { struct thread *t; t = thread; thread = t->next; if (t->arg == arg) { thread_list_delete (&m->timer[i], t); t->type = THREAD_UNUSED; thread_add_unuse (m, t); } } } }
/* Delete top of the list and return it. */ static struct thread * thread_trim_head (struct thread_list *list) { if (list->head) return thread_list_delete (list, list->head); return NULL; }
/* Delete all low-events which has argument value arg */ void thread_cancel_event_low (struct lib_globals *zg, void *arg) { struct thread_master *m = zg->master; struct thread *thread; struct thread *t; thread = m->event_low.head; while (thread) { t = thread; thread = t->next; if (t->arg == arg) { thread_list_delete (&m->event_low, t); t->type = THREAD_UNUSED; thread_add_unuse (m, t); } } /* Since Event could have been Queued search queue_low */ thread = m->queue_low.head; while (thread) { t = thread; thread = t->next; if (t->arg == arg) { thread_list_delete (&m->queue_low, t); t->type = THREAD_UNUSED; thread_add_unuse (m, t); } } return; }
/* Delete all events which has argument value arg. */ void thread_cancel_event (struct thread_master *master, void *arg) { struct thread_master *m = master; struct thread *thread; struct thread *t; thread = m->event.head; while (thread) { t = thread; thread = t->next; if (t->arg == arg) { thread_list_delete (&m->event, t); t->type = THREAD_UNUSED; thread_add_unuse (m, t); } } /* Since Event could have been Queued search queue_high */ thread = m->queue_high.head; while (thread) { t = thread; thread = t->next; if (t->arg == arg) { thread_list_delete (&m->queue_high, t); t->type = THREAD_UNUSED; thread_add_unuse (m, t); } } return; }
/* When the file is ready move to queueu. */ int thread_process_fd (struct thread_master *m, struct thread_list *list, pal_sock_set_t *fdset, pal_sock_set_t *mfdset) { struct thread *thread; struct thread *next; int ready = 0; for (thread = list->head; thread; thread = next) { next = thread->next; if (PAL_SOCK_HANDLESET_ISSET (THREAD_FD (thread), fdset)) { PAL_SOCK_HANDLESET_CLR(THREAD_FD (thread), mfdset); thread_list_delete (list, thread); thread_enqueue_middle (m, thread); ready++; } } return ready; }
/* Delete all write events which has argument value arg. */ void thread_cancel_write (struct lib_globals *zg, void *arg) { struct thread_master *m = zg->master; struct thread *thread; thread = m->write.head; while (thread) { struct thread *t; t = thread; thread = t->next; if (t->arg == arg) { thread_list_delete (&m->write, t); t->type = THREAD_UNUSED; thread_add_unuse (m, t); } } }
/* Delete all read events which has argument value arg. */ void thread_cancel_read (struct thread_master *master, void *arg) { struct thread_master *m = master; struct thread *thread; thread = m->read.head; while (thread) { struct thread *t; t = thread; thread = t->next; if (t->arg == arg) { thread_list_delete (&m->read, t); t->type = THREAD_UNUSED; thread_add_unuse (m, t); } } }
/* 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; }