示例#1
0
/*
 * 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;
			}
		}
	}
}
示例#2
0
/*
 * 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));
	}
}
示例#3
0
/*
 * 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));
	}
}
示例#4
0
/*
 * 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();
        }
     }

}
示例#5
0
/*
 * 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;
    }
}
示例#6
0
/*
 * 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;
}