xref: /original-bsd/sys/kern/kern_proc.c (revision abd50c55)
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.9 (Berkeley) 04/03/90
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 "ioctl.h"
38 #include "tty.h"
39 
40 #include "machine/reg.h"
41 #include "machine/pte.h"
42 #include "machine/psl.h"
43 
44 /*
45  * Clear any pending stops for top and all descendents.
46  */
47 spgrp(top)
48 	struct proc *top;
49 {
50 	register struct proc *p;
51 	int f = 0;
52 
53 	p = top;
54 	for (;;) {
55 		p->p_sig &=
56 			  ~(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU));
57 		f++;
58 		/*
59 		 * If this process has children, descend to them next,
60 		 * otherwise do any siblings, and if done with this level,
61 		 * follow back up the tree (but not past top).
62 		 */
63 		if (p->p_cptr)
64 			p = p->p_cptr;
65 		else if (p == top)
66 			return (f);
67 		else if (p->p_osptr)
68 			p = p->p_osptr;
69 		else for (;;) {
70 			p = p->p_pptr;
71 			if (p == top)
72 				return (f);
73 			if (p->p_osptr) {
74 				p = p->p_osptr;
75 				break;
76 			}
77 		}
78 	}
79 }
80 
81 /*
82  * Is p an inferior of the current process?
83  */
84 inferior(p)
85 	register struct proc *p;
86 {
87 	for (; p != u.u_procp; p = p->p_pptr)
88 		if (p->p_ppid == 0)
89 			return (0);
90 	return (1);
91 }
92 
93 /*
94  * Locate a process by number
95  */
96 struct proc *
97 pfind(pid)
98 	register pid;
99 {
100 	register struct proc *p = pidhash[PIDHASH(pid)];
101 
102 	for (; p; p = p->p_hash)
103 		if (p->p_pid == pid)
104 			return (p);
105 	return ((struct proc *)0);
106 }
107 
108 /*
109  * Locate a process group by number
110  */
111 struct pgrp *
112 pgfind(pgid)
113 	register pid_t pgid;
114 {
115 	register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)];
116 
117 	for (; pgrp; pgrp = pgrp->pg_hforw)
118 		if (pgrp->pg_id == pgid)
119 			return (pgrp);
120 	return ((struct pgrp *)0);
121 }
122 
123 /*
124  * Move p to a new or existing process group (and session)
125  */
126 pgmv(p, pgid, mksess)
127 	register struct proc *p;
128 	pid_t pgid;
129 {
130 	register struct pgrp *pgrp = pgfind(pgid);
131 	register struct proc **pp = &p->p_pgrp->pg_mem;
132 	register struct proc *cp;
133 	struct pgrp *opgrp;
134 	register n;
135 
136 #ifdef DIAGNOSTIC
137 	if (pgrp && mksess)	/* firewalls */
138 		panic("pgmv: setsid into non-empty pgrp");
139 	if (SESS_LEADER(p))
140 		panic("pgmv: session leader attempted setpgrp");
141 #endif
142 	if (pgrp == NULL) {
143 		/*
144 		 * new process group
145 		 */
146 #ifdef DIAGNOSTIC
147 		if (p->p_pid != pgid)
148 			panic("pgmv: new pgrp and pid != pgid");
149 #endif
150 		MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
151 		       M_WAITOK);
152 		if (mksess) {
153 			register struct session *sess;
154 			/*
155 			 * new session
156 			 */
157 			MALLOC(sess, struct session *, sizeof(struct session),
158 				M_SESSION, M_WAITOK);
159 			sess->s_leader = p;
160 			sess->s_count = 1;
161 			sess->s_ttyvp = NULL;
162 			sess->s_ttyp = NULL;
163 			p->p_flag &= ~SCTTY;
164 			pgrp->pg_session = sess;
165 #ifdef DIAGNOSTIC
166 			if (p != u.u_procp)
167 				panic("pgmv: mksession and p != u.u_procp");
168 #endif
169 		} else {
170 			pgrp->pg_session = p->p_session;
171 			pgrp->pg_session->s_count++;
172 		}
173 		pgrp->pg_id = pgid;
174 		pgrp->pg_hforw = pgrphash[n=PIDHASH(pgid)];
175 		pgrphash[n] = pgrp;
176 		pgrp->pg_jobc = 0;
177 		pgrp->pg_mem = NULL;
178 	}
179 	/*
180 	 * adjust eligibility of affected pgrps to participate in job control
181 	 */
182 	if (PGRP_JOBC(p))
183 		p->p_pgrp->pg_jobc--;
184 	for (cp = p->p_cptr; cp; cp = cp->p_osptr)
185 		if (PGRP_JOBC(cp))
186 			cp->p_pgrp->pg_jobc--;
187 	/*
188 	 * unlink p from old process group
189 	 */
190 	for (; *pp; pp = &(*pp)->p_pgrpnxt)
191 		if (*pp == p) {
192 			*pp = p->p_pgrpnxt;
193 			goto done;
194 		}
195 	panic("pgmv: can't find p on old pgrp");
196 done:
197 	/*
198 	 * link into new one
199 	 */
200 	p->p_pgrpnxt = pgrp->pg_mem;
201 	pgrp->pg_mem = p;
202 	opgrp = p->p_pgrp;
203 	p->p_pgrp = pgrp;
204 	/*
205 	 * adjust eligibility of affected pgrps to participate in job control
206 	 */
207 	if (PGRP_JOBC(p))
208 		p->p_pgrp->pg_jobc++;
209 	for (cp = p->p_cptr; cp; cp = cp->p_osptr)
210 		if (PGRP_JOBC(cp))
211 			cp->p_pgrp->pg_jobc++;
212 	/*
213 	 * old pgrp empty?
214 	 */
215 	if (!opgrp->pg_mem)
216 		pgdelete(opgrp);
217 }
218 
219 /*
220  * remove process from process group
221  */
222 pgrm(p)
223 	register struct proc *p;
224 {
225 	register struct proc **pp = &p->p_pgrp->pg_mem;
226 
227 	for (; *pp; pp = &(*pp)->p_pgrpnxt)
228 		if (*pp == p) {
229 			*pp = p->p_pgrpnxt;
230 			goto done;
231 		}
232 	panic("pgrm: can't find p in pgrp");
233 done:
234 	if (!p->p_pgrp->pg_mem)
235 		pgdelete(p->p_pgrp);
236 	p->p_pgrp = 0;
237 }
238 
239 /*
240  * delete a process group
241  */
242 pgdelete(pgrp)
243 	register struct pgrp *pgrp;
244 {
245 	register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)];
246 
247 	if (pgrp->pg_session->s_ttyp != NULL &&
248 	    pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
249 		pgrp->pg_session->s_ttyp->t_pgrp = NULL;
250 	for (; *pgp; pgp = &(*pgp)->pg_hforw)
251 		if (*pgp == pgrp) {
252 			*pgp = pgrp->pg_hforw;
253 			goto done;
254 		}
255 	panic("pgdelete: can't find pgrp on hash chain");
256 done:
257 	if (--pgrp->pg_session->s_count == 0)
258 		FREE(pgrp->pg_session, M_SESSION);
259 	FREE(pgrp, M_PGRP);
260 }
261 
262 /*
263  * init the process queues
264  */
265 pqinit()
266 {
267 	register struct proc *p;
268 
269 	/*
270 	 * most procs are initially on freequeue
271 	 *	nb: we place them there in their "natural" order.
272 	 */
273 
274 	freeproc = NULL;
275 	for (p = procNPROC; --p > proc; freeproc = p)
276 		p->p_nxt = freeproc;
277 
278 	/*
279 	 * but proc[0] is special ...
280 	 */
281 
282 	allproc = p;
283 	p->p_nxt = NULL;
284 	p->p_prev = &allproc;
285 
286 	zombproc = NULL;
287 }
288 
289 #ifdef debug
290 /* DEBUG */
291 pgrpdump()
292 {
293 	register struct pgrp *pgrp;
294 	register struct proc *p;
295 	register i;
296 
297 	for (i=0; i<PIDHSZ; i++) {
298 		if (pgrphash[i]) {
299 		  printf("\tindx %d\n", i);
300 		  for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) {
301 		    printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n",
302 			pgrp, pgrp->pg_id, pgrp->pg_session,
303 			pgrp->pg_session->s_count, pgrp->pg_mem);
304 		    for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) {
305 			printf("\t\tpid %d addr %x pgrp %x\n",
306 				p->p_pid, p, p->p_pgrp);
307 		    }
308 		  }
309 
310 		}
311 	}
312 }
313 #endif /* debug */
314