update for new VM
[unix-history] / usr / src / sys / kern / kern_proc.c
CommitLineData
da7c5cc6 1/*
c4ec2128
KM
2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3 * All rights reserved.
da7c5cc6 4 *
dbf0c423 5 * %sccs.include.redist.c%
c4ec2128 6 *
9db58063 7 * @(#)kern_proc.c 7.13 (Berkeley) %G%
da7c5cc6 8 */
961945a8 9
94368568
JB
10#include "param.h"
11#include "systm.h"
12#include "map.h"
94368568
JB
13#include "user.h"
14#include "kernel.h"
15#include "proc.h"
16#include "buf.h"
94368568
JB
17#include "seg.h"
18#include "acct.h"
19#include "wait.h"
94368568 20#include "file.h"
c4ec2128 21#include "../ufs/quota.h"
94368568 22#include "uio.h"
8fe87cbb 23#include "malloc.h"
94368568 24#include "mbuf.h"
5b6ff773 25#include "ioctl.h"
8fe87cbb 26#include "tty.h"
a1bce776 27
d301d150 28#include "machine/reg.h"
d301d150
KM
29#include "machine/psl.h"
30
29dd101b 31/*
4147b3f6 32 * Is p an inferior of the current process?
29dd101b 33 */
4147b3f6 34inferior(p)
a2a2a0d6 35 register struct proc *p;
29dd101b 36{
2dccc728 37
4147b3f6
BJ
38 for (; p != u.u_procp; p = p->p_pptr)
39 if (p->p_ppid == 0)
40 return (0);
41 return (1);
29dd101b 42}
a2a2a0d6 43
b3ce9b0f
MK
44/*
45 * Locate a process by number
46 */
a2a2a0d6
BJ
47struct proc *
48pfind(pid)
8fe87cbb 49 register pid;
a2a2a0d6 50{
b3ce9b0f 51 register struct proc *p = pidhash[PIDHASH(pid)];
a2a2a0d6 52
b3ce9b0f 53 for (; p; p = p->p_hash)
a2a2a0d6
BJ
54 if (p->p_pid == pid)
55 return (p);
56 return ((struct proc *)0);
57}
1d348849 58
8fe87cbb
MT
59/*
60 * Locate a process group by number
61 */
62struct pgrp *
63pgfind(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)
b3ce9b0f 70 return (pgrp);
8fe87cbb
MT
71 return ((struct pgrp *)0);
72}
73
74/*
75 * Move p to a new or existing process group (and session)
76 */
77pgmv(p, pgid, mksess)
78 register struct proc *p;
79 pid_t pgid;
80{
81 register struct pgrp *pgrp = pgfind(pgid);
2dccc728 82 register struct proc **pp;
8fe87cbb 83 register struct proc *cp;
2dccc728 84 int n;
8fe87cbb 85
944e89dc 86#ifdef DIAGNOSTIC
8fe87cbb 87 if (pgrp && mksess) /* firewalls */
2e8f8cae 88 panic("pgmv: setsid into non-empty pgrp");
8fe87cbb 89 if (SESS_LEADER(p))
2e8f8cae 90 panic("pgmv: session leader attempted setpgrp");
944e89dc 91#endif
2e8f8cae 92 if (pgrp == NULL) {
8fe87cbb
MT
93 /*
94 * new process group
95 */
944e89dc 96#ifdef DIAGNOSTIC
8fe87cbb 97 if (p->p_pid != pgid)
2e8f8cae 98 panic("pgmv: new pgrp and pid != pgid");
944e89dc 99#endif
8fe87cbb
MT
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;
944e89dc
MT
111 sess->s_ttyvp = NULL;
112 sess->s_ttyp = NULL;
113 p->p_flag &= ~SCTTY;
8fe87cbb 114 pgrp->pg_session = sess;
944e89dc 115#ifdef DIAGNOSTIC
8fe87cbb
MT
116 if (p != u.u_procp)
117 panic("pgmv: mksession and p != u.u_procp");
944e89dc 118#endif
8fe87cbb
MT
119 } else {
120 pgrp->pg_session = p->p_session;
121 pgrp->pg_session->s_count++;
122 }
123 pgrp->pg_id = pgid;
2dccc728 124 pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)];
8fe87cbb
MT
125 pgrphash[n] = pgrp;
126 pgrp->pg_jobc = 0;
944e89dc 127 pgrp->pg_mem = NULL;
69ed180a
MT
128 } else if (pgrp == p->p_pgrp)
129 return;
2dccc728 130
8fe87cbb 131 /*
2dccc728
MK
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.
8fe87cbb 135 */
2dccc728
MK
136 fixjobc(p, pgrp, 1);
137 fixjobc(p, p->p_pgrp, 0);
138
8fe87cbb
MT
139 /*
140 * unlink p from old process group
141 */
2dccc728 142 for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt)
8fe87cbb
MT
143 if (*pp == p) {
144 *pp = p->p_pgrpnxt;
145 goto done;
146 }
2e8f8cae 147 panic("pgmv: can't find p on old pgrp");
8fe87cbb 148done:
2dccc728
MK
149 /*
150 * delete old if empty
151 */
152 if (p->p_pgrp->pg_mem == 0)
153 pgdelete(p->p_pgrp);
8fe87cbb
MT
154 /*
155 * link into new one
156 */
2dccc728 157 p->p_pgrp = pgrp;
8fe87cbb
MT
158 p->p_pgrpnxt = pgrp->pg_mem;
159 pgrp->pg_mem = p;
8fe87cbb
MT
160}
161
162/*
163 * remove process from process group
164 */
165pgrm(p)
166 register struct proc *p;
167{
168 register struct proc **pp = &p->p_pgrp->pg_mem;
8fe87cbb
MT
169
170 for (; *pp; pp = &(*pp)->p_pgrpnxt)
171 if (*pp == p) {
172 *pp = p->p_pgrpnxt;
173 goto done;
174 }
2e8f8cae 175 panic("pgrm: can't find p in pgrp");
8fe87cbb
MT
176done:
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 */
185pgdelete(pgrp)
186 register struct pgrp *pgrp;
187{
188 register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)];
189
944e89dc
MT
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;
8fe87cbb
MT
193 for (; *pgp; pgp = &(*pgp)->pg_hforw)
194 if (*pgp == pgrp) {
195 *pgp = pgrp->pg_hforw;
196 goto done;
197 }
2e8f8cae 198 panic("pgdelete: can't find pgrp on hash chain");
8fe87cbb
MT
199done:
200 if (--pgrp->pg_session->s_count == 0)
201 FREE(pgrp->pg_session, M_SESSION);
202 FREE(pgrp, M_PGRP);
203}
204
69ed180a 205/*
2dccc728
MK
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.
69ed180a 214 */
2dccc728 215fixjobc(p, pgrp, entering)
69ed180a 216 register struct proc *p;
2dccc728
MK
217 register struct pgrp *pgrp;
218 int entering;
69ed180a 219{
2dccc728
MK
220 register struct pgrp *hispgrp;
221 register struct session *mysession = pgrp->pg_session;
69ed180a 222
2dccc728
MK
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 &&
69ed180a 228 hispgrp->pg_session == mysession)
2dccc728
MK
229 if (entering)
230 pgrp->pg_jobc++;
231 else if (--pgrp->pg_jobc == 0)
232 orphanpg(pgrp);
69ed180a 233
2dccc728
MK
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 &&
69ed180a
MT
241 hispgrp->pg_session == mysession &&
242 p->p_stat != SZOMB)
2dccc728 243 if (entering)
69ed180a 244 hispgrp->pg_jobc++;
2dccc728
MK
245 else if (--hispgrp->pg_jobc == 0)
246 orphanpg(hispgrp);
247}
69ed180a 248
2dccc728
MK
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 */
254static
255orphanpg(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);
69ed180a 265 }
2dccc728
MK
266 return;
267 }
268 }
69ed180a 269}
2dccc728 270
1d348849
MK
271/*
272 * init the process queues
273 */
274pqinit()
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}
8fe87cbb 297
c4ec2128 298#ifdef debug
8fe87cbb
MT
299/* DEBUG */
300pgrpdump()
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}
c4ec2128 322#endif /* debug */