# /* * Copyright 1975 Bell Telephone Laboratories Inc */ #include "param.h" #include "user.h" #include "proc.h" #include "systm.h" #include "file.h" #include "inode.h" #include "buf.h" #ifdef BGOPTION #include "tty.h" #endif #ifdef BGOPTION int swflg,swwait; #endif /* * Give up the processor till a wakeup occurs * on chan, at which time the process resumes execution. * 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; rp = u.u_procp; s = spl7(); #ifdef BGOPTION rp->p_stat = ((pri == PRIBIO) || (pri == TTOPRI)) ? SWAIT : SSLEEP; #endif BGOPTION #ifndef BGOPTION rp->p_stat = SSLEEP; #endif rp->p_wchan = chan; spl0(); if(pri >= 0) { if(issig()) goto psig; #ifdef BGOPTION swtch(1); #endif #ifndef BGOPTION idle(); #endif if(issig()) goto psig; } else #ifdef BGOPTION swtch(1); #endif #ifndef BGOPTION idle(); #endif rstps(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: rp->p_stat = SRUN; retu(u.u_qsav); } /* * Wake up process if sleeping on chan. */ wakeup(chan) { register struct proc *p; #ifdef BGOPTION for(p = &proc[0]; p < &proc[NPROC+2]; p++) { if(p->p_wchan == chan) setrun(p); } #endif #ifndef BGOPTION p = &proc[cpid]; if(p->p_wchan == chan) setrun(p); #endif } /* * Set the process running; */ setrun(p) { register struct proc *rp; rp = p; rp->p_wchan = 0; rp->p_stat = SRUN; } /* * Create a new process-- the internal version of * sys fork. * It returns 1 in the new process. * How this happens is rather hard to understand. * The essential fact is that the new process is created * in such a way that appears to have started executing * in the same call to newproc as the parent; * but in fact the code that runs is that of swtch. * The subtle implication of the returned value of swtch * (see above) is that this is the value that newproc's * caller in the new process sees. */ newproc() { register struct proc *rpp; register *rip; /* * make duplicate entries * where needed */ for(rip = &u.u_ofile[0]; rip < &u.u_ofile[NOFILE];) if((rpp = *rip++) != NULL) rpp->f_count++; u.u_cdir->i_count++; savu(u.u_ssav); /* save state of parent */ #ifdef BGOPTION retu(u.u_rsav); #endif rip = u.u_procp; rip->p_stat = SIDL; #ifdef BGOPTION swap(B_WRITE,cpid); #endif #ifndef BGOPTION swap(B_WRITE); #endif cpid++; rpp = &proc[cpid]; rpp->p_stat = SRUN; u.u_procp = rpp; #ifdef BGOPTION retu(u.u_ssav); #endif return(1); /* return to child */ } #ifdef BGOPTION swtch(aa) { register struct proc *p,*p1; register s; static int a; if(bgproc == 0) { if(aa) idle(); return; } if(issig()) psig(); s = spl7(); if(swflg) { swwait = 1; rstps(s); return; } swflg = 1; rstps(s); a = aa; loop: p = &proc[cpid]; if(p->p_stat == SSLEEP) { p1 = bgproc; if(p1->p_stat == SRUN) p = p1; else { idle(); swflg = 0; return; } } p1 = u.u_procp; if((p == p1) || (cpid == (NPROC-1))) { swflg = 0; return; } savu(u.u_ssav); retu(u.u_rsav); u.u_procp = &proc[NPROC+1]; s = (p == bgproc) ? NPROC : cpid; swap(B_WRITE,(s == cpid) ? NPROC : cpid); swap(B_READ,s); retu(u.u_ssav); u.u_procp = &proc[s]; setrun(p); s = spl7(); if(swwait) { swwait = 0; rstps(s); goto loop; } swflg = 0; swwait = 0; rstps(s); } #endif