/** * @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(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; }
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; } }
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. */ 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 event_wait(unsigned int dev_num) { // Sanity checks if (dev_num >= NUM_DEVICES) return -EINVAL; // Prevent curr_tcb from being modified by device_update. INT_ATOMIC_START; // Prevent tasks from waiting if they have a mutex. if (curr_tcb->locks_held != 0) return -EHOLDSLOCK; // Restore device priority to its native priority. curr_tcb->curr_prio = curr_tcb->native_prio; // Put calling task on the device queue. dev_enqueue(curr_tcb, dev_num); // Sleep current task. dispatch_sleep(); INT_ATOMIC_END; 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; }