xref: /original-bsd/sys/kern/kern_proc.c (revision 51e389b0)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)kern_proc.c	7.13 (Berkeley) 12/05/90
8  */
9 
10 #include "param.h"
11 #include "systm.h"
12 #include "map.h"
13 #include "user.h"
14 #include "kernel.h"
15 #include "proc.h"
16 #include "buf.h"
17 #include "seg.h"
18 #include "acct.h"
19 #include "wait.h"
20 #include "file.h"
21 #include "../ufs/quota.h"
22 #include "uio.h"
23 #include "malloc.h"
24 #include "mbuf.h"
25 #include "ioctl.h"
26 #include "tty.h"
27 
28 #include "machine/reg.h"
29 #include "machine/psl.h"
30 
31 /*
32  * Is p an inferior of the current process?
33  */
34 inferior(p)
35 	register struct proc *p;
36 {
37 
38 	for (; p != u.u_procp; p = p->p_pptr)
39 		if (p->p_ppid == 0)
40 			return (0);
41 	return (1);
42 }
43 
44 /*
45  * Locate a process by number
46  */
47 struct proc *
48 pfind(pid)
49 	register pid;
50 {
51 	register struct proc *p = pidhash[PIDHASH(pid)];
52 
53 	for (; p; p = p->p_hash)
54 		if (p->p_pid == pid)
55 			return (p);
56 	return ((struct proc *)0);
57 }
58 
59 /*
60  * Locate a process group by number
61  */
62 struct pgrp *
63 pgfind(pgid)
64 	register pid_t pgid;
65 {
66 	register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)];
67 
68 	for (; pgrp; pgrp = pgrp->pg_hforw)
69 		if (pgrp->pg_id == pgid)
70 			return (pgrp);
71 	return ((struct pgrp *)0);
72 }
73 
74 /*
75  * Move p to a new or existing process group (and session)
76  */
77 pgmv(p, pgid, mksess)
78 	register struct proc *p;
79 	pid_t pgid;
80 {
81 	register struct pgrp *pgrp = pgfind(pgid);
82 	register struct proc **pp;
83 	register struct proc *cp;
84 	int n;
85 
86 #ifdef DIAGNOSTIC
87 	if (pgrp && mksess)	/* firewalls */
88 		panic("pgmv: setsid into non-empty pgrp");
89 	if (SESS_LEADER(p))
90 		panic("pgmv: session leader attempted setpgrp");
91 #endif
92 	if (pgrp == NULL) {
93 		/*
94 		 * new process group
95 		 */
96 #ifdef DIAGNOSTIC
97 		if (p->p_pid != pgid)
98 			panic("pgmv: new pgrp and pid != pgid");
99 #endif
100 		MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
101 		       M_WAITOK);
102 		if (mksess) {
103 			register struct session *sess;
104 			/*
105 			 * new session
106 			 */
107 			MALLOC(sess, struct session *, sizeof(struct session),
108 				M_SESSION, M_WAITOK);
109 			sess->s_leader = p;
110 			sess->s_count = 1;
111 			sess->s_ttyvp = NULL;
112 			sess->s_ttyp = NULL;
113 			p->p_flag &= ~SCTTY;
114 			pgrp->pg_session = sess;
115 #ifdef DIAGNOSTIC
116 			if (p != u.u_procp)
117 				panic("pgmv: mksession and p != u.u_procp");
118 #endif
119 		} else {
120 			pgrp->pg_session = p->p_session;
121 			pgrp->pg_session->s_count++;
122 		}
123 		pgrp->pg_id = pgid;
124 		pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)];
125 		pgrphash[n] = pgrp;
126 		pgrp->pg_jobc = 0;
127 		pgrp->pg_mem = NULL;
128 	} else if (pgrp == p->p_pgrp)
129 		return;
130 
131 	/*
132 	 * Adjust eligibility of affected pgrps to participate in job control.
133 	 * Increment eligibility counts before decrementing, otherwise we
134 	 * could reach 0 spuriously during the first call.
135 	 */
136 	fixjobc(p, pgrp, 1);
137 	fixjobc(p, p->p_pgrp, 0);
138 
139 	/*
140 	 * unlink p from old process group
141 	 */
142 	for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt)
143 		if (*pp == p) {
144 			*pp = p->p_pgrpnxt;
145 			goto done;
146 		}
147 	panic("pgmv: can't find p on old pgrp");
148 done:
149 	/*
150 	 * delete old if empty
151 	 */
152 	if (p->p_pgrp->pg_mem == 0)
153 		pgdelete(p->p_pgrp);
154 	/*
155 	 * link into new one
156 	 */
157 	p->p_pgrp = pgrp;
158 	p->p_pgrpnxt = pgrp->pg_mem;
159 	pgrp->pg_mem = p;
160 }
161 
162 /*
163  * remove process from process group
164  */
165 pgrm(p)
166 	register struct proc *p;
167 {
168 	register struct proc **pp = &p->p_pgrp->pg_mem;
169 
170 	for (; *pp; pp = &(*pp)->p_pgrpnxt)
171 		if (*pp == p) {
172 			*pp = p->p_pgrpnxt;
173 			goto done;
174 		}
175 	panic("pgrm: can't find p in pgrp");
176 done:
177 	if (!p->p_pgrp->pg_mem)
178 		pgdelete(p->p_pgrp);
179 	p->p_pgrp = 0;
180 }
181 
182 /*
183  * delete a process group
184  */
185 pgdelete(pgrp)
186 	register struct pgrp *pgrp;
187 {
188 	register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)];
189 
190 	if (pgrp->pg_session->s_ttyp != NULL &&
191 	    pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
192 		pgrp->pg_session->s_ttyp->t_pgrp = NULL;
193 	for (; *pgp; pgp = &(*pgp)->pg_hforw)
194 		if (*pgp == pgrp) {
195 			*pgp = pgrp->pg_hforw;
196 			goto done;
197 		}
198 	panic("pgdelete: can't find pgrp on hash chain");
199 done:
200 	if (--pgrp->pg_session->s_count == 0)
201 		FREE(pgrp->pg_session, M_SESSION);
202 	FREE(pgrp, M_PGRP);
203 }
204 
205 /*
206  * Adjust pgrp jobc counters when specified process changes process group.
207  * We count the number of processes in each process group that "qualify"
208  * the group for terminal job control (those with a parent in a different
209  * process group of the same session).  If that count reaches zero, the
210  * process group becomes orphaned.  Check both the specified process'
211  * process group and that of its children.
212  * entering == 0 => p is leaving specified group.
213  * entering == 1 => p is entering specified group.
214  */
215 fixjobc(p, pgrp, entering)
216 	register struct proc *p;
217 	register struct pgrp *pgrp;
218 	int entering;
219 {
220 	register struct pgrp *hispgrp;
221 	register struct session *mysession = pgrp->pg_session;
222 
223 	/*
224 	 * Check p's parent to see whether p qualifies its own process
225 	 * group; if so, adjust count for p's process group.
226 	 */
227 	if ((hispgrp = p->p_pptr->p_pgrp) != pgrp &&
228 	    hispgrp->pg_session == mysession)
229 		if (entering)
230 			pgrp->pg_jobc++;
231 		else if (--pgrp->pg_jobc == 0)
232 			orphanpg(pgrp);
233 
234 	/*
235 	 * Check this process' children to see whether they qualify
236 	 * their process groups; if so, adjust counts for children's
237 	 * process groups.
238 	 */
239 	for (p = p->p_cptr; p; p = p->p_osptr)
240 		if ((hispgrp = p->p_pgrp) != pgrp &&
241 		    hispgrp->pg_session == mysession &&
242 		    p->p_stat != SZOMB)
243 			if (entering)
244 				hispgrp->pg_jobc++;
245 			else if (--hispgrp->pg_jobc == 0)
246 				orphanpg(hispgrp);
247 }
248 
249 /*
250  * A process group has become orphaned;
251  * if there are any stopped processes in the group,
252  * hang-up all process in that group.
253  */
254 static
255 orphanpg(pg)
256 	struct pgrp *pg;
257 {
258 	register struct proc *p;
259 
260 	for (p = pg->pg_mem; p; p = p->p_pgrpnxt) {
261 		if (p->p_stat == SSTOP) {
262 			for (p = pg->pg_mem; p; p = p->p_pgrpnxt) {
263 				psignal(p, SIGHUP);
264 				psignal(p, SIGCONT);
265 			}
266 			return;
267 		}
268 	}
269 }
270 
271 /*
272  * init the process queues
273  */
274 pqinit()
275 {
276 	register struct proc *p;
277 
278 	/*
279 	 * most procs are initially on freequeue
280 	 *	nb: we place them there in their "natural" order.
281 	 */
282 
283 	freeproc = NULL;
284 	for (p = procNPROC; --p > proc; freeproc = p)
285 		p->p_nxt = freeproc;
286 
287 	/*
288 	 * but proc[0] is special ...
289 	 */
290 
291 	allproc = p;
292 	p->p_nxt = NULL;
293 	p->p_prev = &allproc;
294 
295 	zombproc = NULL;
296 }
297 
298 #ifdef debug
299 /* DEBUG */
300 pgrpdump()
301 {
302 	register struct pgrp *pgrp;
303 	register struct proc *p;
304 	register i;
305 
306 	for (i=0; i<PIDHSZ; i++) {
307 		if (pgrphash[i]) {
308 		  printf("\tindx %d\n", i);
309 		  for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) {
310 		    printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n",
311 			pgrp, pgrp->pg_id, pgrp->pg_session,
312 			pgrp->pg_session->s_count, pgrp->pg_mem);
313 		    for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) {
314 			printf("\t\tpid %d addr %x pgrp %x\n",
315 				p->p_pid, p, p->p_pgrp);
316 		    }
317 		  }
318 
319 		}
320 	}
321 }
322 #endif /* debug */
323