/*------------------------------------------------------------------------ * wakeup - Called by clock interrupt handler to awaken processes *------------------------------------------------------------------------ */ void wakeup(void) { /* Awaken all processes that have no more time to sleep */ while (nonempty(sleepq) && (firstkey(sleepq) <= 0)) { ready(dequeue(sleepq), RESCHED_NO); } if ( (slnonempty = nonempty(sleepq)) == TRUE ) { sltop = &queuetab[firstkey(sleepq)].qkey; } resched(); return; }
interrupt clkhandler(void) { /* Reset the timer to fire again */ clkupdate(platform.clkfreq / CLKTICKS_PER_SEC); /* Another clock tick passes. */ clkticks++; /* Update global second counter. */ if (clkticks >= CLKTICKS_PER_SEC) { clktime++; clkticks = 0; } /* If sleepq is not empty, decrement first key. */ /* If key reaches zero, call wakeup. */ if (nonempty(sleepq) && (--firstkey(sleepq) <= 0)) { wakeup(); // This no longer does a resched() call since we need to // clear our interrupts before doing a resched() } #ifdef FLUKE_ARM /* Acknowledge and clear the interrupt */ timer0->int_clr = 1; irq_handled(); #endif resched(); }
/** * Wakeup and ready all threads that have no more time to sleep */ void wakeup(void) { while (nonempty(sleepq) && (firstkey(sleepq) <= 0)) { ready(dequeue(sleepq), RESCHED_NO); } }
/** * Reschedule processor to highest priority ready thread. * Upon entry, thrcurrent gives current thread id. * Threadtab[thrcurrent].pstate gives correct NEXT state * for current thread if other than THRREADY. * @return OK when the thread is context switched back */ int resched(void) { uchar asid; /* address space identifier */ struct thrent *throld; /* old thread entry */ struct thrent *thrnew; /* new thread entry */ if (resdefer > 0) { /* if deferred, increase count & return */ resdefer++; return (OK); } throld = &thrtab[thrcurrent]; throld->intmask = disable(); if (THRCURR == throld->state) { if (nonempty(readylist) && (throld->prio > firstkey(readylist))) { restore(throld->intmask); return OK; } throld->state = THRREADY; insert(thrcurrent, readylist, throld->prio); } /* get highest priority thread from ready list */ thrcurrent = dequeue(readylist); thrnew = &thrtab[thrcurrent]; thrnew->state = THRCURR; /* change address space identifier to thread id */ asid = thrcurrent & 0xff; #if 0 // XXX Fix this later? asm("mtc0 %0, $10": :"r"(asid)); #endif restore(thrnew->intmask); ctxsw(&throld->stkptr, &thrnew->stkptr); /* old thread returns here when resumed */ restore(throld->intmask); return OK; }
/*------------------------------------------------------------------------ * resched_lab1 - Reschedule processor to highest priority eligible process *------------------------------------------------------------------------ */ void resched_lab1(void) /* Assumes interrupts are disabled */ { struct procent *ptold; /* Ptr to table entry for old process */ struct procent *ptnew; /* Ptr to table entry for new process */ /* If rescheduling is deferred, record attempt and return */ if (Defer.ndefers > 0) { Defer.attempt = TRUE; return; } /* Point to process table entry for the current (old) process */ ptold = &proctab[currpid]; if (ptold->prstate == PR_CURR) { /* Process remains eligible */ if (ptold->prprio > firstkey(readylist)) { return; } /* Old process will no longer remain current */ ptold->prstate = PR_READY; insert(currpid, readylist, ptold->prprio); } /* Force context switch to highest priority ready process */ currpid = dequeue(readylist); ptnew = &proctab[currpid]; ptnew->prstate = PR_CURR; preempt = QUANTUM; /* Reset time slice for process */ ctxsw(&ptold->prstkptr, &ptnew->prstkptr); // LAB 4Q3: Invoke the handleCallback handleCallback(); /* Old process returns here when resumed */ return; }
interrupt clkhandler(void) { //DEBUG //kprintf("Timer went off\n"); /* Reset the timer to fire again */ clkupdate(platform.clkfreq / CLKTICKS_PER_SEC); /* Another clock tick passes. */ clkticks++; msclkticks++; /* Update global second counter. */ if (clkticks >= CLKTICKS_PER_SEC) { clktime++; clkticks = 0; } /* Update global countdown for round robien reschedule */ if (msclkticks >= (CLKTICKS_PER_SEC/1000)) { rescheduleMSLeft -= 1; msclkticks = 0; } /* If sleepq is not empty, decrement first key. */ /* If key reaches zero, call wakeup. */ if (nonempty(sleepq) && (--firstkey(sleepq) <= 0)) { wakeup(); // This no longer does a resched() call since we need to // clear our interrupts before doing a resched() } /* Acknowledge and clear the interrupt */ timer0->int_clr = 1; irq_handled(); resched(); }
/*------------------------------------------------------------------------ * resched_lab2 - fair scheduler from lab2, need to set lab2flag according to specs * given in lab2 documentation on 503 course website. *------------------------------------------------------------------------ */ void resched_lab2(void) { uint32 currTime = clktimemsec; struct procent *ptold; /* Ptr to table entry for old process */ struct procent *ptnew; /* Ptr to table entry for new process */ /* If rescheduling is deferred, record attempt and return */ if (Defer.ndefers > 0) { Defer.attempt = TRUE; return; } uint32 addToTotalTime =0; /* Point to process table entry for the current (old) process */ ptold = &proctab[currpid]; //Update the total processing time for context switched out process // Handle the case where the counter overflows then get the absolute value of difference addToTotalTime = (currTime)-(ptold->prctxswintime); // if the old process id is not of null user then update its total CPU time // else ignore this step because prcpumsec of null user is already set to max to // force it to only execute if no other process is ready if(currpid != 0) ptold->prcpumsec = ptold->prcpumsec + addToTotalTime; // totest switches the key for the readylist queue to be tested based on the lab we are running. // For the lab3, its the priority of the process // and for lab 4 and 5 it's the prcpumsec, the cpu time given to the process int32 totest = ptold->prprio; // Here the totest will be set to the negation of prcpumsec // because we wan't to maintain using the insert function that // inserts elements in decreasing order. By this negation of prcpumsec would // cause the element with the least prcpumsec to be the first to be dequeud at the head. // Hence, we are followin the rules of the dynamic priority scheduling algorithm if(lab2flag == 4 || lab2flag == 5) totest =-(int32)ptold->prcpumsec; if (ptold->prstate == PR_CURR) { /* Process remains eligible */ if (totest > firstkey(readylist)) { ptold->prctxswintime = currTime; if(lab2flag ==5) reward_ready_waiting(); return; } /* Old process will no longer remain current */ if(lab2flag == 5) reward_ready_waiting(); ptold->prstate = PR_READY; // The only other place an insert happens is at the ready method // even there we have chosen to implement a similar strategy of choosing the value // of key based on the lab that we are dealing with. That is, either to insert // based on priority or the negation of the prcpumsec spent. insert(currpid, readylist, totest); currpid = dequeue(readylist); } else { //even if the process is in sleep state and calling a reschedule // we must reward the other processes // of course, as soon as the process that is dequeued is removed its key value // would also if(lab2flag ==5) reward_ready_waiting(); currpid = dequeue(readylist); } /* Force context switch to highest priority ready process */ ptnew = &proctab[currpid]; ptnew->prstate = PR_CURR; preempt = QUANTUM; /* Reset time slice for process */ //Update the context switch-in time for new process ptnew->prctxswintime = currTime; ctxsw(&ptold->prstkptr, &ptnew->prstkptr); // LAB 4Q3: Invoke the handleCallback handleCallback(); /* Old process returns here when resumed */ return; }