/* * uthread_switch() * * Wait until there is a runnable thread, and then switch to it using * uthread_swapcontext(). * */ void uthread_switch(void) { int i = 0; while (1) { uthread_idle(); for(i = UTH_MAXPRIO; i >= 0; i--) { if (!utqueue_empty(&runq_table[i])) { uthread_t* backup = ut_curthr; uthread_t* new_thread = utqueue_dequeue(&runq_table[i]); assert(new_thread->ut_state == UT_RUNNABLE); assert(new_thread->ut_link.l_prev == NULL && new_thread->ut_link.l_next == NULL); /* Swap the new thread */ ut_curthr = new_thread; ut_curthr->ut_state = UT_ON_CPU; /* Swap context */ uthread_swapcontext(&backup->ut_ctx, &ut_curthr->ut_ctx); return; } } } }
/* * uthread_cond_signal * * Wakeup just one thread waiting on the condition variable. * Note there may be no threads waiting. * param cond: the pointer to the conditional variable object */ void uthread_cond_signal(uthread_cond_t *cond) { assert(cond != NULL); if (!utqueue_empty(&cond->uc_waiters)) { uthread_wake(utqueue_dequeue(&cond->uc_waiters)); } }
/* * uthread_cond_broadcast * * Wakeup all the threads waiting on this condition variable. * param cond: the pointer to the conditional variable object */ void uthread_cond_broadcast(uthread_cond_t *cond) { assert(cond != NULL); while (!utqueue_empty(&cond->uc_waiters)) { uthread_wake(utqueue_dequeue(&cond->uc_waiters)); } }
/* * uthread_switch() * * This is where all the magic is. Wait until there is a runnable thread, and * then switch to it using uthread_swapcontext(). Make sure you pick the * highest priority runnable thread to switch to. Also don't forget to take * care of setting the ON_CPU thread state and the current thread. Note that * it is okay to switch back to the calling thread if it is the highest * priority runnable thread. * * Every time uthread_switch() is called, uthread_idle() should be called at * least once. In addition, when there are no runnable threads, you should * repeatedly call uthread_idle() until there are runnable threads. Threads * with numerically higher priorities run first. For example, a thread with * priority 8 will run before one with priority 3. * */ void uthread_switch(void) { //we change the location of //the first thread: it might be put in runnable queue //or it might be just switched uthread_t * old_thr = ut_curthr; //check the state if( old_thr -> ut_state == UT_RUNNABLE){ //called by uthread_yield uthread_add_to_runnable_queue(old_thr); } else{ //wont add to the runnable queue } uthread_idle(); while(1){ //get the next runnable thread. //from highest priority queue to low priority queue int i = UTH_MAXPRIO; /* for(; i >= 0; i --){ printf("%d:%d\n", i, runq_table[i].tq_size); } i = UTH_MAXPRIO; */ uthread_t* next_thread = NULL; for(; i >= 0; i --){ if( !utqueue_empty(&runq_table[i])){ //printf("%d:%d\n", i, runq_table[i].tq_size); next_thread = utqueue_dequeue(&runq_table[i]); break; } } if(next_thread != NULL){ //switch! next_thread->ut_state = UT_ON_CPU; ut_curthr = next_thread; uthread_swapcontext(& old_thr -> ut_ctx, &ut_curthr -> ut_ctx); return; } //no runnable threads //TODO: Rewrtie uthread_idle else{ uthread_idle(); } } }
/* * uthread_mtx_unlock * * Unlock the mutex. If there are people waiting to get this mutex, * explicitly hand off the ownership of the lock to a waiting thread and * then wake that thread. */ void uthread_mtx_unlock(uthread_mtx_t *mtx) { assert(mtx != NULL); assert(mtx->m_owner == ut_curthr); if(utqueue_empty(&mtx->m_waiters)){ mtx->m_owner = NULL; return; } else{ //dequeue a thread //set it as the owner //change it to runnable //and put back to runnable queue uthread_t* dequeued_thread = utqueue_dequeue(&mtx->m_waiters); mtx->m_owner = dequeued_thread; dequeued_thread->ut_state = UT_RUNNABLE; uthread_add_to_runnable_queue(dequeued_thread); return; } }
/* * utqueue_dequeue * remove element from the list */ uthread_t * utqueue_dequeue(utqueue_t *q) { uthread_t *thr; list_link_t *link; assert(q != NULL); if (utqueue_empty(q)) { return NULL; } link = q->tq_waiters.l_prev; thr = list_item(link, uthread_t, ut_link); list_remove(link); q->tq_size--; return thr; }