/** * @brief Puts a task to sleep on the sleep queue until the next * event is signalled for the device. * * @param dev Device number. */ int dev_wait(unsigned int dev __attribute__((unused))) { disable_interrupts(); tcb_t* cur_tcb = get_cur_tcb(); if(cur_tcb->holds_lock !=0){ return -EHOLDSLOCK; } tcb_t* sleep_queue = devices[dev].sleep_q; if(sleep_queue == 0) { devices[dev].sleep_q = cur_tcb; devices[dev].sleep_q -> sleep_queue = 0; } else{ while(sleep_queue -> sleep_queue !=0) sleep_queue = sleep_queue -> sleep_queue; sleep_queue->sleep_queue = cur_tcb; sleep_queue = sleep_queue-> sleep_queue; sleep_queue -> sleep_queue =0; } dispatch_sleep(); enable_interrupts(); return 0; }
int mutex_lock_syscall(int mutex __attribute__((unused))) { //printf("mutex_lock, %d\n", mutex); // if mutex invalid if (mutex >= OS_NUM_MUTEX || gtMutex[mutex].bAvailable == 1) { return EINVAL; } if (gtMutex[mutex].pHolding_Tcb == get_cur_tcb()) return EDEADLOCK; // if blocked if (gtMutex[mutex].bLock == 1) { tcb_t** tmp = &(gtMutex[mutex].pSleep_queue); while (1) { if (*tmp == (void *)0) { gtMutex[mutex].pSleep_queue = runqueue_remove(get_cur_prio()); break; } if((*tmp)->sleep_queue == (void *)0) { (*tmp)->sleep_queue = runqueue_remove(get_cur_prio()); ((*tmp)->sleep_queue) = (void *)0; break; } tmp = (tcb_t **)&((*tmp)->sleep_queue); } //printf("blocked!!!!!!!!!\n"); //printf("mutex holding tcb: %d\n", (gtMutex[mutex].pHolding_Tcb)->native_prio); dispatch_save(); } // if not blocked gtMutex[mutex].bLock = 1; gtMutex[mutex].pHolding_Tcb = get_cur_tcb(); //printf("mutex holding tcb: %d\n", (gtMutex[mutex].pHolding_Tcb)->native_prio); //printf("mutex sleep queue\n"); /* tcb_t* tmp = gtMutex[mutex].pSleep_queue; while (tmp != (void *)0) { printf("sleep %d\n", tmp->native_prio); tmp = tmp->sleep_queue; } */ return 0; }
int mutex_unlock(int mutex_num) { if(debug_enabled1 == 1) printf("\tmutex::mutex_unlock:: id= %d tcb = %d\n", mutex_num, get_cur_tcb()->cur_prio); disable_interrupts(); //check for valid mutex number if(mutex_num < 0 || mutex_num > mutexID) return -EINVAL; //mutex is valid mutex_t* mutex = >Mutex[mutex_num-1]; //mutex we are referencing //check if we own this mutex if(mutex->pHolding_Tcb != get_cur_tcb()) return -EPERM; get_cur_tcb()->holds_lock--; //if the sleep queue is empty if(mutex->pSleep_queue == NULL_TCB) { mutex->bAvailable = TRUE; mutex->bLock = FALSE; mutex->pHolding_Tcb = NULL_TCB; } //queue not empty else { //next is up tcb_t* next = mutex->pSleep_queue; //mutex held by next mutex->pSleep_queue = next->sleep_queue; mutex->pHolding_Tcb = next; //next holds mutex next->sleep_queue = NULL_TCB; next->holds_lock++; //next is ready to run runqueue_add(next, next->cur_prio); } enable_interrupts(); return 0; //success }
int mutex_lock(int mutex_num) { if(debug_enabled1 == 1) printf("\tmutex::mutex_lock:: lock(%d) by tcb %d\n", mutex_num, get_cur_tcb()->cur_prio); disable_interrupts(); //check for valid mutex number if(mutex_num < 0 || mutex_num > mutexID) return -EINVAL; //mutex is valid mutex_t* mutex = >Mutex[mutex_num-1]; //mutex we are referencing //mutex is available if(mutex->bAvailable == TRUE) { //acquire mutex mutex->bLock = TRUE; mutex->bAvailable = FALSE; mutex->pHolding_Tcb = get_cur_tcb(); get_cur_tcb()->holds_lock++; enable_interrupts(); return 0; //success } //mutex is not available else { //if current task is already holding it if(mutex->pHolding_Tcb == get_cur_tcb()) return -EDEADLOCK; //if the sleep queue is empty if( mutex->pSleep_queue == NULL_TCB ) mutex->pSleep_queue = get_cur_tcb(); //else sleep queue is not empty else { //add to the end of the queue tcb_t* t = mutex->pSleep_queue; while(t->sleep_queue != NULL_TCB) t = t->sleep_queue; t->sleep_queue = get_cur_tcb(); } } //sleep and wait..` dispatch_sleep(); enable_interrupts(); return 0; //success }
/** * @brief Puts a task to sleep on the sleep queue until the next * event is signalled for the device. * * @param dev Device number. */ void dev_wait(unsigned int dev ) { if(debug_enabled == 1)puts("dev_wait++\n"); //add to the sleep queue tcb_t* sleep_me = get_cur_tcb(); sleep_me->sleep_queue = devices[dev].sleep_queue; devices[dev].sleep_queue = sleep_me; if(debug_enabled == 1)printf("dev_wait...dev = %d:::new = (prio) %d:::old = %x\n", dev, (unsigned)devices[dev].sleep_queue->cur_prio, (unsigned)devices[dev].sleep_queue->sleep_queue); }
int mutex_lock(int mutex __attribute__((unused))) { tcb_t* temp; disable_interrupts(); // if the provided mutex identifier if invalid if(mutex > OS_NUM_MUTEX || gtMutex[mutex].bAvailable == TRUE) { enable_interrupts(); return -EINVAL; } if(gtMutex[mutex].pHolding_Tcb == get_cur_tcb()) { // if the current task is already holding the lock enable_interrupts(); return -EDEADLOCK; } else { if(gtMutex[mutex].bLock == 0) { // if the lock is not been locked // set lock status and holding tcb gtMutex[mutex].bLock = 1; gtMutex[mutex].pHolding_Tcb = get_cur_tcb(); get_cur_tcb()->holds_lock = 1; #ifdef HLP get_cur_tcb()->cur_prio = 0; #endif // HLP gtMutex[mutex].pSleep_queue = 0; enable_interrupts(); return 0; } else { // if the lock is been locked // move the current tack to mutex sleeping queue temp = gtMutex[mutex].pSleep_queue; if (temp == 0) { gtMutex[mutex].pSleep_queue = get_cur_tcb(); } else { // put current tcb at the end of the mutex sleeping queue while((temp->sleep_queue) != 0) { temp = temp->sleep_queue; } temp->sleep_queue = get_cur_tcb(); } // context switch to another task dispatch_sleep(); } } // the function cannot get here return 1; }
/* ------------------------------------------------ Function: mutex_unlock Description: Unlocks the mutex and assigns lock to next-in-queue. If queue is empty, it simply unlocks the mutex ------------------------------------------------ */ int mutex_unlock(int mutex) { tcb_t* curr_tcb; tcb_t* temp_tcb; curr_tcb = get_cur_tcb(); if (mutex<1 || (gtMutex[mutex-1].bAvailable!=1)){ return -EINVAL; } if(curr_tcb != gtMutex[mutex-1].pHolding_Tcb){ return -EPERM; } gtMutex[mutex-1].pHolding_Tcb->holds_lock = 0; gtMutex[mutex-1].bLock = 0; curr_tcb->cur_prio = curr_tcb->native_prio; /*Changing lock status in current_tcb*/ if(gtMutex[mutex-1].pSleep_queue!=0){ /* Updating status of next in line for lock*/ /* If queue is not single-element */ runqueue_add(gtMutex[mutex-1].pSleep_queue, gtMutex[mutex-1].pSleep_queue->native_prio); if(gtMutex[mutex-1].pSleep_queue->sleep_queue!=0){ temp_tcb = gtMutex[mutex-1].pSleep_queue; gtMutex[mutex-1].pSleep_queue = temp_tcb->sleep_queue; temp_tcb->sleep_queue = 0; } else { /* If queue is single-element */ temp_tcb = gtMutex[mutex-1].pSleep_queue; gtMutex[mutex-1].pSleep_queue = 0; temp_tcb->sleep_queue = 0; rear[mutex-1] = 0; } /* Updating status of mutex */ gtMutex[mutex-1].bLock = 1; gtMutex[mutex-1].pHolding_Tcb = temp_tcb; gtMutex[mutex-1].pHolding_Tcb->holds_lock = 1; } else { /* If sleep queue is empty, unlock mutex*/ gtMutex[mutex-1].bLock = 0; gtMutex[mutex-1].pHolding_Tcb = 0; } return 0; }
int event_wait(unsigned int dev) { tcb_t *task = get_cur_tcb(); if (dev >= NUM_DEVICES) return -EINVAL; if (task->holds_lock) return -EDEADLOCK; disable_interrupts(); dev_wait(dev); enable_interrupts(); return 1; }
int mutex_unlock_syscall(int mutex __attribute__((unused))) { // if mutex invalid if (mutex >= OS_NUM_MUTEX || gtMutex[mutex].bAvailable == 1) { return EINVAL; } if (gtMutex[mutex].pHolding_Tcb != get_cur_tcb()) return EPERM; // first tcb in pSleep_queue tcb_t* nextTcb = gtMutex[mutex].pSleep_queue; //if (nextTcb != (void *)0) { // set pSleep_queue to next one // gtMutex[mutex].pSleep_queue = (gtMutex[mutex].pSleep_queue)->sleep_queue; // if there are no other tcbs blocked if (nextTcb == (void *)0) { gtMutex[mutex].bLock = 0; gtMutex[mutex].pHolding_Tcb = (void *)0; // test //printf("mutex_unlock, %d\n", mutex); //printf("mutex holding tcb: %d\n", (gtMutex[mutex].pHolding_Tcb)->native_prio); } else { gtMutex[mutex].pSleep_queue = (gtMutex[mutex].pSleep_queue)->sleep_queue; nextTcb->sleep_queue = (void *)0; gtMutex[mutex].pHolding_Tcb = nextTcb; runqueue_add(nextTcb, nextTcb->native_prio); //printf("mutex_unlock, change to %d\n", mutex); //printf("mutex holding tcb: %d\n", (gtMutex[mutex].pHolding_Tcb)->native_prio); //printf("mutex sleep queue\n"); /* tcb_t* tmp = gtMutex[mutex].pSleep_queue; while (tmp != (void *)0) { printf("sleep %d\n", tmp->native_prio); tmp = tmp->sleep_queue; } */ } return 0; }
int mutex_lock(int mutex __attribute__((unused))) { disable_interrupts(); /* invalid mutex id, return error code */ if(mutex < 0 || mutex >= OS_NUM_MUTEX || gtMutex[mutex].bAvailable){ enable_interrupts(); return -EINVAL; } else{ tcb_t* cur_tcb = get_cur_tcb(); /* current task is already holding the lock, return error code */ if(cur_tcb == gtMutex[mutex].pHolding_Tcb){ enable_interrupts(); return -EDEADLOCK; } /* lock is holding by others, put current task to sleep */ else if(gtMutex[mutex].bLock){ /* put the task into sleep queue */ if(gtMutex[mutex].pSleep_queue == NULL){ gtMutex[mutex].pSleep_queue = cur_tcb; cur_tcb->sleep_queue = NULL; } else{ tcb_t* tmp = gtMutex[mutex].pSleep_queue; while(tmp->sleep_queue != NULL){ tmp = tmp->sleep_queue; } tmp->sleep_queue = cur_tcb; cur_tcb->sleep_queue = NULL; } /* sleep & context switch */ dispatch_sleep(); } /* no one's holding it, get go! */ gtMutex[mutex].pHolding_Tcb = cur_tcb; gtMutex[mutex].bLock = TRUE; cur_tcb->holds_lock ++; //cur_tcb->native_prio = cur_tcb->cur_prio; //cur_tcb->cur_prio = 0; enable_interrupts(); return 0; } }
/** * @brief Puts a task to sleep on the sleep queue until the next * event is signalled for the device. * * @param dev Device number. */ int dev_wait(unsigned int dev __attribute__((unused))) { tcb_t* cur_tcb; tcb_t* sleepQ; disable_interrupts(); // get current tcb and sleep devices on sleep queue cur_tcb = get_cur_tcb(); sleepQ = devices[dev].sleep_queue; // if task is holding a lock, return error if (cur_tcb->holds_lock != 0) return -EHOLDSLOCK; // add cur_tcb to head of sleep queue linked list devices[dev].sleep_queue = cur_tcb; cur_tcb->sleep_queue = sleepQ; // dispatch to next task dispatch_sleep(); return 0; }
/* ------------------------------------------------ Function: mutex_lock Description: Locks the mutex if no process currently holds the mutex, else puts the current process in sleep queue. ------------------------------------------------ */ int mutex_lock(int mutex) { tcb_t* cur_tcb; /*Getting currrently running TCB*/ cur_tcb = get_cur_tcb(); if (mutex<1 || mutex>OS_NUM_MUTEX || (gtMutex[mutex-1].bAvailable!=1)) { return -EINVAL; } if (gtMutex[mutex-1].pHolding_Tcb == cur_tcb) { return -EDEADLOCK; } /*Locking the current mutex, if available*/ if (gtMutex[mutex-1].bLock == 0) { gtMutex[mutex-1].pHolding_Tcb = cur_tcb; gtMutex[mutex-1].bLock = 1; gtMutex[mutex-1].pHolding_Tcb->holds_lock = 1; cur_tcb->cur_prio = 0; return 0; } /* adding process to mutex sleep queue */ else { /* If initial sleep queue is empty*/ if (gtMutex[mutex-1].pSleep_queue == 0){ cur_tcb->sleep_queue = 0; gtMutex[mutex-1].pSleep_queue = cur_tcb; rear[mutex-1] = cur_tcb; } else { /* Attaching current head to new del_tcb and updating head*/ cur_tcb->sleep_queue = 0; rear[mutex-1]->sleep_queue = cur_tcb; rear[mutex-1] = cur_tcb; } dispatch_sleep(); return 0; } return 0; }
/** * @brief Puts a task to sleep on the sleep queue until the next * event is signalled for the device. * * @param dev Device number. */ int dev_wait(unsigned int dev) { disable_interrupts(); // get the current task's tcb, no need to handle fault dev tcb_t* current_task_tcb = get_cur_tcb(); // check if the current task holds any mutex if (current_task_tcb->cur_prio == HLP_PRIO) { printf("current taks has mutex on hand, cannot sleep!\n"); return EHOLDSLOCK; } // insert the task on the head of device sleep queue current_task_tcb->sleep_queue = devices[dev].sleep_queue; devices[dev].sleep_queue = current_task_tcb; // make it sleep dispatch_sleep(); return 0; }
int mutex_unlock(int mutex __attribute__((unused))) { if (mutex >= OS_NUM_MUTEX) { return EINVAL; } disable_interrupts(); tcb_t* cur_tcb = get_cur_tcb(); mutex_t cur_mutex = gtMutex[mutex]; /* check if provided mutex identifier is valid */ if (!cur_mutex.bAvailable) { enable_interrupts(); return EINVAL; } /* check if current task is holding the mutex */ if (cur_tcb != cur_mutex.pHolding_Tcb) { enable_interrupts(); return EPERM; } cur_mutex.pHolding_Tcb = 0; /* add first task in sleep queue to run queue */ if (cur_mutex.pSleep_queue != 0) { tcb_t* h_tcb = cur_mutex.pSleep_queue; cur_mutex.pHolding_Tcb = h_tcb; runqueue_add(h_tcb, h_tcb->cur_prio); cur_mutex.pSleep_queue = h_tcb->sleep_queue; cur_mutex.bLock = 1; } cur_mutex.bLock = 0; enable_interrupts(); return 0; }
int mutex_unlock(int mutex __attribute__((unused))) { disable_interrupts(); /* invalid mutex id, return error code */ if(mutex < 0 || mutex >= OS_NUM_MUTEX || gtMutex[mutex].bAvailable){ enable_interrupts(); return -EINVAL; } else{ tcb_t* cur_tcb = get_cur_tcb(); /* current task does not hold the lock, return error code */ if(cur_tcb != gtMutex[mutex].pHolding_Tcb){ enable_interrupts(); return -EPERM; } else{ /* release the lock */ gtMutex[mutex].pHolding_Tcb = NULL; gtMutex[mutex].bLock = FALSE; /* there is task waiting in the sleep queue, make it able to run */ if(gtMutex[mutex].pSleep_queue != NULL){ tcb_t* tmp = gtMutex[mutex].pSleep_queue; gtMutex[mutex].pSleep_queue = tmp->sleep_queue; tmp->sleep_queue = NULL; runqueue_add(tmp, tmp->cur_prio); } /* decrease the num of locks hold by current task by one */ if(cur_tcb->holds_lock != 0) cur_tcb->holds_lock --; enable_interrupts(); return 0; } } }
int mutex_lock(int mutex __attribute__((unused))) { // Get the current task tcb_t* cur_tcb = get_cur_tcb(); mutex_t* cur_mutex = &(gtMutex[mutex]); // Check if mutex is in range if((mutex <0) || (mutex >= OS_NUM_MUTEX)) return EINVAL; // Check if deadlock error if(cur_tcb == gtMutex[mutex].pHolding_Tcb) return EDEADLOCK; // Disable interrupts disable_interrupts(); // If mutex is locked (blocked), wait until freed up by sleeping while(cur_mutex->bLock == 1){ // Enable interrupts enable_interrupts(); dispatch_sleep(); //Disable interrupts disable_interrupts(); } // Set holding Tcb to current task, set bLock = TRUE, give curr\ent task highest priority, set cur tasks's "holds_lock" val to 1 cur_mutex->bLock = 1; cur_mutex->pHolding_Tcb = cur_tcb; cur_tcb->cur_prio = highest_prio(); cur_tcb->holds_lock = 1; // Enable Interrupts enable_interrupts(); return 0; }
int mutex_lock(int mutex __attribute__((unused))) { disable_interrupts(); tcb_t* cur_tcb = get_cur_tcb(); uint8_t cur_prio = get_cur_prio(); tcb_t* sleep_queue, *temp; mutex_t *cur_mutex = &(gtMutex[mutex]); /* check if provided mutex identifier is valid */ if(mutex > num_mutices) { enable_interrupts(); return EINVAL; } /* check if current task is holding the mutex */ if(cur_mutex->pHolding_Tcb == cur_tcb) { enable_interrupts(); return EDEADLOCK; } /* check if sleep queue is empty */ if(cur_mutex->pSleep_queue == 0) { cur_mutex->pSleep_queue = cur_tcb; cur_tcb->sleep_queue = 0; } /* insert task at appropriate location in sleep queue */ else { sleep_queue = cur_mutex->pSleep_queue; temp = sleep_queue; /* insert at front of the list */ if(cur_prio < (sleep_queue->cur_prio)) { cur_tcb->sleep_queue = cur_mutex->pSleep_queue; cur_mutex->pSleep_queue = cur_tcb; } else { sleep_queue = sleep_queue->sleep_queue; while(sleep_queue != 0) { if(cur_prio < (sleep_queue->cur_prio)) { cur_tcb->sleep_queue = sleep_queue; temp->sleep_queue = cur_tcb; break; } temp = sleep_queue; sleep_queue = sleep_queue->sleep_queue; } } } disable_interrupts(); dispatch_sleep(); enable_interrupts(); return 0; }
int mutex_unlock(int mutex __attribute__((unused))) { tcb_t* temp; disable_interrupts(); // if the provided mutex identifier if invalid if(mutex > OS_NUM_MUTEX || gtMutex[mutex].bAvailable == TRUE) { enable_interrupts(); return -EINVAL; } if(gtMutex[mutex].pHolding_Tcb != get_cur_tcb()) { // if the urrent task does not hold the mutex enable_interrupts(); return -EPERM; } else { temp = gtMutex[mutex].pHolding_Tcb; temp->holds_lock = 0; #ifdef HLP temp->cur_prio = temp->native_prio; #endif // HLP // if there is no element in sleep queue if(gtMutex[mutex].pSleep_queue == 0) { gtMutex[mutex].bLock = 0; gtMutex[mutex].pHolding_Tcb = 0; enable_interrupts(); return 0; } else { // if the sleep queue have tasks waiting for the mutex // first tcb in sleeping queue gets the mutex gtMutex[mutex].pHolding_Tcb = gtMutex[mutex].pSleep_queue; // move the head of mutex sleeping queue to next gtMutex[mutex].pSleep_queue = gtMutex[mutex].pSleep_queue->sleep_queue; // clear the sleeping queue of the holding tcb gtMutex[mutex].pHolding_Tcb->sleep_queue = 0; gtMutex[mutex].pHolding_Tcb->holds_lock = 1; #ifdef HLP gtMutex[mutex].pHolding_Tcb->cur_prio = 0; #endif // HLP // put the wake up task into runqueue runqueue_add(gtMutex[mutex].pHolding_Tcb, gtMutex[mutex].pHolding_Tcb->cur_prio); // check the wake up task's priority and current running task's priority if(highest_prio() < get_cur_prio()) { // switch to the highest task dispatch_save(); } else { // stay the same enable_interrupts(); return 0; } } } // the function will not get here return 1; }