/* * Give up the processor till a wakeup occurs * on chan, at which time the process * enters the scheduling queue at priority pri. * The most important effect of pri is that when * pri<0 a signal cannot disturb the sleep; * if pri>=0 signals will be processed. * Callers of this routine must be prepared for * premature return, and check that the reason for * sleeping has gone away. */ sleep(chan, pri) { register *rp, s; s = PS->integ; rp = u.u_procp; if(pri >= 0) { if(issig()) goto psig; spl6(); rp->p_wchan = chan; rp->p_stat = SWAIT; rp->p_pri = pri; spl0(); if(runin != 0) { runin = 0; wakeup(&runin); } swtch(); if(issig()) goto psig; } else { spl6(); rp->p_wchan = chan; rp->p_stat = SSLEEP; rp->p_pri = pri; spl0(); swtch(); } PS->integ = s; return; /* * If priority was low (>=0) and * there has been a signal, * execute non-local goto to * the qsav location. * (see trap1/trap.c) */ psig: aretu(u.u_qsav); }
/* * This routine is called to reschedule the CPU. * if the calling process is not in RUN state, * arrangements for it to restart must have * been made elsewhere, usually by calling via sleep. */ swtch() { static struct proc *p; register i, n; register struct proc *rp; if(p == NULL) p = &proc[0]; /* * Remember stack of caller */ savu(u.u_rsav); /* * Switch to scheduler's stack */ retu(proc[0].p_addr); loop: runrun = 0; rp = p; p = NULL; n = 128; /* * Search for highest-priority runnable process */ i = NPROC; do { rp++; if(rp >= &proc[NPROC]) rp = &proc[0]; if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)!=0) { if(rp->p_pri < n) { p = rp; n = rp->p_pri; } } } while(--i); /* * If no process is runnable, idle. */ if(p == NULL) { p = rp; idle(); goto loop; } rp = p; curpri = n; /* Switch to stack of the new process and set up * his segmentation registers. */ retu(rp->p_addr); sureg(); /* * If the new process paused because it was * swapped out, set the stack level to the last call * to savu(u_ssav). This means that the return * which is executed immediately after the call to aretu * actually returns from the last routine which did * the savu. * * You are not expected to understand this. */ if(rp->p_flag&SSWAP) { rp->p_flag =& ~SSWAP; aretu(u.u_ssav); } /* The value returned here has many subtle implications. * See the newproc comments. */ return(1); }
/* * This routine is called to reschedule the CPU. * if the calling process is not in RUN state, * arrangements for it to restart must have * been made elsewhere, usually by calling via sleep. */ swtch() { // static variable p points to the last process that swtch selected. static struct proc *p; register i, n; register struct proc *rp; // if this is the first time switch is called, then p points to the system process. if(p == NULL) p = &proc[0]; /* * Remember stack of caller */ savu(u.u_rsav); /* * Switch to scheduler's stack */ // proc[0] is system process that is used for scheduling. It is initialized // when system boots. retu(proc[0].p_addr); loop: // runrun is set when there is a process that has the higher priority // than currently running process. runrun = 0; // rp points to the current process so that the swtch selects a process // that appears to after current process if there are more than two processes // that have the highest priority. rp = p; // after finishing the loop below, p will point the highest-priority // runnable process. p = NULL; // 128 is the lowest priority. All processes in the system can have // priority smaller than 128. n = 128; /* * Search for highest-priority runnable process */ i = NPROC; do { rp++; // for circular search if(rp >= &proc[NPROC]) rp = &proc[0]; // finds runnable and in-memory process if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)!=0) { // compares it with the candidate. if new one wins updates candidate. if(rp->p_pri < n) { p = rp; n = rp->p_pri; } } } while(--i); /* * If no process is runnable, idle. */ if(p == NULL) { p = rp; idle(); goto loop; } rp = p; // curpri is global variable that represents the priority of running process. curpri = n; /* * Switch to stack of the new process and set up * his segmentation registers. */ retu(rp->p_addr); sureg(); /* * If the new process paused because it was * swapped out, set the stack level to the last call * to savu(u_ssav). This means that the return * which is executed immediately after the call to aretu * actually returns from the last routine which did * the savu. * * You are not expected to understand this. */ // TODO: what does it mean? // when the swapped-out data comes back into the memory again? if(rp->p_flag&SSWAP) { rp->p_flag =& ~SSWAP; aretu(u.u_ssav); } /* * The value returned here has many subtle implications. * See the newproc comments. */ return(1); }