/* * uthread_mtx_lock * * Lock the mutex. This call will block if it's already locked. When the * thread wakes up from waiting, it should own the mutex (see _unlock()). */ void uthread_mtx_lock(uthread_mtx_t *mtx) { //NOT_YET_IMPLEMENTED("UTHREADS: uthread_mtx_lock"); assert(mtx != NULL); if(mtx -> m_owner == NULL) mtx -> m_owner = ut_curthr; else{ assert(mtx->m_owner != ut_curthr); //put current thread in the waiters queue utqueue_enqueue(&mtx->m_waiters, ut_curthr); //block current thread uthread_block(); } }
/* * uthread_setprio * * Changes the priority of the indicated thread. Note that if the thread * is in the UT_RUNNABLE state (it's runnable but not on cpu) you should * change the list it's waiting on so the effect of this call is * immediate. */ void uthread_setprio(uthread_id_t id, int prio) { uthread_t* thread_to_change = &uthreads[id]; if(thread_to_change->ut_state == UT_RUNNABLE){ int previous_prio = thread_to_change->ut_prio; thread_to_change->ut_prio = prio; utqueue_remove(&runq_table[previous_prio], thread_to_change); utqueue_enqueue(&runq_table[prio], thread_to_change); } else{ //change directly thread_to_change->ut_prio = prio; } return; }
/* * uthread_cond_wait * * Should behave just like a stripped down version of pthread_cond_wait. * Block on the given condition variable. * param cond: the pointer to the conditional variable object * param mtx: the pointer to the mutex object */ void uthread_cond_wait(uthread_cond_t *cond, uthread_mtx_t *mtx) { /* Make sure the mtx is locked by the current thread */ assert(mtx != NULL && cond != NULL); assert(mtx->m_owner == ut_curthr); utqueue_enqueue(&cond->uc_waiters, ut_curthr); uthread_mtx_unlock(mtx); /* Block on the conditional variable */ uthread_block(); /* Now it gets back, try lock the mutex */ uthread_mtx_lock(mtx); }
/* * uthread_setprio * * Changes the priority of the indicated thread. * param id: the uthread id * param prio: the priority to be set */ int uthread_setprio(uthread_id_t id, int prio) { /* If prio is invalid */ if (prio < 0 || prio > UTH_MAXPRIO) { ut_curthr->ut_errno = EINVAL; return EINVAL; } /* Invalid thread id */ if (id < 0 || id >= UTH_MAX_UTHREADS || uthreads[id].ut_state == UT_NO_STATE || uthreads[id].ut_state == UT_ZOMBIE) { ut_curthr->ut_errno = ESRCH; return ESRCH; } /* If the current state is runnable */ if (uthreads[id].ut_state == UT_RUNNABLE) { if (uthreads[id].ut_link.l_prev != NULL && uthreads[id].ut_link.l_next != NULL) utqueue_remove(&runq_table[uthreads[id].ut_prio], &uthreads[id]); uthreads[id].ut_prio = prio; utqueue_enqueue(&runq_table[prio], &uthreads[id]); } else { /* If it is waiting or on CPU, just set the priority */ /* Because it's not in the queue! */ uthreads[id].ut_prio = prio; } return 0; }
/* ----------- public code -- */ void uthread_add_to_runnable_queue(uthread_t* thread){ int prio = thread->ut_prio; utqueue_enqueue(&runq_table[prio], thread); }