/*------------------------------------------------------------------------ * copyqueue - Move the internal queue linked list of pids from one * queue to another by pointing the internal list at the other queue's * first and last id's. Any contents in the destination queue will be * dequeued first, and the source queue head and tail will be linked to * make the source queue empty. *------------------------------------------------------------------------ */ void copyqueue(qid16 srcq, qid16 destq) { while(!isempty(destq)) dequeue(destq); qid16 firstid = firstid(srcq); qid16 lastid = lastid(srcq); firstid(srcq) = queuetail(srcq); lastid(srcq) = queuehead(srcq); firstid(destq) = firstid; queuetab[firstid].qprev = queuehead(destq); lastid(destq) = lastid; queuetab[lastid].qnext = queuetail(destq); }
/*------------------------------------------------------------------------ * insert - Insert a process into a queue in descending key order *------------------------------------------------------------------------ */ status insert_real( pid32 pid, /* ID of process to insert */ qid16 q, /* ID of queue to use */ double key /* Key for the inserted process */ ) { int16 curr; /* Runs through items in a queue*/ int16 prev; /* Holds previous node index */ if (isbadqid(q) || isbadpid(pid)) { return SYSERR; } curr = firstid(q); while (queuetab[curr].real_qkey >= key) { curr = queuetab[curr].qnext; } /* Insert process between curr node and previous node */ prev = queuetab[curr].qprev; /* Get index of previous node */ queuetab[pid].qnext = curr; queuetab[pid].qprev = prev; queuetab[pid].real_qkey = key; queuetab[prev].qnext = pid; queuetab[curr].qprev = pid; return OK; }
/*------------------------------------------------------------------------ * strtclk -- take the clock out of defer mode *------------------------------------------------------------------------ */ strtclk() { STATWORD ps; int makeup; int next; disable(ps); if ( defclk<=0 || --defclk>0 ) { restore(ps); return; } makeup = clkdiff; preempt -= makeup; clkdiff = 0; if ( slnempty ) { for (next=firstid(clockq) ; next < NPROC && q[next].qkey < makeup ; next=q[next].qnext) { makeup -= q[next].qkey; q[next].qkey = 0; } if (next < NPROC) q[next].qkey -= makeup; wakeup(); } if ( preempt <= 0 ) resched(); restore(ps); }
/*----------------------------------------------------------------------- * clkhandler - high level clock interrupt handler *----------------------------------------------------------------------- */ void clkhandler() { static uint32 count1000 = 1000; /* variable to count 1000ms */ volatile struct am335x_timer1ms *csrptr = 0x44E31000; /* Pointer to timer CSR */ int32 slot; /* Slot in ARP cache */ /* If there is no interrupt, return */ if((csrptr->tisr & AM335X_TIMER1MS_TISR_OVF_IT_FLAG) == 0) { return; } /* Acknowledge the interrupt */ csrptr->tisr = AM335X_TIMER1MS_TISR_OVF_IT_FLAG; /* Decrement 1000ms counter */ count1000--; /* After 1 sec, increment clktime */ if(count1000 == 0) { clktime++; count1000 = 1000; /* code to check ARP entry */ for (slot=0; slot < ARP_SIZ; slot++) { if ((clktime - arpcache[slot].clktime) > 300) { arpcache[slot].arstate = AR_FREE; } } } /* check if sleep queue is empty */ if(!isempty(sleepq)) { /* sleepq nonempty, decrement the key of */ /* topmost process on sleepq */ if((--queuetab[firstid(sleepq)].qkey) == 0) { wakeup(); } } /* Decrement the preemption counter */ /* Reschedule if necessary */ if((--preempt) == 0) { preempt = QUANTUM; resched(); } }
pid32 getfirst(qid16 qid) { if(isbadqid(qid)) { return EMPTY; } return getitem(firstid(qid)); }
/*------------------------------------------------------------------------ * clkhandler - high level clock interrupt handler *------------------------------------------------------------------------ */ void clkhandler() { static uint32 count1000 = 1000; /* Count to 1000 ms */ /* Decrement the ms counter, and see if a second has passed */ struct procent *prptr = &proctab[currpid]; //pointer to the table entry for current process clktimefine++; //incrementing the clktimefine if(prptr->alrmfunc != NULL && prptr->mysigalrmtime >= 0) { // check if the function isn't null and the saved sigalrmtime in the process table isn't negative if(clktimefine >= prptr->mysigalrmtime){ //if the current clktimefine is greater than the saved sigalrmtime prptr->alrmfunc(); //call the function pointing to callback function prptr->alrmfunc = NULL; //set the ptr to function as NULL, so that the process can't activate another callback function } } else if(prptr->xcpufunc != NULL){ // check if the function isn't null if(prptr->prcpuused >= prptr->optarg){ //check if the cpuused by the process exceeds the optional argument prptr->xcpufunc(); //call the function pointing to callback function prptr->xcpufunc = NULL; //reset the the function ptr to NULL so that the process can't activate another callback function } } if((--count1000) <= 0) { /* One second has passed, so increment seconds count */ clktime++; /* Reset the local ms counter for the next second */ count1000 = 1000; } /* Handle sleeping processes if any exist */ if(!isempty(sleepq)) { /* Decrement the delay for the first process on the */ /* sleep queue, and awaken if the count reaches zero */ if((--queuetab[firstid(sleepq)].qkey) <= 0) { wakeup(); } } /* Decrement the preemption counter, and reschedule when the */ /* remaining time reaches zero */ if((--preempt) <= 0) { preempt = QUANTUM; resched(); } }
/*------------------------------------------------------------------------ * 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[firstid(sleepq)].qkey; } resched(); return; }
/*------------------------------------------------------------------------ * reward_ready_waiting - this method promotes all the processes on the readylist by giving them each an * increment of 6ms to their keys. We do this so that a process that has been waiting for a long time * would at least get a chance to execute if it had executed the cpu for a long time. * All processes in this ready list are processes that were not selected in this run of resched * as the next process to execute, despite being ready. Hence, this loss of opportunity is * defined as waiting in our context. * *------------------------------------------------------------------------ */ void reward_ready_waiting() { qid16 curr; /* Runs through items in a queue*/ qid16 prev; /* Holds previous node index */ struct procent * prptr; curr = firstid(readylist); while (curr != queuetail(readylist)) { prptr = &proctab[curr]; // don't promote prnull process if(curr!=0) queuetab[curr].qkey +=6; curr = queuetab[curr].qnext; } }
/* insert a process into a queue in descending key order */ status insert(pid32 pid, qid16 q, int32 key) { int16 curr, prev; if (isbadqid(q) || isbadpid(pid)) { return SYSERR; } curr = firstid(q); while (queuetab[curr].qkey >= key) { curr = queuetab[curr].qnext; } prev = queuetab[curr].qprev; queuetab[pid].qnext = curr; queuetab[pid].qprev = prev; queuetab[pid].qkey = key; queuetab[prev].qnext = pid; queuetab[curr].qprev = pid; return OK; }
/*------------------------------------------------------------------------ * unsleep - Remove a process from the sleep queue prematurely by * adjusting the delay of successive processes *------------------------------------------------------------------------ */ syscall unsleep( pid32 pid /* ID of process to remove */ ) { intmask mask; /* saved interrupt mask */ struct procent *prptr; /* ptr to process' table entry */ pid32 pidnext; /* ID of process on sleep queue */ /* that follows the process that*/ /* is being removed */ mask = disable(); if (isbadpid(pid)) { restore(mask); return SYSERR; } /* Verify that candidate process is on the sleep queue */ prptr = &proctab[pid]; if ((prptr->prstate!=PR_SLEEP) && (prptr->prstate!=PR_RECTIM)) { restore(mask); return SYSERR; } /* Increment delay of next process if such a process exists */ pidnext = queuetab[pid].qnext; if (pidnext < NPROC) { queuetab[pidnext].qkey += queuetab[pid].qkey; } if ( nonempty(sleepq) ) { sltop = &queuetab[firstid(sleepq)].qkey; slnonempty = TRUE; } else { slnonempty = FALSE; } getitem(pid); /* unlink process from queue */ restore(mask); return OK; }
/*------------------------------------------------------------------------ * clkhandler - high level clock interrupt handler *------------------------------------------------------------------------ */ void clkhandler() { static uint32 count1000 = 1000; /* Count to 1000 ms */ /* Decrement the ms counter, and see if a second has passed */ myglobalclock++; if((--count1000) <= 0) { /* One second has passed, so increment seconds count */ clktime++; /* Reset the local ms counter for the next second */ count1000 = 1000; } /* Handle sleeping processes if any exist */ if(!isempty(sleepq)) { /* Decrement the delay for the first process on the */ /* sleep queue, and awaken if the count reaches zero */ if((--queuetab[firstid(sleepq)].qkey) <= 0) { wakeup(); } } /* Decrement the preemption counter, and reschedule when the */ /* remaining time reaches zero */ if((--preempt) <= 0) { preempt = QUANTUM; resched(); } }
void clkhandler() { static uint32 count1000 = 1000; /* variable to count 1000ms */ volatile struct am335x_timer1ms *csrptr = 0x44E31000; /* Pointer to timer CSR */ /* If there is no interrupt, return */ if((csrptr->tisr & AM335X_TIMER1MS_TISR_OVF_IT_FLAG) == 0) { return; } LOG2(DEBUG_VERBOSE,DEBUG_SCHEDULER, "\nClkInt: a clock tick is being handled, ms was %d, secs were %d\n", 1000-count1000,clktime); /* Acknowledge the interrupt */ csrptr->tisr = AM335X_TIMER1MS_TISR_OVF_IT_FLAG; /* Decrement 1000ms counter */ count1000--; /* After 1 sec, increment clktime */ if(count1000 == 0) { clktime++; count1000 = 1000; /* if EV_DTIMER env var is turned on then run the associated debugging output on a psuedo timer */ if(envtab[EV_DTIMER].val && !(clktime%(envtab[EV_DTIMER].val))) { dtimer(); } } /* if still NULL, update the pointer to the millisecond tracker so millisecond timestamps can be generated */ if(!clktimems) { clktimems = &count1000; } /* check if sleep queue is empty */ if(!isempty(sleepq)) { /* sleepq nonempty, decrement the key of */ /* topmost process on sleepq */ if((--queuetab[firstid(sleepq)].qkey) == 0) { wakeup(); } } /* Decrement the preemption counter */ /* Reschedule if necessary */ if((--preempt) == 0) { LOG2(DEBUG_VERBOSE,DEBUG_SCHEDULER,"\nClkInt: preemption time \n"); preempt = QUANTUM; resched(); } }
/*------------------------------------------------------------------------ * resched - Reschedule processor to highest priority eligible process *------------------------------------------------------------------------ */ void resched(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->is_real_proc==1) { if(ptold->prstate == PR_CURR){ if(ptold->real_prio > queuetab[firstid(60)].real_qkey) { return; } ptold->prstate = PR_READY; insert_real(currpid, readylist[60], (double)(ptold->real_prio)); } } //if the process is currently executing i.e it is executing currently, then it is considered as CPU bound process else{ if (ptold->prstate == PR_CURR) { /* Process remains eligible */ /*if (ptold->prprio > firstkey(readylist)) { return; }*/ /* Old process will no longer remain current */ if(currpid!=NULLPROC){ ptold->prprio = tstab[ptold->prprio].ts_tqexp; } ptold->prstate = PR_READY; enqueue(currpid, readylist[ptold->prprio]); } //if the process is in sleep state, it is considered to be as an I/O bound process else if(ptold->prstate == PR_SLEEP){ ptold->prprio = tstab[ptold->prprio].ts_slpret; } } /* Force context switch to highest priority ready process */ //Now find the Process with the highest Priority from the ready list and then assign it as the currpid int i; for(i=60;i>=0;i--){ if(!isempty(readylist[i])) { //enqueue(currpid, readylist[ptold->prprio]); currpid = dequeue(readylist[i]); if(currpid ==NULLPROC) { if(!isempty(readylist[i])) { enqueue(currpid, readylist[i]); currpid = dequeue(readylist[i]); } } break; } } ptnew = &proctab[currpid]; if(ptnew->is_real_proc==1) { preempt = 70; } else { preempt = tstab[ptnew->prprio].ts_quantum; /* Reset time slice for process */ } ptnew->prstate = PR_CURR; ctxsw(&ptold->prstkptr, &ptnew->prstkptr); //run the call back function ptnew = &proctab[currpid]; if(ptnew->asigcb == 0){ if(proctab[currpid].func!=NULL && proctab[currpid].prhasmsg==TRUE) { *(proctab[currpid].abuf)= proctab[currpid].prmsg; proctab[currpid].prhasmsg = FALSE; (*proctab[currpid].func)(); // proctab[currpid].prhasmsg = FALSE; } } if(ptnew->asigcb ==1) { if(ptnew->optarg == 0) { if(ptnew->arecvfunc!=NULL && ptnew->prhasmsg==TRUE) { (*ptnew->arecvfunc)(); // ptnew->prhasmsg = FALSE; } } // if(ptnew->optarg>0) // { // if(ptnew->alarmfunc!=NULL && ptnew->prhasmsg==TRUE) // { if(ptnew->alarm_time>0) { if(myglobalclock >= ptnew->alarm_time) { ptnew->alarm_time = -1; (*ptnew->alarmfunc)(); } } // ptnew->prhasmsg = FALSE; // } // } // } } /* Old process returns here when resumed */ return; }
/*----------------------------------------------------------------------- * clkhandler - high level clock interrupt handler *----------------------------------------------------------------------- */ void clkhandler() { struct arpentry *arptr; /* variable to access arpcache */ static uint32 arpcount1000 = 1000; /* variable to count 1000ms for arpcache */ static uint32 count1000 = 1000; /* variable to count 1000ms */ volatile struct am335x_timer1ms *csrptr = 0x44E31000; /* Pointer to timer CSR */ /* Checks arpcache entry time */ int i; arpcount1000--; if(arpcount1000 == 0) { for (i = 0; i < ARP_SIZ; i++) { arptr = &arpcache[i]; if(arptr->arclk >= 300) { arptr->arstate = AR_FREE; arptr->arclk = 0; } else arptr->arclk++; } arpcount1000 = 1000; } /* If there is no interrupt, return */ if((csrptr->tisr & AM335X_TIMER1MS_TISR_OVF_IT_FLAG) == 0) { return; } /* Acknowledge the interrupt */ csrptr->tisr = AM335X_TIMER1MS_TISR_OVF_IT_FLAG; /* Decrement 1000ms counter */ count1000--; /* After 1 sec, increment clktime */ if(count1000 == 0) { clktime++; count1000 = 1000; } /* check if sleep queue is empty */ if(!isempty(sleepq)) { /* sleepq nonempty, decrement the key of */ /* topmost process on sleepq */ if((--queuetab[firstid(sleepq)].qkey) == 0) { wakeup(); } } /* Decrement the preemption counter */ /* Reschedule if necessary */ if((--preempt) == 0) { preempt = QUANTUM; resched(); } }