/** * @brief Context switch to the highest priority task while saving off the * current task state. * * This function needs to be externally synchronized. * We could be switching from the idle task. The priority searcher has been tuned * to return IDLE_PRIO for a completely empty run_queue case. */ void dispatch_save(void) { if(cur_tcb->cur_prio == HIGHEST_PRIO) return; tcb_t *dest, *temp; temp = cur_tcb; uint8_t hp = highest_prio(); /* If the idle task is he only next high prio task that means we are already running idle task */ if(hp == IDLE_PRIO) dest = cur_tcb; else dest = runqueue_remove(hp); /* Set cur_tcb to the task that we are about to run */ cur_tcb = dest; /* Set the cur_kstack var of the task that we are about to run */ cur_kstack = (int)dest->kstack_high; /* Add the task that we just switched from back to the queue */ runqueue_add(temp, temp->cur_prio); ctx_switch_full(&(dest->context), &(temp->context)); }
/** * @brief Context switch to the highest priority task while saving off the * current task state. * * This function needs to beexternally synchronized. * We could be switching from the idle task. The priority searcher has been tuned * to return IDLE_PRIO for a completely empty run_queue case. */ void dispatch_save(void) { uint8_t next_prio; tcb_t *next_tcb, *saved_cur_tcb; // printf("inside dispatch save\n"); // printf("added cur_tcb %u %p to run queue\n", cur_tcb->cur_prio, cur_tcb); next_prio = highest_prio(); /* * add the current task to the run queue... */ runqueue_add(cur_tcb, cur_tcb->cur_prio); // printf("next_prio is %u\n", next_prio); next_tcb = runqueue_remove(next_prio); // printf(" d save: removed next_tcb %u %p from run queue\n", next_tcb->cur_prio, next_tcb); // print_run_queue(); saved_cur_tcb = cur_tcb; cur_tcb = next_tcb; #if 0 printf("before calling ctx sw full, cur->context is %p\n", &(saved_cur_tcb->context)); printf("hexdump of cur->context is\n"); hexdump(&saved_cur_tcb->context, 160); printf("before calling ctx sw full, next->context is %p\n", &(next_tcb->context)); printf("hexdump of next->context is\n"); hexdump(&next_tcb->context, 160); #endif // disable_interrupts(); ctx_switch_full((volatile void *)(&(next_tcb->context)), (volatile void *)(&(saved_cur_tcb->context))); // while(1); }
/** * @brief Context switch to the highest priority task that is not this task -- * and save the current task but don't mark is runnable. * * There is always an idle task to switch to. */ void dispatch_sleep(void) { uint8_t next_prio; tcb_t *next_tcb, *saved_cur_tcb; // printf("inside dispatch sleep\n"); next_prio = highest_prio(); // printf("next_prio is %u\n", next_prio); next_tcb = runqueue_remove(next_prio); // printf("d sleep: removed next_tcb %u %p from run queue\n", next_tcb->cur_prio, next_tcb); // print_run_queue(); saved_cur_tcb = cur_tcb; cur_tcb = next_tcb; // printf("before calling ctx sw full, next->context->sp is %p\n", next_tcb->context.sp); // printf("before calling ctx sw full, cur->context->sp is %p\n", saved_cur_tcb->context.sp); // printf("in dispatch sleep, sp is %u\n", get_kernel_sp()); // hexdump(get_kernel_sp(), 200); // disable_interrupts(); // printf("inside dispatch sleep hexdump of cur->context is\n"); // hexdump(&saved_cur_tcb->context, 160); ctx_switch_full((volatile void *)(&(next_tcb->context)), (volatile void *)(&(saved_cur_tcb->context))); // while(1); }
/** * @brief Context switch to the highest priority task that is not this task -- * don't save the current task state. * * There is always an idle task to switch to. */ void dispatch_nosave(void) { /* Get the highest priority */ uint8_t prio = highest_prio(); /* Get the corresponding task */ tcb_t *tcb = runqueue_remove(prio); /* Call ctx_switch_half */ cur_tcb = tcb; ctx_switch_half(&(cur_tcb -> context)); }
/** * @brief Context switch to the highest priority task that is not this task -- * don't save the current task state. * * There is always an idle task to switch to. */ void dispatch_nosave(void) { uint8_t prio = highest_prio(); tcb_t *next_task = runqueue_remove(prio); //Enqueue current task runqueue_add(cur_tcb, cur_tcb->cur_prio); cur_tcb = next_task; ctx_switch_half(&(next_task->context)); }
/** * @brief Context switch to the highest priority task that is not this task -- * and save the current task but don't mark is runnable. * * There is always an idle task to switch to. */ void dispatch_sleep(void) { uint8_t prio = highest_prio(); //printf("Highest prio is %d\n",prio); tcb_t *next_task = runqueue_remove(prio); tcb_t *tmp_task = cur_tcb; cur_tcb = next_task; ctx_switch_full(&(next_task->context), &(tmp_task->context)); }
/** * @brief Context switch to the highest priority task that is not this task -- * and save the current task but don't mark is runnable. * * There is always an idle task to switch to. */ void dispatch_sleep(void) { /* Similar implementation as dispatch_save but let the current task sleep, and don't * add it into the runqueue */ uint8_t prio = highest_prio(); tcb_t *new_task; new_task = runqueue_remove(prio); sched_context_t *cur_ctx = &(cur_tcb -> context); cur_tcb = new_task; ctx_switch_full(&(new_task -> context), cur_ctx); }
/** * @brief Context switch to the highest priority task that is not this task -- * don't save the current task state. * * There is always an idle task to switch to. */ void dispatch_nosave(void) { /* This executes the first task This ends up being the initial high prio task */ /* Set cur_tcb to the task that we are about to run */ cur_tcb = runqueue_remove(highest_prio()); /* Set the cur_kstack var of the task that we are about to run */ cur_kstack = (int)cur_tcb->kstack_high; ctx_switch_half(&(cur_tcb->context)); }
/** * @brief Context switch to the highest priority task while saving off the * current task state. * * This function needs to be externally synchronized. * We could be switching from the idle task. The priority searcher has been tuned * to return IDLE_PRIO for a completely empty run_queue case. */ void dispatch_save(void) { tcb_t *new_task; tcb_t *old_task = cur_tcb; uint8_t prio = highest_prio(); /* If the current task is not the highest priority task */ if (old_task -> cur_prio > prio) { new_task = runqueue_remove(prio); sched_context_t *old_ctx = &(old_task -> context); runqueue_add(old_task, old_task -> cur_prio); cur_tcb = new_task; /* !!! ctx_switch_full has not yet implemented */ ctx_switch_full(&(new_task -> context), old_ctx); } }
/** * @brief Context switch to the highest priority task that is not this task -- * don't save the current task state. * * There is always an idle task to switch to. */ void dispatch_nosave(void) { uint8_t next_prio; tcb_t *next_tcb; // printf("inside dispatch no save\n"); next_prio = highest_prio(); // printf("next_prio is %u\n", next_prio); /* * manage the run queue... */ next_tcb = runqueue_remove(next_prio); // printf("d nosave: removed next_tcb %u %p from run queue\n", next_tcb->cur_prio, next_tcb); // print_run_queue(); cur_tcb = next_tcb; // printf("before calling ctx sw half, context->sp is %p\n", next_tcb->context.sp); ctx_switch_half((volatile void *)(&(next_tcb->context))); }
/** * @brief Context switch to the highest priority task that is not this task -- * and save the current task but don't mark is runnable. * * There is always an idle task to switch to. */ void dispatch_sleep(void) { tcb_t *dest, *temp; temp = cur_tcb; uint8_t cp = get_cur_prio(); /* i.e task that was just put to sleep */ uint8_t hp = highest_prio(); /* next task to run */ /* Run idle task if there are no other */ if(cp == hp) dest = runqueue_remove(IDLE_PRIO); else dest = runqueue_remove(hp); /* Set cur_tcb to the task that we are about to run */ cur_tcb = dest; /* Set the cur_kstack var of the task that we are about to run */ cur_kstack = (int)dest->kstack_high; ctx_switch_full(&(dest->context), &(temp->context)); }
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_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; }