xref: /csrg-svn/sys/kern/kern_proc.c (revision 44387)
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*44387Smarc  *	@(#)kern_proc.c	7.10 (Berkeley) 06/28/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 /*
457497Sroot  * Is p an inferior of the current process?
4636Sbill  */
477497Sroot inferior(p)
487816Sroot 	register struct proc *p;
4936Sbill {
507497Sroot 	for (; p != u.u_procp; p = p->p_pptr)
517497Sroot 		if (p->p_ppid == 0)
527497Sroot 			return (0);
537497Sroot 	return (1);
5436Sbill }
557816Sroot 
5640709Skarels /*
5740709Skarels  * Locate a process by number
5840709Skarels  */
597816Sroot struct proc *
607816Sroot pfind(pid)
6135810Smarc 	register pid;
627816Sroot {
6340709Skarels 	register struct proc *p = pidhash[PIDHASH(pid)];
647816Sroot 
6540709Skarels 	for (; p; p = p->p_hash)
667816Sroot 		if (p->p_pid == pid)
677816Sroot 			return (p);
687816Sroot 	return ((struct proc *)0);
697816Sroot }
7016529Skarels 
7116529Skarels /*
7235810Smarc  * Locate a process group by number
7335810Smarc  */
7435810Smarc struct pgrp *
7535810Smarc pgfind(pgid)
7635810Smarc 	register pid_t pgid;
7735810Smarc {
7835810Smarc 	register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)];
7935810Smarc 
8035810Smarc 	for (; pgrp; pgrp = pgrp->pg_hforw)
8135810Smarc 		if (pgrp->pg_id == pgid)
8240709Skarels 			return (pgrp);
8335810Smarc 	return ((struct pgrp *)0);
8435810Smarc }
8535810Smarc 
8635810Smarc /*
8735810Smarc  * Move p to a new or existing process group (and session)
8835810Smarc  */
8935810Smarc pgmv(p, pgid, mksess)
9035810Smarc 	register struct proc *p;
9135810Smarc 	pid_t pgid;
9235810Smarc {
9335810Smarc 	register struct pgrp *pgrp = pgfind(pgid);
9435810Smarc 	register struct proc **pp = &p->p_pgrp->pg_mem;
9535810Smarc 	register struct proc *cp;
9637589Smarc 	struct pgrp *opgrp;
9735810Smarc 	register n;
9835810Smarc 
9939562Smarc #ifdef DIAGNOSTIC
10035810Smarc 	if (pgrp && mksess)	/* firewalls */
10137589Smarc 		panic("pgmv: setsid into non-empty pgrp");
10235810Smarc 	if (SESS_LEADER(p))
10337589Smarc 		panic("pgmv: session leader attempted setpgrp");
10439562Smarc #endif
10537589Smarc 	if (pgrp == NULL) {
10635810Smarc 		/*
10735810Smarc 		 * new process group
10835810Smarc 		 */
10939562Smarc #ifdef DIAGNOSTIC
11035810Smarc 		if (p->p_pid != pgid)
11137589Smarc 			panic("pgmv: new pgrp and pid != pgid");
11239562Smarc #endif
11335810Smarc 		MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
11435810Smarc 		       M_WAITOK);
11535810Smarc 		if (mksess) {
11635810Smarc 			register struct session *sess;
11735810Smarc 			/*
11835810Smarc 			 * new session
11935810Smarc 			 */
12035810Smarc 			MALLOC(sess, struct session *, sizeof(struct session),
12135810Smarc 				M_SESSION, M_WAITOK);
12235810Smarc 			sess->s_leader = p;
12335810Smarc 			sess->s_count = 1;
12439562Smarc 			sess->s_ttyvp = NULL;
12539562Smarc 			sess->s_ttyp = NULL;
12639562Smarc 			p->p_flag &= ~SCTTY;
12735810Smarc 			pgrp->pg_session = sess;
12839562Smarc #ifdef DIAGNOSTIC
12935810Smarc 			if (p != u.u_procp)
13035810Smarc 				panic("pgmv: mksession and p != u.u_procp");
13139562Smarc #endif
13235810Smarc 		} else {
13335810Smarc 			pgrp->pg_session = p->p_session;
13435810Smarc 			pgrp->pg_session->s_count++;
13535810Smarc 		}
13635810Smarc 		pgrp->pg_id = pgid;
13735810Smarc 		pgrp->pg_hforw = pgrphash[n=PIDHASH(pgid)];
13835810Smarc 		pgrphash[n] = pgrp;
13935810Smarc 		pgrp->pg_jobc = 0;
14039562Smarc 		pgrp->pg_mem = NULL;
141*44387Smarc 	} else if (pgrp == p->p_pgrp)
142*44387Smarc 		return;
14335810Smarc 	/*
14435810Smarc 	 * adjust eligibility of affected pgrps to participate in job control
14535810Smarc 	 */
146*44387Smarc 	fixjobc(p, 0);
14735810Smarc 	/*
14835810Smarc 	 * unlink p from old process group
14935810Smarc 	 */
15035810Smarc 	for (; *pp; pp = &(*pp)->p_pgrpnxt)
15135810Smarc 		if (*pp == p) {
15235810Smarc 			*pp = p->p_pgrpnxt;
15335810Smarc 			goto done;
15435810Smarc 		}
15537589Smarc 	panic("pgmv: can't find p on old pgrp");
15635810Smarc done:
15735810Smarc 	/*
15835810Smarc 	 * link into new one
15935810Smarc 	 */
16035810Smarc 	p->p_pgrpnxt = pgrp->pg_mem;
16135810Smarc 	pgrp->pg_mem = p;
16237589Smarc 	opgrp = p->p_pgrp;
16335810Smarc 	p->p_pgrp = pgrp;
16435810Smarc 	/*
16535810Smarc 	 * adjust eligibility of affected pgrps to participate in job control
16635810Smarc 	 */
167*44387Smarc 	fixjobc(p, 1);
16835810Smarc 	/*
169*44387Smarc 	 * delete old if empty
17035810Smarc 	 */
17137589Smarc 	if (!opgrp->pg_mem)
17237589Smarc 		pgdelete(opgrp);
17335810Smarc }
17435810Smarc 
17535810Smarc /*
17635810Smarc  * remove process from process group
17735810Smarc  */
17835810Smarc pgrm(p)
17935810Smarc 	register struct proc *p;
18035810Smarc {
18135810Smarc 	register struct proc **pp = &p->p_pgrp->pg_mem;
18235810Smarc 
18335810Smarc 	for (; *pp; pp = &(*pp)->p_pgrpnxt)
18435810Smarc 		if (*pp == p) {
18535810Smarc 			*pp = p->p_pgrpnxt;
18635810Smarc 			goto done;
18735810Smarc 		}
18837589Smarc 	panic("pgrm: can't find p in pgrp");
18935810Smarc done:
19035810Smarc 	if (!p->p_pgrp->pg_mem)
19135810Smarc 		pgdelete(p->p_pgrp);
19235810Smarc 	p->p_pgrp = 0;
19335810Smarc }
19435810Smarc 
19535810Smarc /*
19635810Smarc  * delete a process group
19735810Smarc  */
19835810Smarc pgdelete(pgrp)
19935810Smarc 	register struct pgrp *pgrp;
20035810Smarc {
20135810Smarc 	register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)];
20235810Smarc 
20339562Smarc 	if (pgrp->pg_session->s_ttyp != NULL &&
20439562Smarc 	    pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
20539562Smarc 		pgrp->pg_session->s_ttyp->t_pgrp = NULL;
20635810Smarc 	for (; *pgp; pgp = &(*pgp)->pg_hforw)
20735810Smarc 		if (*pgp == pgrp) {
20835810Smarc 			*pgp = pgrp->pg_hforw;
20935810Smarc 			goto done;
21035810Smarc 		}
21137589Smarc 	panic("pgdelete: can't find pgrp on hash chain");
21235810Smarc done:
21335810Smarc 	if (--pgrp->pg_session->s_count == 0)
21435810Smarc 		FREE(pgrp->pg_session, M_SESSION);
21535810Smarc 	FREE(pgrp, M_PGRP);
21635810Smarc }
21735810Smarc 
21835810Smarc /*
219*44387Smarc  * Adjust pgrp jobc counter.
220*44387Smarc  * flag == 0 => p is leaving current state.
221*44387Smarc  * flag == 1 => p is entering current state.
222*44387Smarc  */
223*44387Smarc fixjobc(p, flag)
224*44387Smarc 	register struct proc *p;
225*44387Smarc 	register flag;
226*44387Smarc {
227*44387Smarc 	register struct pgrp *mypgrp = p->p_pgrp, *hispgrp;
228*44387Smarc 	register struct session *mysession = mypgrp->pg_session;
229*44387Smarc 	register struct proc *qp;
230*44387Smarc 
231*44387Smarc 	if ((hispgrp = p->p_pptr->p_pgrp) != mypgrp &&
232*44387Smarc 	    hispgrp->pg_session == mysession)
233*44387Smarc 		if (flag)
234*44387Smarc 			mypgrp->pg_jobc++;
235*44387Smarc 		else if (--mypgrp->pg_jobc == 0) {
236*44387Smarc 			int deliver = 0;
237*44387Smarc 
238*44387Smarc 			sigstopped:
239*44387Smarc 			for (qp = mypgrp->pg_mem; qp != NULL;
240*44387Smarc 			     qp = qp->p_pgrpnxt)
241*44387Smarc 				if (deliver) {
242*44387Smarc 					psignal(qp, SIGHUP);
243*44387Smarc 					psignal(qp, SIGCONT);
244*44387Smarc 				} else if (qp->p_stat == SSTOP) {
245*44387Smarc 					deliver++;
246*44387Smarc 					goto sigstopped;
247*44387Smarc 				}
248*44387Smarc 		}
249*44387Smarc 
250*44387Smarc 	for (p = p->p_cptr; p != NULL; p = p->p_osptr)
251*44387Smarc 		if ((hispgrp = p->p_pgrp) != mypgrp &&
252*44387Smarc 		    hispgrp->pg_session == mysession &&
253*44387Smarc 		    p->p_stat != SZOMB)
254*44387Smarc 			if (flag)
255*44387Smarc 				hispgrp->pg_jobc++;
256*44387Smarc 			else if (--hispgrp->pg_jobc == 0) {
257*44387Smarc 				int deliver = 0;
258*44387Smarc 
259*44387Smarc 				sigstopped2:
260*44387Smarc 				for (qp = hispgrp->pg_mem; qp != NULL;
261*44387Smarc 				     qp = qp->p_pgrpnxt)
262*44387Smarc 					if (deliver) {
263*44387Smarc 						psignal(qp, SIGHUP);
264*44387Smarc 						psignal(qp, SIGCONT);
265*44387Smarc 					} else if (qp->p_stat == SSTOP) {
266*44387Smarc 						deliver++;
267*44387Smarc 						goto sigstopped2;
268*44387Smarc 					}
269*44387Smarc 			}
270*44387Smarc }
271*44387Smarc 
272*44387Smarc /*
27316529Skarels  * init the process queues
27416529Skarels  */
27516529Skarels pqinit()
27616529Skarels {
27716529Skarels 	register struct proc *p;
27816529Skarels 
27916529Skarels 	/*
28016529Skarels 	 * most procs are initially on freequeue
28116529Skarels 	 *	nb: we place them there in their "natural" order.
28216529Skarels 	 */
28316529Skarels 
28416529Skarels 	freeproc = NULL;
28516529Skarels 	for (p = procNPROC; --p > proc; freeproc = p)
28616529Skarels 		p->p_nxt = freeproc;
28716529Skarels 
28816529Skarels 	/*
28916529Skarels 	 * but proc[0] is special ...
29016529Skarels 	 */
29116529Skarels 
29216529Skarels 	allproc = p;
29316529Skarels 	p->p_nxt = NULL;
29416529Skarels 	p->p_prev = &allproc;
29516529Skarels 
29616529Skarels 	zombproc = NULL;
29716529Skarels }
29835810Smarc 
29937728Smckusick #ifdef debug
30035810Smarc /* DEBUG */
30135810Smarc pgrpdump()
30235810Smarc {
30335810Smarc 	register struct pgrp *pgrp;
30435810Smarc 	register struct proc *p;
30535810Smarc 	register i;
30635810Smarc 
30735810Smarc 	for (i=0; i<PIDHSZ; i++) {
30835810Smarc 		if (pgrphash[i]) {
30935810Smarc 		  printf("\tindx %d\n", i);
31035810Smarc 		  for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) {
31135810Smarc 		    printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n",
31235810Smarc 			pgrp, pgrp->pg_id, pgrp->pg_session,
31335810Smarc 			pgrp->pg_session->s_count, pgrp->pg_mem);
31435810Smarc 		    for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) {
31535810Smarc 			printf("\t\tpid %d addr %x pgrp %x\n",
31635810Smarc 				p->p_pid, p, p->p_pgrp);
31735810Smarc 		    }
31835810Smarc 		  }
31935810Smarc 
32035810Smarc 		}
32135810Smarc 	}
32235810Smarc }
32337728Smckusick #endif /* debug */
324