X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/0981aef03352a6adba15ca1429f4e2d1cc467cd6..5c723b90ceb41c125105d2a818e372ee31f2e522:/usr/src/sys/kern/kern_proc.c diff --git a/usr/src/sys/kern/kern_proc.c b/usr/src/sys/kern/kern_proc.c index b7b2e1f1b6..cec7926fad 100644 --- a/usr/src/sys/kern/kern_proc.c +++ b/usr/src/sys/kern/kern_proc.c @@ -1,884 +1,69 @@ -/* kern_proc.c 4.47 82/11/02 */ - -#include "../h/param.h" -#include "../h/systm.h" -#include "../h/map.h" -#include "../h/dir.h" -#include "../h/user.h" -#include "../h/kernel.h" -#include "../h/proc.h" -#include "../h/buf.h" -#include "../h/reg.h" -#include "../h/inode.h" -#include "../h/seg.h" -#include "../h/acct.h" -#include -#include "../h/pte.h" -#include "../h/vm.h" -#include "../h/text.h" -#include "../h/psl.h" -#include "../h/file.h" -#include "../h/quota.h" -#include "../h/descrip.h" -#include "../h/uio.h" -#include "../h/mbuf.h" - -gethostid() -{ - - u.u_r.r_val1 = hostid; -} - -sethostid() -{ - struct a { - int hostid; - } *uap = (struct a *)u.u_ap; - - if (suser()) - hostid = uap->hostid; -} - -gethostname() -{ - register struct a { - char *hostname; - int len; - } *uap = (struct a *)u.u_ap; - register u_int len; - - len = uap->len; - if (len > hostnamelen) - len = hostnamelen; - if (copyout((caddr_t)hostname, (caddr_t)uap->hostname, len)) - u.u_error = EFAULT; -} - -sethostname() -{ - register struct a { - char *hostname; - u_int len; - } *uap = (struct a *)u.u_ap; - - if (!suser()) - return; - if (uap->len > sizeof (hostname) - 1) { - u.u_error = EINVAL; - return; - } - hostnamelen = uap->len; - if (copyin((caddr_t)uap->hostname, hostname, uap->len)) - u.u_error = EFAULT; - hostname[hostnamelen] = 0; -} - -/* - * exec system call, with and without environments. - */ -struct execa { - char *fname; - char **argp; - char **envp; -}; - -execv() -{ - ((struct execa *)u.u_ap)->envp = NULL; - execve(); -} - -execve() -{ - register nc; - register char *cp; - register struct buf *bp; - register struct execa *uap; - int na, ne, ucp, ap, c; - int indir, uid, gid; - char *sharg; - struct inode *ip; - swblk_t bno; - char cfname[MAXNAMLEN + 1]; - char cfarg[SHSIZE]; - int resid; - - if ((ip = namei(uchar, 0, 1)) == NULL) - return; - bno = 0; - bp = 0; - indir = 0; - uid = u.u_uid; - gid = u.u_gid; - if (ip->i_mode & ISUID) - uid = ip->i_uid; - if (ip->i_mode & ISGID) - gid = ip->i_gid; - - again: - if (access(ip, IEXEC)) - goto bad; - if ((u.u_procp->p_flag&STRC) && access(ip, IREAD)) - goto bad; - if ((ip->i_mode & IFMT) != IFREG || - (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) { - u.u_error = EACCES; - goto bad; - } - - /* - * Read in first few bytes of file for segment sizes, ux_mag: - * 407 = plain executable - * 410 = RO text - * 413 = demand paged RO text - * Also an ASCII line beginning with #! is - * the file name of a ``shell'' and arguments may be prepended - * to the argument list if given here. - * - * SHELL NAMES ARE LIMITED IN LENGTH. - * - * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM - * THE ASCII LINE. - */ - u.u_error = rdwri(UIO_READ, ip, (caddr_t)&u.u_exdata, sizeof (u.u_exdata), - 0, 1, &resid); - if (u.u_error) - goto bad; - u.u_count = resid; -#ifndef lint - if (u.u_count > sizeof(u.u_exdata) - sizeof(u.u_exdata.Ux_A) && - u.u_exdata.ux_shell[0] != '#') { - u.u_error = ENOEXEC; - goto bad; - } -#endif - switch (u.u_exdata.ux_mag) { - - case 0407: - u.u_exdata.ux_dsize += u.u_exdata.ux_tsize; - u.u_exdata.ux_tsize = 0; - break; - - case 0413: - case 0410: - if (u.u_exdata.ux_tsize == 0) { - u.u_error = ENOEXEC; - goto bad; - } - break; - - default: - if (u.u_exdata.ux_shell[0] != '#' || - u.u_exdata.ux_shell[1] != '!' || - indir) { - u.u_error = ENOEXEC; - goto bad; - } - cp = &u.u_exdata.ux_shell[2]; /* skip "#!" */ - while (cp < &u.u_exdata.ux_shell[SHSIZE]) { - if (*cp == '\t') - *cp = ' '; - else if (*cp == '\n') { - *cp = '\0'; - break; - } - cp++; - } - if (*cp != '\0') { - u.u_error = ENOEXEC; - goto bad; - } - cp = &u.u_exdata.ux_shell[2]; - while (*cp == ' ') - cp++; - u.u_dirp = cp; - while (*cp && *cp != ' ') - cp++; - sharg = NULL; - if (*cp) { - *cp++ = '\0'; - while (*cp == ' ') - cp++; - if (*cp) { - bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE); - sharg = cfarg; - } - } - bcopy((caddr_t)u.u_dent.d_name, (caddr_t)cfname, - (unsigned)(u.u_dent.d_namlen + 1)); - indir = 1; - iput(ip); - ip = namei(schar, 0, 1); - if (ip == NULL) - return; - goto again; - } - - /* - * Collect arguments on "file" in swap space. - */ - na = 0; - ne = 0; - nc = 0; - uap = (struct execa *)u.u_ap; - if ((bno = rmalloc(argmap, (long)ctod(clrnd((int)btoc(NCARGS))))) == 0) { - swkill(u.u_procp, "exece"); - goto bad; - } - if (bno % CLSIZE) - panic("execa rmalloc"); - if (uap->argp) for (;;) { - ap = NULL; - if (indir && (na == 1 || na == 2 && sharg)) - ap = (int)uap->fname; - else if (uap->argp) { - ap = fuword((caddr_t)uap->argp); - uap->argp++; - } - if (ap==NULL && uap->envp) { - uap->argp = NULL; - if ((ap = fuword((caddr_t)uap->envp)) == NULL) - break; - uap->envp++; - ne++; - } - if (ap == NULL) - break; - na++; - if (ap == -1) - u.u_error = EFAULT; - do { - if (nc >= NCARGS-1) - u.u_error = E2BIG; - if (indir && na == 2 && sharg != NULL) - c = *sharg++ & 0377; - else if ((c = fubyte((caddr_t)ap++)) < 0) - u.u_error = EFAULT; - if (u.u_error) { - if (bp) - brelse(bp); - bp = 0; - goto badarg; - } - if (nc % (CLSIZE*NBPG) == 0) { - if (bp) - bdwrite(bp); - bp = getblk(argdev, bno + ctod(nc / NBPG), - CLSIZE*NBPG); - cp = bp->b_un.b_addr; - } - nc++; - *cp++ = c; - } while (c > 0); - } - if (bp) - bdwrite(bp); - bp = 0; - nc = (nc + NBPW-1) & ~(NBPW-1); - if (indir) { - u.u_dent.d_namlen = strlen(cfname); - bcopy((caddr_t)cfname, (caddr_t)u.u_dent.d_name, - (unsigned)(u.u_dent.d_namlen + 1)); - } - getxfile(ip, nc + (na+4)*NBPW, uid, gid); - if (u.u_error) { -badarg: - for (c = 0; c < nc; c += CLSIZE*NBPG) { - bp = baddr(argdev, bno + ctod(c / NBPG), CLSIZE*NBPG); - if (bp) { - bp->b_flags |= B_AGE; /* throw away */ - bp->b_flags &= ~B_DELWRI; /* cancel io */ - brelse(bp); - bp = 0; - } - } - goto bad; - } - - /* - * copy back arglist - */ - ucp = USRSTACK - nc - NBPW; - ap = ucp - na*NBPW - 3*NBPW; - u.u_ar0[SP] = ap; - (void) suword((caddr_t)ap, na-ne); - nc = 0; - for (;;) { - ap += NBPW; - if (na==ne) { - (void) suword((caddr_t)ap, 0); - ap += NBPW; - } - if (--na < 0) - break; - (void) suword((caddr_t)ap, ucp); - do { - if (nc % (CLSIZE*NBPG) == 0) { - if (bp) - brelse(bp); - bp = bread(argdev, bno + nc / NBPG, - CLSIZE*NBPG); - bp->b_flags |= B_AGE; /* throw away */ - bp->b_flags &= ~B_DELWRI; /* cancel io */ - cp = bp->b_un.b_addr; - } - (void) subyte((caddr_t)ucp++, (c = *cp++)); - nc++; - } while(c&0377); - } - (void) suword((caddr_t)ap, 0); - (void) suword((caddr_t)ucp, 0); - setregs(); -bad: - if (bp) - brelse(bp); - if (bno) - rmfree(argmap, (long)ctod(clrnd((int) btoc(NCARGS))), bno); - iput(ip); -} - -/* - * Read in and set up memory for executed file. - */ -getxfile(ip, nargc, uid, gid) -register struct inode *ip; -{ - register size_t ts, ds, ss; - int pagi; - - if (u.u_exdata.ux_mag == 0413) - pagi = SPAGI; - else - pagi = 0; - if (u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && - ip->i_count!=1) { - register struct file *fp; - - for (fp = file; fp < fileNFILE; fp++) { - if (fp->f_type == DTYPE_FILE && - fp->f_inode == ip && (fp->f_flag&FWRITE)) { - u.u_error = ETXTBSY; - goto bad; - } - } - } - - /* - * Compute text and data sizes and make sure not too large. - */ - ts = clrnd(btoc(u.u_exdata.ux_tsize)); - ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize))); - ss = clrnd(SSIZE + btoc(nargc)); - if (chksize(ts, ds, ss)) - goto bad; - - /* - * Make sure enough space to start process. - */ - u.u_cdmap = zdmap; - u.u_csmap = zdmap; - if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) - goto bad; - - /* - * At this point, committed to the new image! - * Release virtual memory resources of old process, and - * initialize the virtual memory of the new process. - * If we resulted from vfork(), instead wakeup our - * parent who will set SVFDONE when he has taken back - * our resources. - */ - if ((u.u_procp->p_flag & SVFORK) == 0) - vrelvm(); - else { - u.u_procp->p_flag &= ~SVFORK; - u.u_procp->p_flag |= SKEEP; - wakeup((caddr_t)u.u_procp); - while ((u.u_procp->p_flag & SVFDONE) == 0) - sleep((caddr_t)u.u_procp, PZERO - 1); - u.u_procp->p_flag &= ~(SVFDONE|SKEEP); - } - u.u_procp->p_flag &= ~(SPAGI|SSEQL|SUANOM|SNUSIG); - u.u_procp->p_flag |= pagi; - u.u_dmap = u.u_cdmap; - u.u_smap = u.u_csmap; - vgetvm(ts, ds, ss); - - if (pagi == 0) - u.u_error = - rdwri(UIO_READ, ip, - (char *)ctob(dptov(u.u_procp, 0)), - (int)u.u_exdata.ux_dsize, - (int)(sizeof(u.u_exdata)+u.u_exdata.ux_tsize), - 0, (int *)0); - xalloc(ip, pagi); - if (pagi && u.u_procp->p_textp) - vinifod((struct fpte *)dptopte(u.u_procp, 0), - PG_FTEXT, u.u_procp->p_textp->x_iptr, - (long)(1 + ts/CLSIZE), (int)btoc(u.u_exdata.ux_dsize)); - -#ifdef vax - /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ -#include "../vax/mtpr.h" /* XXX */ - mtpr(TBIA, 0); -#endif - - if (u.u_error) - swkill(u.u_procp, "i/o error mapping pages"); - /* - * set SUID/SGID protections, if no tracing - */ - if ((u.u_procp->p_flag&STRC)==0) { - u.u_uid = uid; - u.u_procp->p_uid = uid; - u.u_gid = gid; - (void) entergroup(gid); - } else - psignal(u.u_procp, SIGTRAP); - u.u_tsize = ts; - u.u_dsize = ds; - u.u_ssize = ss; -bad: - return; -} - -/* - * Clear registers on exec - */ -setregs() -{ - register int (**rp)(); - register i; - long sigmask; - - for (rp = &u.u_signal[1], sigmask = 1L; rp < &u.u_signal[NSIG]; - sigmask <<= 1, rp++) { - switch (*rp) { - - case SIG_IGN: - case SIG_DFL: - case SIG_HOLD: - continue; - - default: - /* - * Normal or deferring catch; revert to default. - */ - (void) spl6(); - *rp = SIG_DFL; - if ((int)*rp & 1) - u.u_procp->p_siga0 |= sigmask; - else - u.u_procp->p_siga0 &= ~sigmask; - if ((int)*rp & 2) - u.u_procp->p_siga1 |= sigmask; - else - u.u_procp->p_siga1 &= ~sigmask; - (void) spl0(); - continue; - } - } -#ifdef vax /* - for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) - *rp++ = 0; -*/ - u.u_ar0[PC] = u.u_exdata.ux_entloc+2; -#endif -#ifdef sun - { register struct regs *r = (struct regs *)u.u_ar0; - for (i = 0; i < 8; i++) { - r->r_dreg[i] = 0; - if (&r->r_areg[i] != &r->r_sp) - r->r_areg[i] = 0; - } - r->r_sr = PSL_USERSET; - r->r_pc = u.u_exdata.ux_entloc; - } -#endif - for (i=0; irval & 0377) << 8); -} - -/* - * Release resources. - * Save u. area for parent to look at. - * Enter zombie state. - * Wake up parent and init processes, - * and dispose of children. - */ -exit(rv) -{ - register int i; - register struct proc *p, *q; - register int x; - struct mbuf *m = m_getclr(M_WAIT); - -#ifdef PGINPROF - vmsizmon(); -#endif - p = u.u_procp; - p->p_flag &= ~(STRC|SULOCK); - p->p_flag |= SWEXIT; - (void) spl6(); - if ((int)SIG_IGN & 1) - p->p_siga0 = ~0; - else - p->p_siga0 = 0; - if ((int)SIG_IGN & 2) - p->p_siga1 = ~0; - else - p->p_siga1 = 0; - (void) spl0(); - p->p_cpticks = 0; - p->p_pctcpu = 0; - for (i=0; ip_flag & SVFORK) == 0) - vrelvm(); - else { - p->p_flag &= ~SVFORK; - wakeup((caddr_t)p); - while ((p->p_flag & SVFDONE) == 0) - sleep((caddr_t)p, PZERO - 1); - p->p_flag &= ~SVFDONE; - } - for (i = 0; i < NOFILE; i++) { -#ifdef notdef - /* why was this like this? */ - f = u.u_ofile[i]; - u.u_ofile[i] = NULL; - closef(f, 1); -#else - closef(u.u_ofile[i], 1, u.u_pofile[i]); - u.u_ofile[i] = NULL; - u.u_pofile[i] = 0; -#endif - } - ilock(u.u_cdir); - iput(u.u_cdir); - if (u.u_rdir) { - ilock(u.u_rdir); - iput(u.u_rdir); - } - u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; - acct(); -#ifdef QUOTA - qclean(); -#endif -#ifdef sun - ctxfree(&u); -#endif - vrelpt(u.u_procp); - vrelu(u.u_procp, 0); - (void) spl5(); /* hack for mem alloc race XXX */ - multprog--; - p->p_stat = SZOMB; - noproc = 1; - i = PIDHASH(p->p_pid); - x = p - proc; - if (pidhash[i] == x) - pidhash[i] = p->p_idhash; - else { - for (i = pidhash[i]; i != 0; i = proc[i].p_idhash) - if (proc[i].p_idhash == x) { - proc[i].p_idhash = p->p_idhash; - goto done; - } - panic("exit"); - } - if (p->p_pid == 1) - panic("init died"); -done: - p->p_xstat = rv; - p->p_ru = mtod(m, struct rusage *); - *p->p_ru = u.u_ru; - ruadd(p->p_ru, &u.u_cru); - for (q = proc; q < procNPROC; q++) - if (q->p_pptr == p) { - if (q->p_osptr) - q->p_osptr->p_ysptr = q->p_ysptr; - if (q->p_ysptr) - q->p_ysptr->p_osptr = q->p_osptr; - if (proc[1].p_cptr) - proc[1].p_cptr->p_ysptr = q; - q->p_osptr = proc[1].p_cptr; - q->p_ysptr = NULL; - proc[1].p_cptr = q; - - q->p_pptr = &proc[1]; - q->p_ppid = 1; - wakeup((caddr_t)&proc[1]); - /* - * Traced processes are killed - * since their existence means someone is screwing up. - * Stopped processes are sent a hangup and a continue. - * This is designed to be ``safe'' for setuid - * processes since they must be willing to tolerate - * hangups anyways. - */ - if (q->p_flag&STRC) { - q->p_flag &= ~STRC; - psignal(q, SIGKILL); - } else if (q->p_stat == SSTOP) { - psignal(q, SIGHUP); - psignal(q, SIGCONT); - } - /* - * Protect this process from future - * tty signals, clear TSTP/TTIN/TTOU if pending. - */ - (void) spgrp(q, -1); - } - psignal(p->p_pptr, SIGCHLD); - wakeup((caddr_t)p->p_pptr); - swtch(); -} - -#include - -owait() -{ - struct rusage ru; - struct vtimes *vtp, avt; - - if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { - wait1(0, (struct rusage *)0); - return; - } - vtp = (struct vtimes *)u.u_ar0[R1]; - wait1(u.u_ar0[R0], &ru); - if (u.u_error) - return; - getvtimes(&ru, &avt); - (void) copyout((caddr_t)&avt, (caddr_t)vtp, sizeof (struct vtimes)); -} - -/* - * Wait system call. - * Search for a terminated (zombie) child, - * finally lay it to rest, and collect its status. - * Look also for stopped (traced) children, - * and pass back status from them. - */ -wait1(options, ru) - register int options; - struct rusage *ru; -{ - register f; - register struct proc *p, *q; - - f = 0; -loop: - for (p = proc; p < procNPROC; p++) - if (p->p_pptr == u.u_procp) { - f++; - if (p->p_stat == SZOMB) { - u.u_r.r_val1 = p->p_pid; - u.u_r.r_val2 = p->p_xstat; - p->p_xstat = 0; - if (ru) - *ru = *p->p_ru; - ruadd(&u.u_cru, p->p_ru); - (void) m_free(dtom(p->p_ru)); - p->p_ru = 0; - p->p_stat = NULL; - p->p_pid = 0; - p->p_ppid = 0; - if (q = p->p_ysptr) - q->p_osptr = p->p_osptr; - if (q = p->p_osptr) - q->p_ysptr = p->p_ysptr; - if ((q = p->p_pptr)->p_cptr == p) - q->p_cptr = p->p_osptr; - p->p_pptr = 0; - p->p_ysptr = 0; - p->p_osptr = 0; - p->p_cptr = 0; - p->p_sig = 0; - p->p_siga0 = 0; - p->p_siga1 = 0; - p->p_pgrp = 0; - p->p_flag = 0; - p->p_wchan = 0; - p->p_cursig = 0; - return; - } - if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && - (p->p_flag&STRC || options&WUNTRACED)) { - p->p_flag |= SWTED; - u.u_r.r_val1 = p->p_pid; - u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; - return; - } - } - if (f==0) { - u.u_error = ECHILD; - return; - } - if (options&WNOHANG) { - u.u_r.r_val1 = 0; - return; - } - if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) { - u.u_eosys = RESTARTSYS; - return; - } - sleep((caddr_t)u.u_procp, PWAIT); - goto loop; -} +#include "../machine/reg.h" +#include "../machine/pte.h" +#include "../machine/psl.h" + +#include "param.h" +#include "systm.h" +#include "map.h" +#include "dir.h" +#include "user.h" +#include "kernel.h" +#include "proc.h" +#include "buf.h" +#include "inode.h" +#include "seg.h" +#include "acct.h" +#include "wait.h" +#include "vm.h" +#include "text.h" +#include "file.h" +#include "quota.h" +#include "uio.h" +#include "mbuf.h" /* - * fork system call. + * Clear any pending stops for top and all descendents. */ -fork() +spgrp(top) + struct proc *top; { - - u.u_cdmap = zdmap; - u.u_csmap = zdmap; - if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) { - u.u_r.r_val2 = 0; - return; - } - fork1(0); -} - -fork1(isvfork) -{ - register struct proc *p1, *p2; -#ifndef QUOTA - register a; - - a = 0; -#else - if (u.u_quota != NOQUOT && u.u_quota->q_plim && - u.u_quota->q_cnt >= u.u_quota->q_plim) { - u.u_error = EPROCLIM; - return; - } -#endif - p2 = NULL; - for (p1 = proc; p1 < procNPROC; p1++) { -#ifdef QUOTA - if (p1->p_stat == NULL) { - p2 = p1; - break; - } -#else - if (p1->p_stat==NULL && p2==NULL) - p2 = p1; - else { - if (p1->p_uid==u.u_uid && p1->p_stat!=NULL) - a++; - } -#endif - } - /* - * Disallow if - * No processes at all; - * not su and too many procs owned; or - * not su and would take last slot. - */ - if (p2==NULL) - tablefull("proc"); -#ifdef QUOTA - if (p2==NULL || (u.u_uid!=0 && p2==procNPROC-1)) { -#else - if (p2==NULL || (u.u_uid!=0 && (p2==procNPROC-1 || a>MAXUPRC))) { -#endif - u.u_error = EAGAIN; - if (!isvfork) { - (void) vsexpand(0, &u.u_cdmap, 1); - (void) vsexpand(0, &u.u_csmap, 1); - } - goto out; - } - p1 = u.u_procp; - if (newproc(isvfork)) { - u.u_r.r_val1 = p1->p_pid; - u.u_r.r_val2 = 1; /* child */ - u.u_start = time.tv_sec; - u.u_acflag = AFORK; -#ifdef QUOTA - u.u_qflags &= ~QUF_LOGIN; -#endif - return; - } - u.u_r.r_val1 = p2->p_pid; - -out: - u.u_r.r_val2 = 0; -} - -spgrp(top, npgrp) -register struct proc *top; -{ - register struct proc *pp, *p; + register struct proc *p; int f = 0; - for (p = top; npgrp == -1 || u.u_uid == p->p_uid || - !u.u_uid || inferior(p); p = pp) { - if (npgrp == -1) { -#define bit(a) (1<<(a-1)) - p->p_sig &= ~(bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU)); - } else - p->p_pgrp = npgrp; + p = top; + for (;;) { + p->p_sig &= + ~(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU)); f++; /* - * Search for children. - */ - for (pp = proc; pp < procNPROC; pp++) - if (pp->p_pptr == p) - goto cont; - /* - * Search for siblings. + * If this process has children, descend to them next, + * otherwise do any siblings, and if done with this level, + * follow back up the tree (but not past top). */ - for (; p != top; p = p->p_pptr) - for (pp = p + 1; pp < procNPROC; pp++) - if (pp->p_pptr == p->p_pptr) - goto cont; - break; - cont: - ; + if (p->p_cptr) + p = p->p_cptr; + else if (p == top) + return (f); + else if (p->p_osptr) + p = p->p_osptr; + else for (;;) { + p = p->p_pptr; + if (p == top) + return (f); + if (p->p_osptr) { + p = p->p_osptr; + break; + } + } } - return (f); } /* @@ -907,170 +92,28 @@ pfind(pid) } /* - * Create a new process-- the internal version of - * sys fork. - * It returns 1 in the new process, 0 in the old. + * init the process queues */ -newproc(isvfork) - int isvfork; +pqinit() { register struct proc *p; - register struct proc *rpp, *rip; - register int n; - register struct file *fp; - - p = NULL; - /* - * First, just locate a slot for a process - * and copy the useful info from this process into it. - * The panic "cannot happen" because fork has already - * checked for the existence of a slot. - */ -retry: - mpid++; - if (mpid >= 30000) { - mpid = 0; - goto retry; - } - for (rpp = proc; rpp < procNPROC; rpp++) { - if (rpp->p_stat == NULL && p==NULL) - p = rpp; - if (rpp->p_pid==mpid || rpp->p_pgrp==mpid) - goto retry; - } - if ((rpp = p) == NULL) - panic("no procs"); - - /* - * Make a proc table entry for the new process. - */ - rip = u.u_procp; -#ifdef QUOTA - (rpp->p_quota = rip->p_quota)->q_cnt++; -#endif - rpp->p_stat = SIDL; - timerclear(&rpp->p_realtimer.it_value); - rpp->p_flag = SLOAD | (rip->p_flag & (SPAGI|SNUSIG)); - if (isvfork) { - rpp->p_flag |= SVFORK; - rpp->p_ndx = rip->p_ndx; - } else - rpp->p_ndx = rpp - proc; - rpp->p_uid = rip->p_uid; - rpp->p_pgrp = rip->p_pgrp; - rpp->p_nice = rip->p_nice; - rpp->p_textp = isvfork ? 0 : rip->p_textp; - rpp->p_pid = mpid; - rpp->p_ppid = rip->p_pid; - rpp->p_pptr = rip; - rpp->p_osptr = rip->p_cptr; - if (rip->p_cptr) - rip->p_cptr->p_ysptr = rpp; - rpp->p_ysptr = NULL; - rpp->p_cptr = NULL; - rip->p_cptr = rpp; - rpp->p_time = 0; - rpp->p_cpu = 0; - rpp->p_siga0 = rip->p_siga0; - rpp->p_siga1 = rip->p_siga1; - /* take along any pending signals, like stops? */ - if (isvfork) { - rpp->p_tsize = rpp->p_dsize = rpp->p_ssize = 0; - rpp->p_szpt = clrnd(ctopt(UPAGES)); - forkstat.cntvfork++; - forkstat.sizvfork += rip->p_dsize + rip->p_ssize; - } else { - rpp->p_tsize = rip->p_tsize; - rpp->p_dsize = rip->p_dsize; - rpp->p_ssize = rip->p_ssize; - rpp->p_szpt = rip->p_szpt; - forkstat.cntfork++; - forkstat.sizfork += rip->p_dsize + rip->p_ssize; - } - rpp->p_rssize = 0; - rpp->p_maxrss = rip->p_maxrss; - rpp->p_wchan = 0; - rpp->p_slptime = 0; - rpp->p_pctcpu = 0; - rpp->p_cpticks = 0; - n = PIDHASH(rpp->p_pid); - p->p_idhash = pidhash[n]; - pidhash[n] = rpp - proc; - multprog++; - - /* - * Increase reference counts on shared objects. - */ - for (n = 0; n < NOFILE; n++) { - fp = u.u_ofile[n]; - if (fp == NULL) - continue; - fp->f_count++; - if (u.u_pofile[n]&RDLOCK) - fp->f_inode->i_rdlockc++; - if (u.u_pofile[n]&WRLOCK) - fp->f_inode->i_wrlockc++; - } - u.u_cdir->i_count++; - if (u.u_rdir) - u.u_rdir->i_count++; - - /* - * Partially simulate the environment - * of the new process so that when it is actually - * created (by copying) it will look right. - * This begins the section where we must prevent the parent - * from being swapped. - */ - rip->p_flag |= SKEEP; - if (procdup(rpp, isvfork)) - return (1); /* - * Make child runnable and add to run queue. + * most procs are initially on freequeue + * nb: we place them there in their "natural" order. */ - (void) spl6(); - rpp->p_stat = SRUN; - setrq(rpp); - (void) spl0(); - /* - * Cause child to take a non-local goto as soon as it runs. - * On older systems this was done with SSWAP bit in proc - * table; on VAX we use u.u_pcb.pcb_sswap so don't need - * to do rpp->p_flag |= SSWAP. Actually do nothing here. - */ - /* rpp->p_flag |= SSWAP; */ + freeproc = NULL; + for (p = procNPROC; --p > proc; freeproc = p) + p->p_nxt = freeproc; /* - * Now can be swapped. + * but proc[0] is special ... */ - rip->p_flag &= ~SKEEP; - /* - * If vfork make chain from parent process to child - * (where virtal memory is temporarily). Wait for - * child to finish, steal virtual memory back, - * and wakeup child to let it die. - */ - if (isvfork) { - u.u_procp->p_xlink = rpp; - u.u_procp->p_flag |= SNOVM; - while (rpp->p_flag & SVFORK) - sleep((caddr_t)rpp, PZERO - 1); - if ((rpp->p_flag & SLOAD) == 0) - panic("newproc vfork"); - uaccess(rpp, Vfmap, &vfutl); - u.u_procp->p_xlink = 0; - vpassvm(rpp, u.u_procp, &vfutl, &u, Vfmap); - u.u_procp->p_flag &= ~SNOVM; - rpp->p_ndx = rpp - proc; - rpp->p_flag |= SVFDONE; - wakeup((caddr_t)rpp); - } + allproc = p; + p->p_nxt = NULL; + p->p_prev = &allproc; - /* - * 0 return means parent. - */ - return (0); + zombproc = NULL; }