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