xref: /csrg-svn/sys/kern/kern_proc.c (revision 40709)
123371Smckusick /*
237728Smckusick  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
337728Smckusick  * All rights reserved.
423371Smckusick  *
537728Smckusick  * Redistribution and use in source and binary forms are permitted
637728Smckusick  * provided that the above copyright notice and this paragraph are
737728Smckusick  * duplicated in all such forms and that any documentation,
837728Smckusick  * advertising materials, and other materials related to such
937728Smckusick  * distribution and use acknowledge that the software was developed
1037728Smckusick  * by the University of California, Berkeley.  The name of the
1137728Smckusick  * University may not be used to endorse or promote products derived
1237728Smckusick  * from this software without specific prior written permission.
1337728Smckusick  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1437728Smckusick  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1537728Smckusick  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1637728Smckusick  *
17*40709Skarels  *	@(#)kern_proc.c	7.9 (Berkeley) 04/03/90
1823371Smckusick  */
1936Sbill 
2017091Sbloom #include "param.h"
2117091Sbloom #include "systm.h"
2217091Sbloom #include "map.h"
2317091Sbloom #include "user.h"
2417091Sbloom #include "kernel.h"
2517091Sbloom #include "proc.h"
2617091Sbloom #include "buf.h"
2717091Sbloom #include "seg.h"
2817091Sbloom #include "acct.h"
2917091Sbloom #include "wait.h"
3017091Sbloom #include "vm.h"
3117091Sbloom #include "text.h"
3217091Sbloom #include "file.h"
3337728Smckusick #include "../ufs/quota.h"
3417091Sbloom #include "uio.h"
3535810Smarc #include "malloc.h"
3617091Sbloom #include "mbuf.h"
3739064Smarc #include "ioctl.h"
3835810Smarc #include "tty.h"
3936Sbill 
4037524Smckusick #include "machine/reg.h"
4137524Smckusick #include "machine/pte.h"
4237524Smckusick #include "machine/psl.h"
4337524Smckusick 
4417540Skarels /*
4525385Skarels  * Clear any pending stops for top and all descendents.
4617540Skarels  */
4725385Skarels spgrp(top)
4817540Skarels 	struct proc *top;
497497Sroot {
5017540Skarels 	register struct proc *p;
517497Sroot 	int f = 0;
527497Sroot 
5317540Skarels 	p = top;
5417540Skarels 	for (;;) {
5525385Skarels 		p->p_sig &=
5617540Skarels 			  ~(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU));
577497Sroot 		f++;
587497Sroot 		/*
5917540Skarels 		 * If this process has children, descend to them next,
6017540Skarels 		 * otherwise do any siblings, and if done with this level,
6117540Skarels 		 * follow back up the tree (but not past top).
627497Sroot 		 */
6317540Skarels 		if (p->p_cptr)
6417540Skarels 			p = p->p_cptr;
6517540Skarels 		else if (p == top)
6617540Skarels 			return (f);
6717540Skarels 		else if (p->p_osptr)
6817540Skarels 			p = p->p_osptr;
6917540Skarels 		else for (;;) {
7017540Skarels 			p = p->p_pptr;
7117540Skarels 			if (p == top)
7217540Skarels 				return (f);
7317540Skarels 			if (p->p_osptr) {
7417540Skarels 				p = p->p_osptr;
7517540Skarels 				break;
7617540Skarels 			}
7717540Skarels 		}
787497Sroot 	}
797497Sroot }
807497Sroot 
8136Sbill /*
827497Sroot  * Is p an inferior of the current process?
8336Sbill  */
847497Sroot inferior(p)
857816Sroot 	register struct proc *p;
8636Sbill {
877497Sroot 	for (; p != u.u_procp; p = p->p_pptr)
887497Sroot 		if (p->p_ppid == 0)
897497Sroot 			return (0);
907497Sroot 	return (1);
9136Sbill }
927816Sroot 
93*40709Skarels /*
94*40709Skarels  * Locate a process by number
95*40709Skarels  */
967816Sroot struct proc *
977816Sroot pfind(pid)
9835810Smarc 	register pid;
997816Sroot {
100*40709Skarels 	register struct proc *p = pidhash[PIDHASH(pid)];
1017816Sroot 
102*40709Skarels 	for (; p; p = p->p_hash)
1037816Sroot 		if (p->p_pid == pid)
1047816Sroot 			return (p);
1057816Sroot 	return ((struct proc *)0);
1067816Sroot }
10716529Skarels 
10816529Skarels /*
10935810Smarc  * Locate a process group by number
11035810Smarc  */
11135810Smarc struct pgrp *
11235810Smarc pgfind(pgid)
11335810Smarc 	register pid_t pgid;
11435810Smarc {
11535810Smarc 	register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)];
11635810Smarc 
11735810Smarc 	for (; pgrp; pgrp = pgrp->pg_hforw)
11835810Smarc 		if (pgrp->pg_id == pgid)
119*40709Skarels 			return (pgrp);
12035810Smarc 	return ((struct pgrp *)0);
12135810Smarc }
12235810Smarc 
12335810Smarc /*
12435810Smarc  * Move p to a new or existing process group (and session)
12535810Smarc  */
12635810Smarc pgmv(p, pgid, mksess)
12735810Smarc 	register struct proc *p;
12835810Smarc 	pid_t pgid;
12935810Smarc {
13035810Smarc 	register struct pgrp *pgrp = pgfind(pgid);
13135810Smarc 	register struct proc **pp = &p->p_pgrp->pg_mem;
13235810Smarc 	register struct proc *cp;
13337589Smarc 	struct pgrp *opgrp;
13435810Smarc 	register n;
13535810Smarc 
13639562Smarc #ifdef DIAGNOSTIC
13735810Smarc 	if (pgrp && mksess)	/* firewalls */
13837589Smarc 		panic("pgmv: setsid into non-empty pgrp");
13935810Smarc 	if (SESS_LEADER(p))
14037589Smarc 		panic("pgmv: session leader attempted setpgrp");
14139562Smarc #endif
14237589Smarc 	if (pgrp == NULL) {
14335810Smarc 		/*
14435810Smarc 		 * new process group
14535810Smarc 		 */
14639562Smarc #ifdef DIAGNOSTIC
14735810Smarc 		if (p->p_pid != pgid)
14837589Smarc 			panic("pgmv: new pgrp and pid != pgid");
14939562Smarc #endif
15035810Smarc 		MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
15135810Smarc 		       M_WAITOK);
15235810Smarc 		if (mksess) {
15335810Smarc 			register struct session *sess;
15435810Smarc 			/*
15535810Smarc 			 * new session
15635810Smarc 			 */
15735810Smarc 			MALLOC(sess, struct session *, sizeof(struct session),
15835810Smarc 				M_SESSION, M_WAITOK);
15935810Smarc 			sess->s_leader = p;
16035810Smarc 			sess->s_count = 1;
16139562Smarc 			sess->s_ttyvp = NULL;
16239562Smarc 			sess->s_ttyp = NULL;
16339562Smarc 			p->p_flag &= ~SCTTY;
16435810Smarc 			pgrp->pg_session = sess;
16539562Smarc #ifdef DIAGNOSTIC
16635810Smarc 			if (p != u.u_procp)
16735810Smarc 				panic("pgmv: mksession and p != u.u_procp");
16839562Smarc #endif
16935810Smarc 		} else {
17035810Smarc 			pgrp->pg_session = p->p_session;
17135810Smarc 			pgrp->pg_session->s_count++;
17235810Smarc 		}
17335810Smarc 		pgrp->pg_id = pgid;
17435810Smarc 		pgrp->pg_hforw = pgrphash[n=PIDHASH(pgid)];
17535810Smarc 		pgrphash[n] = pgrp;
17635810Smarc 		pgrp->pg_jobc = 0;
17739562Smarc 		pgrp->pg_mem = NULL;
17835810Smarc 	}
17935810Smarc 	/*
18035810Smarc 	 * adjust eligibility of affected pgrps to participate in job control
18135810Smarc 	 */
18235810Smarc 	if (PGRP_JOBC(p))
18335810Smarc 		p->p_pgrp->pg_jobc--;
18435810Smarc 	for (cp = p->p_cptr; cp; cp = cp->p_osptr)
18535810Smarc 		if (PGRP_JOBC(cp))
18635810Smarc 			cp->p_pgrp->pg_jobc--;
18735810Smarc 	/*
18835810Smarc 	 * unlink p from old process group
18935810Smarc 	 */
19035810Smarc 	for (; *pp; pp = &(*pp)->p_pgrpnxt)
19135810Smarc 		if (*pp == p) {
19235810Smarc 			*pp = p->p_pgrpnxt;
19335810Smarc 			goto done;
19435810Smarc 		}
19537589Smarc 	panic("pgmv: can't find p on old pgrp");
19635810Smarc done:
19735810Smarc 	/*
19835810Smarc 	 * link into new one
19935810Smarc 	 */
20035810Smarc 	p->p_pgrpnxt = pgrp->pg_mem;
20135810Smarc 	pgrp->pg_mem = p;
20237589Smarc 	opgrp = p->p_pgrp;
20335810Smarc 	p->p_pgrp = pgrp;
20435810Smarc 	/*
20535810Smarc 	 * adjust eligibility of affected pgrps to participate in job control
20635810Smarc 	 */
20735810Smarc 	if (PGRP_JOBC(p))
20835810Smarc 		p->p_pgrp->pg_jobc++;
20935810Smarc 	for (cp = p->p_cptr; cp; cp = cp->p_osptr)
21035810Smarc 		if (PGRP_JOBC(cp))
21135810Smarc 			cp->p_pgrp->pg_jobc++;
21235810Smarc 	/*
21335810Smarc 	 * old pgrp empty?
21435810Smarc 	 */
21537589Smarc 	if (!opgrp->pg_mem)
21637589Smarc 		pgdelete(opgrp);
21735810Smarc }
21835810Smarc 
21935810Smarc /*
22035810Smarc  * remove process from process group
22135810Smarc  */
22235810Smarc pgrm(p)
22335810Smarc 	register struct proc *p;
22435810Smarc {
22535810Smarc 	register struct proc **pp = &p->p_pgrp->pg_mem;
22635810Smarc 
22735810Smarc 	for (; *pp; pp = &(*pp)->p_pgrpnxt)
22835810Smarc 		if (*pp == p) {
22935810Smarc 			*pp = p->p_pgrpnxt;
23035810Smarc 			goto done;
23135810Smarc 		}
23237589Smarc 	panic("pgrm: can't find p in pgrp");
23335810Smarc done:
23435810Smarc 	if (!p->p_pgrp->pg_mem)
23535810Smarc 		pgdelete(p->p_pgrp);
23635810Smarc 	p->p_pgrp = 0;
23735810Smarc }
23835810Smarc 
23935810Smarc /*
24035810Smarc  * delete a process group
24135810Smarc  */
24235810Smarc pgdelete(pgrp)
24335810Smarc 	register struct pgrp *pgrp;
24435810Smarc {
24535810Smarc 	register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)];
24635810Smarc 
24739562Smarc 	if (pgrp->pg_session->s_ttyp != NULL &&
24839562Smarc 	    pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
24939562Smarc 		pgrp->pg_session->s_ttyp->t_pgrp = NULL;
25035810Smarc 	for (; *pgp; pgp = &(*pgp)->pg_hforw)
25135810Smarc 		if (*pgp == pgrp) {
25235810Smarc 			*pgp = pgrp->pg_hforw;
25335810Smarc 			goto done;
25435810Smarc 		}
25537589Smarc 	panic("pgdelete: can't find pgrp on hash chain");
25635810Smarc done:
25735810Smarc 	if (--pgrp->pg_session->s_count == 0)
25835810Smarc 		FREE(pgrp->pg_session, M_SESSION);
25935810Smarc 	FREE(pgrp, M_PGRP);
26035810Smarc }
26135810Smarc 
26235810Smarc /*
26316529Skarels  * init the process queues
26416529Skarels  */
26516529Skarels pqinit()
26616529Skarels {
26716529Skarels 	register struct proc *p;
26816529Skarels 
26916529Skarels 	/*
27016529Skarels 	 * most procs are initially on freequeue
27116529Skarels 	 *	nb: we place them there in their "natural" order.
27216529Skarels 	 */
27316529Skarels 
27416529Skarels 	freeproc = NULL;
27516529Skarels 	for (p = procNPROC; --p > proc; freeproc = p)
27616529Skarels 		p->p_nxt = freeproc;
27716529Skarels 
27816529Skarels 	/*
27916529Skarels 	 * but proc[0] is special ...
28016529Skarels 	 */
28116529Skarels 
28216529Skarels 	allproc = p;
28316529Skarels 	p->p_nxt = NULL;
28416529Skarels 	p->p_prev = &allproc;
28516529Skarels 
28616529Skarels 	zombproc = NULL;
28716529Skarels }
28835810Smarc 
28937728Smckusick #ifdef debug
29035810Smarc /* DEBUG */
29135810Smarc pgrpdump()
29235810Smarc {
29335810Smarc 	register struct pgrp *pgrp;
29435810Smarc 	register struct proc *p;
29535810Smarc 	register i;
29635810Smarc 
29735810Smarc 	for (i=0; i<PIDHSZ; i++) {
29835810Smarc 		if (pgrphash[i]) {
29935810Smarc 		  printf("\tindx %d\n", i);
30035810Smarc 		  for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) {
30135810Smarc 		    printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n",
30235810Smarc 			pgrp, pgrp->pg_id, pgrp->pg_session,
30335810Smarc 			pgrp->pg_session->s_count, pgrp->pg_mem);
30435810Smarc 		    for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) {
30535810Smarc 			printf("\t\tpid %d addr %x pgrp %x\n",
30635810Smarc 				p->p_pid, p, p->p_pgrp);
30735810Smarc 		    }
30835810Smarc 		  }
30935810Smarc 
31035810Smarc 		}
31135810Smarc 	}
31235810Smarc }
31337728Smckusick #endif /* debug */
314