/* * Copyright (c) 1982, 1986, 1989 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)kern_proc.c 7.9 (Berkeley) 04/03/90 */ #include "param.h" #include "systm.h" #include "map.h" #include "user.h" #include "kernel.h" #include "proc.h" #include "buf.h" #include "seg.h" #include "acct.h" #include "wait.h" #include "vm.h" #include "text.h" #include "file.h" #include "../ufs/quota.h" #include "uio.h" #include "malloc.h" #include "mbuf.h" #include "ioctl.h" #include "tty.h" #include "machine/reg.h" #include "machine/pte.h" #include "machine/psl.h" /* * Clear any pending stops for top and all descendents. */ spgrp(top) struct proc *top; { register struct proc *p; int f = 0; p = top; for (;;) { p->p_sig &= ~(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU)); f++; /* * 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). */ 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; } } } } /* * Is p an inferior of the current process? */ inferior(p) register struct proc *p; { for (; p != u.u_procp; p = p->p_pptr) if (p->p_ppid == 0) return (0); return (1); } /* * Locate a process by number */ struct proc * pfind(pid) register pid; { register struct proc *p = pidhash[PIDHASH(pid)]; for (; p; p = p->p_hash) if (p->p_pid == pid) return (p); return ((struct proc *)0); } /* * Locate a process group by number */ struct pgrp * pgfind(pgid) register pid_t pgid; { register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)]; for (; pgrp; pgrp = pgrp->pg_hforw) if (pgrp->pg_id == pgid) return (pgrp); return ((struct pgrp *)0); } /* * Move p to a new or existing process group (and session) */ pgmv(p, pgid, mksess) register struct proc *p; pid_t pgid; { register struct pgrp *pgrp = pgfind(pgid); register struct proc **pp = &p->p_pgrp->pg_mem; register struct proc *cp; struct pgrp *opgrp; register n; #ifdef DIAGNOSTIC if (pgrp && mksess) /* firewalls */ panic("pgmv: setsid into non-empty pgrp"); if (SESS_LEADER(p)) panic("pgmv: session leader attempted setpgrp"); #endif if (pgrp == NULL) { /* * new process group */ #ifdef DIAGNOSTIC if (p->p_pid != pgid) panic("pgmv: new pgrp and pid != pgid"); #endif MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK); if (mksess) { register struct session *sess; /* * new session */ MALLOC(sess, struct session *, sizeof(struct session), M_SESSION, M_WAITOK); sess->s_leader = p; sess->s_count = 1; sess->s_ttyvp = NULL; sess->s_ttyp = NULL; p->p_flag &= ~SCTTY; pgrp->pg_session = sess; #ifdef DIAGNOSTIC if (p != u.u_procp) panic("pgmv: mksession and p != u.u_procp"); #endif } else { pgrp->pg_session = p->p_session; pgrp->pg_session->s_count++; } pgrp->pg_id = pgid; pgrp->pg_hforw = pgrphash[n=PIDHASH(pgid)]; pgrphash[n] = pgrp; pgrp->pg_jobc = 0; pgrp->pg_mem = NULL; } /* * adjust eligibility of affected pgrps to participate in job control */ if (PGRP_JOBC(p)) p->p_pgrp->pg_jobc--; for (cp = p->p_cptr; cp; cp = cp->p_osptr) if (PGRP_JOBC(cp)) cp->p_pgrp->pg_jobc--; /* * unlink p from old process group */ for (; *pp; pp = &(*pp)->p_pgrpnxt) if (*pp == p) { *pp = p->p_pgrpnxt; goto done; } panic("pgmv: can't find p on old pgrp"); done: /* * link into new one */ p->p_pgrpnxt = pgrp->pg_mem; pgrp->pg_mem = p; opgrp = p->p_pgrp; p->p_pgrp = pgrp; /* * adjust eligibility of affected pgrps to participate in job control */ if (PGRP_JOBC(p)) p->p_pgrp->pg_jobc++; for (cp = p->p_cptr; cp; cp = cp->p_osptr) if (PGRP_JOBC(cp)) cp->p_pgrp->pg_jobc++; /* * old pgrp empty? */ if (!opgrp->pg_mem) pgdelete(opgrp); } /* * remove process from process group */ pgrm(p) register struct proc *p; { register struct proc **pp = &p->p_pgrp->pg_mem; for (; *pp; pp = &(*pp)->p_pgrpnxt) if (*pp == p) { *pp = p->p_pgrpnxt; goto done; } panic("pgrm: can't find p in pgrp"); done: if (!p->p_pgrp->pg_mem) pgdelete(p->p_pgrp); p->p_pgrp = 0; } /* * delete a process group */ pgdelete(pgrp) register struct pgrp *pgrp; { register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; if (pgrp->pg_session->s_ttyp != NULL && pgrp->pg_session->s_ttyp->t_pgrp == pgrp) pgrp->pg_session->s_ttyp->t_pgrp = NULL; for (; *pgp; pgp = &(*pgp)->pg_hforw) if (*pgp == pgrp) { *pgp = pgrp->pg_hforw; goto done; } panic("pgdelete: can't find pgrp on hash chain"); done: if (--pgrp->pg_session->s_count == 0) FREE(pgrp->pg_session, M_SESSION); FREE(pgrp, M_PGRP); } /* * init the process queues */ pqinit() { register struct proc *p; /* * most procs are initially on freequeue * nb: we place them there in their "natural" order. */ freeproc = NULL; for (p = procNPROC; --p > proc; freeproc = p) p->p_nxt = freeproc; /* * but proc[0] is special ... */ allproc = p; p->p_nxt = NULL; p->p_prev = &allproc; zombproc = NULL; } #ifdef debug /* DEBUG */ pgrpdump() { register struct pgrp *pgrp; register struct proc *p; register i; for (i=0; ipg_hforw) { printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", pgrp, pgrp->pg_id, pgrp->pg_session, pgrp->pg_session->s_count, pgrp->pg_mem); for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { printf("\t\tpid %d addr %x pgrp %x\n", p->p_pid, p, p->p_pgrp); } } } } } #endif /* debug */