/** * @brief Signals the occurrence of an event on all applicable devices. * This function should be called on timer interrupts to determine that * the interrupt corresponds to the event frequency of a device. If the * interrupt corresponded to the interrupt frequency of a device, this * function should ensure that the task is made ready to run */ void dev_update(unsigned long millis __attribute__((unused))) { disable_interrupts(); int i = 0; bool_e flag = FALSE; for (i = 0; i < NUM_DEVICES; i++) { if (devices[i].next_match <= millis) { devices[i].next_match += dev_freq[i]; tcb_t* sleep_queue = devices[i].sleep_q; if (sleep_queue != 0) { flag = TRUE; while(sleep_queue != 0) { runqueue_add(sleep_queue,sleep_queue->native_prio); sleep_queue = sleep_queue->sleep_queue; } devices[i].sleep_q = 0; } } } if(flag == TRUE) dispatch_save(); enable_interrupts(); }
/** * @brief Signals the occurrence of an event on all applicable devices. * This function should be called on timer interrupts to determine that * the interrupt corresponds to the event frequency of a device. If the * interrupt corresponded to the interrupt frequency of a device, this * function should ensure that the task is made ready to run */ void dev_update(unsigned long millis) { disable_interrupts(); int i; for (i = 0; i < NUM_DEVICES; i++) { // if a devices task match the time the add all sleep takes to the run queue if (devices[i].next_match <= millis) { while (devices[i].sleep_queue) { //print_sleep_queue(); tcb_t* head = devices[i].sleep_queue; runqueue_add(head, head->cur_prio); // go to the next sleep task devices[i].sleep_queue = head->sleep_queue; // set the current task's next to null head->sleep_queue = NULL; } // update next match devices[i].next_match += dev_freq[i]; } } // do context switch after the devices state are updated dispatch_save(); }
/* c_irq_handler - custom irq handler called by assembly irq handler after state has been saved/restored appropriately. Parameters: None */ void c_irq_handler(){ unsigned stamp; mmio_t oscr = (mmio_t)OSCR; mmio_t ossr = (mmio_t)OSSR; mmio_t osmr0 = (mmio_t)OSMR_0; if(*ossr & OSSR_M0){ //keep global time by checking if oscr has overlapped start_time if(lastoscr<start_time && *oscr>=start_time){ rollovercount++; } lastoscr = *oscr; dotime(&stamp); //set next interrupt for 10ms later *osmr0 = *oscr + OSTMR_FREQ/100; //unset interrupts *ossr |= OSSR_M0; //update devices and switch to highest prio task dev_update((unsigned long)stamp); dispatch_save(); } if(*ossr & OSSR_M1) *ossr |= OSSR_M1; if(*ossr & OSSR_M2) *ossr |= OSSR_M2; if(*ossr & OSSR_M3) *ossr |= OSSR_M3; }
void irq_handler(void) { disable_interrupts(); irq_time ++; dev_update(irq_time); reg_set(OSTMR_OSSR_ADDR, OSTMR_OSSR_M0); reg_write(OSTMR_OSCR_ADDR, TIMER_CLEAR); /* Wait for timer to reset */ while(((volatile unsigned)reg_read(INT_ICPR_ADDR) >>INT_OSTMR_0) & 0x1); dispatch_save(); }
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; }
/** * @brief Signals the occurrence of an event on all applicable devices. * This function should be called on timer interrupts to determine that * the interrupt corresponds to the event frequency of a device. If the * interrupt corresponded to the interrupt frequency of a device, this * function should ensure that the task is made ready to run */ void dev_update(unsigned long millis ) { disable_interrupts(); //check each device for an event int i; int have_some = 0; //if(debug_enabled ==1) puts("dev_update::checking \n"); for( i = 0; i < NUM_DEVICES - 1; i++) { if( millis >= devices[i].next_match) { if(debug_enabled ==1) printf("dev_update::waking up %d\n",i); //wake up device! //make tasks ready to run //for each sleeper tcb_t* sleepy = devices[i].sleep_queue; tcb_t* next; while( sleepy != 0) { //WAKE UP SLEEPY runqueue_add(sleepy, sleepy->cur_prio); if(debug_enabled == 1)printf("dev_update...dev = %d:::woke up (prio)= %d::next = %x\n", i, (unsigned)sleepy->cur_prio, (unsigned)sleepy->sleep_queue); //another sleeper? next = sleepy->sleep_queue; sleepy->sleep_queue = 0; sleepy = next; //set flag that there is a reason to update have_some = 1; } //set next match point in millis devices[i].next_match += dev_freq[i]; } } //re-evaluate our priorities, if we have a reason to if(have_some == 1 ) dispatch_save(); enable_interrupts(); }
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; }