1*88Sbill /* kern_synch.c 3.2 10/14/12 */ 233Sbill 333Sbill #include "../h/param.h" 433Sbill #include "../h/systm.h" 533Sbill #include "../h/dir.h" 633Sbill #include "../h/user.h" 733Sbill #include "../h/proc.h" 833Sbill #include "../h/file.h" 933Sbill #include "../h/inode.h" 1033Sbill #include "../h/vm.h" 1133Sbill #include "../h/pte.h" 1233Sbill 1333Sbill #ifdef FASTVAX 1433Sbill asm(" .globl _eintr"); 1533Sbill #endif 1633Sbill 1733Sbill #define SQSIZE 0100 /* Must be power of 2 */ 1833Sbill #define HASH(x) (( (int) x >> 5) & (SQSIZE-1)) 1933Sbill struct proc *slpque[SQSIZE]; 2033Sbill 2133Sbill /* 2233Sbill * Give up the processor till a wakeup occurs 2333Sbill * on chan, at which time the process 2433Sbill * enters the scheduling queue at priority pri. 2533Sbill * The most important effect of pri is that when 2633Sbill * pri<=PZERO a signal cannot disturb the sleep; 2733Sbill * if pri>PZERO signals will be processed. 2833Sbill * Callers of this routine must be prepared for 2933Sbill * premature return, and check that the reason for 3033Sbill * sleeping has gone away. 3133Sbill */ 3233Sbill sleep(chan, pri) 3333Sbill caddr_t chan; 3433Sbill { 3533Sbill register struct proc *rp; 3633Sbill register s, h; 3733Sbill 3833Sbill rp = u.u_procp; 3933Sbill s = spl6(); 4033Sbill if (chan==0 || rp->p_stat != SRUN || rp->p_rlink) 4133Sbill panic("sleep"); 4233Sbill rp->p_stat = SSLEEP; 4333Sbill rp->p_wchan = chan; 4433Sbill rp->p_slptime = 0; 4533Sbill rp->p_pri = pri; 4633Sbill h = HASH(chan); 4733Sbill rp->p_link = slpque[h]; 4833Sbill slpque[h] = rp; 4933Sbill if(pri > PZERO) { 5033Sbill if(rp->p_sig && issig()) { 5133Sbill rp->p_wchan = 0; 5233Sbill rp->p_stat = SRUN; 5333Sbill slpque[h] = rp->p_link; 5433Sbill VOID spl0(); 5533Sbill goto psig; 5633Sbill } 5733Sbill VOID spl0(); 5833Sbill if(runin != 0) { 5933Sbill runin = 0; 6033Sbill wakeup((caddr_t)&runin); 6133Sbill } 6233Sbill swtch(); 6333Sbill if(rp->p_sig && issig()) 6433Sbill goto psig; 6533Sbill } else { 6633Sbill VOID spl0(); 6733Sbill swtch(); 6833Sbill } 6933Sbill splx(s); 7033Sbill return; 7133Sbill 7233Sbill /* 7333Sbill * If priority was low (>PZERO) and 7433Sbill * there has been a signal, 7533Sbill * execute non-local goto to 7633Sbill * the qsav location. 7733Sbill * (see trap1/trap.c) 7833Sbill */ 7933Sbill psig: 8033Sbill #ifndef FASTVAX 8133Sbill longjmp(u.u_qsav); 8233Sbill #else 8333Sbill asm(".set U_SSAV,140"); 8433Sbill asm("movl _u+U_SSAV,fp"); 8533Sbill asm("movl _u+U_SSAV+4,sp"); 8633Sbill asm("movl _u+U_SSAV+8,r11"); 8733Sbill u.u_error = EINTR; 8833Sbill asm("jmp _eintr"); 8933Sbill #endif 9033Sbill /*NOTREACHED*/ 9133Sbill } 9233Sbill 9333Sbill /* 9433Sbill * Wake up all processes sleeping on chan. 9533Sbill */ 9633Sbill wakeup(chan) 9733Sbill register caddr_t chan; 9833Sbill { 9933Sbill register struct proc *p, *q; 10033Sbill register i; 10133Sbill int s; 10233Sbill 10333Sbill s = spl6(); 10433Sbill i = HASH(chan); 10533Sbill restart: 10633Sbill p = slpque[i]; 10733Sbill q = NULL; 10833Sbill while(p != NULL) { 10933Sbill if (p->p_rlink || p->p_stat != SSLEEP) 11033Sbill panic("wakeup"); 11133Sbill if (p->p_wchan==chan && p->p_stat!=SZOMB) { 11233Sbill if (q == NULL) 11333Sbill slpque[i] = p->p_link; 11433Sbill else 11533Sbill q->p_link = p->p_link; 11633Sbill p->p_wchan = 0; 11733Sbill p->p_slptime = 0; 11833Sbill /* OPTIMIZED INLINE EXPANSION OF setrun(p) */ 11933Sbill p->p_stat = SRUN; 12033Sbill if (p->p_flag & SLOAD) { 12133Sbill #ifndef FASTVAX 12233Sbill p->p_link = runq; 12333Sbill runq = p->p_link; 12433Sbill #else 12533Sbill setrq(p); 12633Sbill #endif 12733Sbill } 12833Sbill if(p->p_pri < curpri) 12933Sbill runrun++; 13033Sbill if(runout != 0 && (p->p_flag&SLOAD) == 0) { 13133Sbill runout = 0; 13233Sbill wakeup((caddr_t)&runout); 13333Sbill } 13433Sbill /* END INLINE EXPANSION */ 13533Sbill goto restart; 13633Sbill } 13733Sbill q = p; 13833Sbill p = p->p_link; 13933Sbill } 14033Sbill splx(s); 14133Sbill } 14233Sbill 14333Sbill #ifdef FASTVAX 14433Sbill /* 14533Sbill * Initialize the (doubly-linked) run queues 14633Sbill * to be empty. 14733Sbill */ 14833Sbill rqinit() 14933Sbill { 15033Sbill register int i; 15133Sbill 15233Sbill for (i = 0; i < NQS; i++) 15333Sbill qs[i].ph_link = qs[i].ph_rlink = (struct proc *)&qs[i]; 15433Sbill } 15533Sbill #endif 15633Sbill 15733Sbill /* 15833Sbill * Set the process running; 15933Sbill * arrange for it to be swapped in if necessary. 16033Sbill */ 16133Sbill setrun(p) 16233Sbill register struct proc *p; 16333Sbill { 16433Sbill register caddr_t w; 16533Sbill register s; 16633Sbill 16733Sbill s = spl6(); 16833Sbill switch (p->p_stat) { 16933Sbill 17033Sbill case 0: 17133Sbill case SWAIT: 17233Sbill case SRUN: 17333Sbill case SZOMB: 17433Sbill default: 17533Sbill panic("setrun"); 17633Sbill 17733Sbill case SSLEEP: 17833Sbill if (w = p->p_wchan) { 17933Sbill wakeup(w); 18033Sbill splx(s); 18133Sbill return; 18233Sbill } 18333Sbill break; 18433Sbill 18533Sbill case SIDL: 18633Sbill case SSTOP: 18733Sbill break; 18833Sbill } 18933Sbill p->p_stat = SRUN; 19033Sbill if (p->p_flag & SLOAD) 19133Sbill setrq(p); 19233Sbill splx(s); 19333Sbill if(p->p_pri < curpri) 19433Sbill runrun++; 19533Sbill if(runout != 0 && (p->p_flag&SLOAD) == 0) { 19633Sbill runout = 0; 19733Sbill wakeup((caddr_t)&runout); 19833Sbill } 19933Sbill } 20033Sbill 20133Sbill /* 20233Sbill * Set user priority. 20333Sbill * The rescheduling flag (runrun) 20433Sbill * is set if the priority is better 20533Sbill * than the currently running process. 20633Sbill */ 20733Sbill setpri(pp) 20833Sbill register struct proc *pp; 20933Sbill { 21033Sbill register p; 21133Sbill 21233Sbill p = (pp->p_cpu & 0377)/16; 21333Sbill p += PUSER + pp->p_nice - NZERO; 21433Sbill if(p > 127) 21533Sbill p = 127; 21633Sbill if(p < curpri) 21733Sbill runrun++; 21833Sbill pp->p_usrpri = p; 21933Sbill return(p); 22033Sbill } 22133Sbill 22233Sbill /* 22333Sbill * Create a new process-- the internal version of 22433Sbill * sys fork. 22533Sbill * It returns 1 in the new process, 0 in the old. 22633Sbill */ 22733Sbill newproc(isvfork) 22833Sbill { 22933Sbill register struct proc *p; 23033Sbill register struct proc *rpp, *rip; 23133Sbill register int n; 23233Sbill 23333Sbill p = NULL; 23433Sbill /* 23533Sbill * First, just locate a slot for a process 23633Sbill * and copy the useful info from this process into it. 23733Sbill * The panic "cannot happen" because fork has already 23833Sbill * checked for the existence of a slot. 23933Sbill */ 24033Sbill retry: 24133Sbill mpid++; 24233Sbill if(mpid >= 30000) { 24333Sbill mpid = 0; 24433Sbill goto retry; 24533Sbill } 24633Sbill for(rpp = &proc[0]; rpp < &proc[NPROC]; rpp++) { 24733Sbill if(rpp->p_stat == NULL && p==NULL) 24833Sbill p = rpp; 24933Sbill if (rpp->p_pid==mpid || rpp->p_pgrp==mpid) 25033Sbill goto retry; 25133Sbill } 25233Sbill if ((rpp = p)==NULL) 25333Sbill panic("no procs"); 25433Sbill 25533Sbill /* 25633Sbill * make proc entry for new proc 25733Sbill */ 25833Sbill 25933Sbill rip = u.u_procp; 26033Sbill rpp->p_stat = SIDL; 26133Sbill rpp->p_clktim = 0; 26233Sbill rpp->p_flag = SLOAD | (rip->p_flag & SPAGI); 26333Sbill if (isvfork) { 26433Sbill rpp->p_flag |= SVFORK; 26533Sbill rpp->p_ndx = rip->p_ndx; 26633Sbill } else 26733Sbill rpp->p_ndx = rpp - proc; 26833Sbill rpp->p_uid = rip->p_uid; 26933Sbill rpp->p_pgrp = rip->p_pgrp; 27033Sbill rpp->p_nice = rip->p_nice; 27133Sbill rpp->p_textp = isvfork ? 0 : rip->p_textp; 27233Sbill rpp->p_pid = mpid; 27333Sbill rpp->p_ppid = rip->p_pid; 27433Sbill rpp->p_time = 0; 27533Sbill rpp->p_cpu = 0; 27633Sbill if (isvfork) { 27733Sbill rpp->p_tsize = rpp->p_dsize = rpp->p_ssize = 0; 27833Sbill rpp->p_szpt = clrnd(ctopt(UPAGES)); 27933Sbill forkstat.cntvfork++; 28033Sbill forkstat.sizvfork += rip->p_dsize + rip->p_ssize; 28133Sbill } else { 28233Sbill rpp->p_tsize = rip->p_tsize; 28333Sbill rpp->p_dsize = rip->p_dsize; 28433Sbill rpp->p_ssize = rip->p_ssize; 28533Sbill rpp->p_szpt = rip->p_szpt; 28633Sbill forkstat.cntfork++; 28733Sbill forkstat.sizfork += rip->p_dsize + rip->p_ssize; 28833Sbill } 28933Sbill rpp->p_rssize = 0; 29033Sbill rpp->p_wchan = 0; 29133Sbill rpp->p_slptime = 0; 29233Sbill rpp->p_aveflt = rip->p_aveflt; 29333Sbill rate.v_pgin += rip->p_aveflt; 29433Sbill rpp->p_faults = 0; 29533Sbill n = PIDHASH(rpp->p_pid); 29633Sbill p->p_idhash = pidhash[n]; 29733Sbill pidhash[n] = rpp - proc; 29833Sbill 29933Sbill /* 30033Sbill * make duplicate entries 30133Sbill * where needed 30233Sbill */ 30333Sbill 30433Sbill multprog++; 30533Sbill 30633Sbill for(n=0; n<NOFILE; n++) 30733Sbill if(u.u_ofile[n] != NULL) { 30833Sbill u.u_ofile[n]->f_count++; 30933Sbill if(!isvfork && u.u_vrpages[n]) 31033Sbill u.u_ofile[n]->f_inode->i_vfdcnt++; 31133Sbill } 31233Sbill 31333Sbill u.u_cdir->i_count++; 31433Sbill if (u.u_rdir) 31533Sbill u.u_rdir->i_count++; 31633Sbill /* 31733Sbill * Partially simulate the environment 31833Sbill * of the new process so that when it is actually 31933Sbill * created (by copying) it will look right. 32033Sbill */ 32133Sbill 32233Sbill rip->p_flag |= SKEEP; /* prevent parent from being swapped */ 32333Sbill 32433Sbill if (procdup(rpp, isvfork)) 32533Sbill return (1); 32633Sbill 32733Sbill spl6(); 32833Sbill rpp->p_stat = SRUN; 32933Sbill setrq(rpp); 33033Sbill spl0(); 331*88Sbill /* SSWAP NOT NEEDED IN THIS CASE AS u.u_pcb.pcb_sswap SUFFICES */ 33233Sbill /* rpp->p_flag |= SSWAP; */ 33333Sbill rip->p_flag &= ~SKEEP; 33433Sbill if (isvfork) { 33533Sbill u.u_procp->p_xlink = rpp; 33633Sbill u.u_procp->p_flag |= SNOVM; 33733Sbill while (rpp->p_flag & SVFORK) 33833Sbill sleep((caddr_t)rpp, PZERO - 1); 33933Sbill if ((rpp->p_flag & SLOAD) == 0) 34033Sbill panic("newproc vfork"); 34133Sbill uaccess(rpp, Vfmap, &vfutl); 34233Sbill u.u_procp->p_xlink = 0; 34333Sbill vpassvm(rpp, u.u_procp, &vfutl, &u, Vfmap); 34433Sbill for (n = 0; n < NOFILE; n++) 34533Sbill if (vfutl.u_vrpages[n]) { 34633Sbill if ((u.u_vrpages[n] = vfutl.u_vrpages[n] - 1) == 0) 34733Sbill if (--u.u_ofile[n]->f_inode->i_vfdcnt < 0) 34833Sbill panic("newproc i_vfdcnt"); 34933Sbill vfutl.u_vrpages[n] = 0; 35033Sbill } 35133Sbill u.u_procp->p_flag &= ~SNOVM; 35233Sbill rpp->p_ndx = rpp - proc; 35333Sbill rpp->p_flag |= SVFDONE; 35433Sbill wakeup((caddr_t)rpp); 35533Sbill } 35633Sbill return (0); 35733Sbill } 358