xref: /csrg-svn/sys/kern/kern_proc.c (revision 37728)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)kern_proc.c	7.6 (Berkeley) 05/09/89
18  */
19 
20 #include "param.h"
21 #include "systm.h"
22 #include "map.h"
23 #include "user.h"
24 #include "kernel.h"
25 #include "proc.h"
26 #include "buf.h"
27 #include "seg.h"
28 #include "acct.h"
29 #include "wait.h"
30 #include "vm.h"
31 #include "text.h"
32 #include "file.h"
33 #include "../ufs/quota.h"
34 #include "uio.h"
35 #include "malloc.h"
36 #include "mbuf.h"
37 #include "tty.h"
38 
39 #include "machine/reg.h"
40 #include "machine/pte.h"
41 #include "machine/psl.h"
42 
43 /*
44  * Clear any pending stops for top and all descendents.
45  */
46 spgrp(top)
47 	struct proc *top;
48 {
49 	register struct proc *p;
50 	int f = 0;
51 
52 	p = top;
53 	for (;;) {
54 		p->p_sig &=
55 			  ~(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU));
56 		f++;
57 		/*
58 		 * If this process has children, descend to them next,
59 		 * otherwise do any siblings, and if done with this level,
60 		 * follow back up the tree (but not past top).
61 		 */
62 		if (p->p_cptr)
63 			p = p->p_cptr;
64 		else if (p == top)
65 			return (f);
66 		else if (p->p_osptr)
67 			p = p->p_osptr;
68 		else for (;;) {
69 			p = p->p_pptr;
70 			if (p == top)
71 				return (f);
72 			if (p->p_osptr) {
73 				p = p->p_osptr;
74 				break;
75 			}
76 		}
77 	}
78 }
79 
80 /*
81  * Is p an inferior of the current process?
82  */
83 inferior(p)
84 	register struct proc *p;
85 {
86 	for (; p != u.u_procp; p = p->p_pptr)
87 		if (p->p_ppid == 0)
88 			return (0);
89 	return (1);
90 }
91 
92 struct proc *
93 pfind(pid)
94 	register pid;
95 {
96 	register struct proc *p;
97 
98 	for (p = &proc[pidhash[PIDHASH(pid)]] ;
99 	     p != &proc[0]; p = &proc[p->p_idhash])
100 		if (p->p_pid == pid)
101 			return (p);
102 	return ((struct proc *)0);
103 }
104 
105 /*
106  * Locate a process group by number
107  */
108 struct pgrp *
109 pgfind(pgid)
110 	register pid_t pgid;
111 {
112 	register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)];
113 
114 	for (; pgrp; pgrp = pgrp->pg_hforw)
115 		if (pgrp->pg_id == pgid)
116 			return(pgrp);
117 	return ((struct pgrp *)0);
118 }
119 
120 /*
121  * Move p to a new or existing process group (and session)
122  */
123 pgmv(p, pgid, mksess)
124 	register struct proc *p;
125 	pid_t pgid;
126 {
127 	register struct pgrp *pgrp = pgfind(pgid);
128 	register struct proc **pp = &p->p_pgrp->pg_mem;
129 	register struct proc *cp;
130 	struct pgrp *opgrp;
131 	register n;
132 
133 	if (pgrp && mksess)	/* firewalls */
134 		panic("pgmv: setsid into non-empty pgrp");
135 	if (SESS_LEADER(p))
136 		panic("pgmv: session leader attempted setpgrp");
137 	if (pgrp == NULL) {
138 		/*
139 		 * new process group
140 		 */
141 		if (p->p_pid != pgid)
142 			panic("pgmv: new pgrp and pid != pgid");
143 		MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
144 		       M_WAITOK);
145 		if (mksess) {
146 			register struct session *sess;
147 			/*
148 			 * new session
149 			 */
150 			MALLOC(sess, struct session *, sizeof(struct session),
151 				M_SESSION, M_WAITOK);
152 			sess->s_leader = p;
153 			sess->s_count = 1;
154 			pgrp->pg_session = sess;
155 			if (p != u.u_procp)
156 				panic("pgmv: mksession and p != u.u_procp");
157 			u.u_ttyp = NULL;
158 			u.u_ttyd = 0;
159 		} else {
160 			pgrp->pg_session = p->p_session;
161 			pgrp->pg_session->s_count++;
162 		}
163 		pgrp->pg_id = pgid;
164 		pgrp->pg_hforw = pgrphash[n=PIDHASH(pgid)];
165 		pgrphash[n] = pgrp;
166 		pgrp->pg_jobc = 0;
167 		pgrp->pg_mem = 0;
168 	}
169 	/*
170 	 * adjust eligibility of affected pgrps to participate in job control
171 	 */
172 	if (PGRP_JOBC(p))
173 		p->p_pgrp->pg_jobc--;
174 	for (cp = p->p_cptr; cp; cp = cp->p_osptr)
175 		if (PGRP_JOBC(cp))
176 			cp->p_pgrp->pg_jobc--;
177 	/*
178 	 * unlink p from old process group
179 	 */
180 	for (; *pp; pp = &(*pp)->p_pgrpnxt)
181 		if (*pp == p) {
182 			*pp = p->p_pgrpnxt;
183 			goto done;
184 		}
185 	panic("pgmv: can't find p on old pgrp");
186 done:
187 	/*
188 	 * link into new one
189 	 */
190 	p->p_pgrpnxt = pgrp->pg_mem;
191 	pgrp->pg_mem = p;
192 	opgrp = p->p_pgrp;
193 	p->p_pgrp = pgrp;
194 	/*
195 	 * adjust eligibility of affected pgrps to participate in job control
196 	 */
197 	if (PGRP_JOBC(p))
198 		p->p_pgrp->pg_jobc++;
199 	for (cp = p->p_cptr; cp; cp = cp->p_osptr)
200 		if (PGRP_JOBC(cp))
201 			cp->p_pgrp->pg_jobc++;
202 	/*
203 	 * old pgrp empty?
204 	 */
205 	if (!opgrp->pg_mem)
206 		pgdelete(opgrp);
207 }
208 
209 /*
210  * remove process from process group
211  */
212 pgrm(p)
213 	register struct proc *p;
214 {
215 	register struct proc **pp = &p->p_pgrp->pg_mem;
216 
217 	for (; *pp; pp = &(*pp)->p_pgrpnxt)
218 		if (*pp == p) {
219 			*pp = p->p_pgrpnxt;
220 			goto done;
221 		}
222 	panic("pgrm: can't find p in pgrp");
223 done:
224 	if (!p->p_pgrp->pg_mem)
225 		pgdelete(p->p_pgrp);
226 	p->p_pgrp = 0;
227 }
228 
229 /*
230  * delete a process group
231  */
232 pgdelete(pgrp)
233 	register struct pgrp *pgrp;
234 {
235 	register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)];
236 
237 	for (; *pgp; pgp = &(*pgp)->pg_hforw)
238 		if (*pgp == pgrp) {
239 			*pgp = pgrp->pg_hforw;
240 			goto done;
241 		}
242 	panic("pgdelete: can't find pgrp on hash chain");
243 done:
244 	if (--pgrp->pg_session->s_count == 0)
245 		FREE(pgrp->pg_session, M_SESSION);
246 	FREE(pgrp, M_PGRP);
247 }
248 
249 /*
250  * init the process queues
251  */
252 pqinit()
253 {
254 	register struct proc *p;
255 
256 	/*
257 	 * most procs are initially on freequeue
258 	 *	nb: we place them there in their "natural" order.
259 	 */
260 
261 	freeproc = NULL;
262 	for (p = procNPROC; --p > proc; freeproc = p)
263 		p->p_nxt = freeproc;
264 
265 	/*
266 	 * but proc[0] is special ...
267 	 */
268 
269 	allproc = p;
270 	p->p_nxt = NULL;
271 	p->p_prev = &allproc;
272 
273 	zombproc = NULL;
274 }
275 
276 #ifdef debug
277 /* DEBUG */
278 pgrpdump()
279 {
280 	register struct pgrp *pgrp;
281 	register struct proc *p;
282 	register i;
283 
284 	for (i=0; i<PIDHSZ; i++) {
285 		if (pgrphash[i]) {
286 		  printf("\tindx %d\n", i);
287 		  for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) {
288 		    printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n",
289 			pgrp, pgrp->pg_id, pgrp->pg_session,
290 			pgrp->pg_session->s_count, pgrp->pg_mem);
291 		    for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) {
292 			printf("\t\tpid %d addr %x pgrp %x\n",
293 				p->p_pid, p, p->p_pgrp);
294 		    }
295 		  }
296 
297 		}
298 	}
299 }
300 #endif /* debug */
301