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