fix jobc adjustments so we increment before decrementing, avoiding spurious
[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 *
2dccc728 7 * @(#)kern_proc.c 7.12 (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"
20#include "vm.h"
21#include "text.h"
22#include "file.h"
c4ec2128 23#include "../ufs/quota.h"
94368568 24#include "uio.h"
8fe87cbb 25#include "malloc.h"
94368568 26#include "mbuf.h"
5b6ff773 27#include "ioctl.h"
8fe87cbb 28#include "tty.h"
a1bce776 29
d301d150
KM
30#include "machine/reg.h"
31#include "machine/pte.h"
32#include "machine/psl.h"
33
29dd101b 34/*
4147b3f6 35 * Is p an inferior of the current process?
29dd101b 36 */
4147b3f6 37inferior(p)
a2a2a0d6 38 register struct proc *p;
29dd101b 39{
2dccc728 40
4147b3f6
BJ
41 for (; p != u.u_procp; p = p->p_pptr)
42 if (p->p_ppid == 0)
43 return (0);
44 return (1);
29dd101b 45}
a2a2a0d6 46
b3ce9b0f
MK
47/*
48 * Locate a process by number
49 */
a2a2a0d6
BJ
50struct proc *
51pfind(pid)
8fe87cbb 52 register pid;
a2a2a0d6 53{
b3ce9b0f 54 register struct proc *p = pidhash[PIDHASH(pid)];
a2a2a0d6 55
b3ce9b0f 56 for (; p; p = p->p_hash)
a2a2a0d6
BJ
57 if (p->p_pid == pid)
58 return (p);
59 return ((struct proc *)0);
60}
1d348849 61
8fe87cbb
MT
62/*
63 * Locate a process group by number
64 */
65struct pgrp *
66pgfind(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)
b3ce9b0f 73 return (pgrp);
8fe87cbb
MT
74 return ((struct pgrp *)0);
75}
76
77/*
78 * Move p to a new or existing process group (and session)
79 */
80pgmv(p, pgid, mksess)
81 register struct proc *p;
82 pid_t pgid;
83{
84 register struct pgrp *pgrp = pgfind(pgid);
2dccc728 85 register struct proc **pp;
8fe87cbb 86 register struct proc *cp;
2dccc728 87 int n;
8fe87cbb 88
944e89dc 89#ifdef DIAGNOSTIC
8fe87cbb 90 if (pgrp && mksess) /* firewalls */
2e8f8cae 91 panic("pgmv: setsid into non-empty pgrp");
8fe87cbb 92 if (SESS_LEADER(p))
2e8f8cae 93 panic("pgmv: session leader attempted setpgrp");
944e89dc 94#endif
2e8f8cae 95 if (pgrp == NULL) {
8fe87cbb
MT
96 /*
97 * new process group
98 */
944e89dc 99#ifdef DIAGNOSTIC
8fe87cbb 100 if (p->p_pid != pgid)
2e8f8cae 101 panic("pgmv: new pgrp and pid != pgid");
944e89dc 102#endif
8fe87cbb
MT
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;
944e89dc
MT
114 sess->s_ttyvp = NULL;
115 sess->s_ttyp = NULL;
116 p->p_flag &= ~SCTTY;
8fe87cbb 117 pgrp->pg_session = sess;
944e89dc 118#ifdef DIAGNOSTIC
8fe87cbb
MT
119 if (p != u.u_procp)
120 panic("pgmv: mksession and p != u.u_procp");
944e89dc 121#endif
8fe87cbb
MT
122 } else {
123 pgrp->pg_session = p->p_session;
124 pgrp->pg_session->s_count++;
125 }
126 pgrp->pg_id = pgid;
2dccc728 127 pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)];
8fe87cbb
MT
128 pgrphash[n] = pgrp;
129 pgrp->pg_jobc = 0;
944e89dc 130 pgrp->pg_mem = NULL;
69ed180a
MT
131 } else if (pgrp == p->p_pgrp)
132 return;
2dccc728 133
8fe87cbb 134 /*
2dccc728
MK
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.
8fe87cbb 138 */
2dccc728
MK
139 fixjobc(p, pgrp, 1);
140 fixjobc(p, p->p_pgrp, 0);
141
8fe87cbb
MT
142 /*
143 * unlink p from old process group
144 */
2dccc728 145 for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt)
8fe87cbb
MT
146 if (*pp == p) {
147 *pp = p->p_pgrpnxt;
148 goto done;
149 }
2e8f8cae 150 panic("pgmv: can't find p on old pgrp");
8fe87cbb 151done:
2dccc728
MK
152 /*
153 * delete old if empty
154 */
155 if (p->p_pgrp->pg_mem == 0)
156 pgdelete(p->p_pgrp);
8fe87cbb
MT
157 /*
158 * link into new one
159 */
2dccc728 160 p->p_pgrp = pgrp;
8fe87cbb
MT
161 p->p_pgrpnxt = pgrp->pg_mem;
162 pgrp->pg_mem = p;
8fe87cbb
MT
163}
164
165/*
166 * remove process from process group
167 */
168pgrm(p)
169 register struct proc *p;
170{
171 register struct proc **pp = &p->p_pgrp->pg_mem;
8fe87cbb
MT
172
173 for (; *pp; pp = &(*pp)->p_pgrpnxt)
174 if (*pp == p) {
175 *pp = p->p_pgrpnxt;
176 goto done;
177 }
2e8f8cae 178 panic("pgrm: can't find p in pgrp");
8fe87cbb
MT
179done:
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 */
188pgdelete(pgrp)
189 register struct pgrp *pgrp;
190{
191 register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)];
192
944e89dc
MT
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;
8fe87cbb
MT
196 for (; *pgp; pgp = &(*pgp)->pg_hforw)
197 if (*pgp == pgrp) {
198 *pgp = pgrp->pg_hforw;
199 goto done;
200 }
2e8f8cae 201 panic("pgdelete: can't find pgrp on hash chain");
8fe87cbb
MT
202done:
203 if (--pgrp->pg_session->s_count == 0)
204 FREE(pgrp->pg_session, M_SESSION);
205 FREE(pgrp, M_PGRP);
206}
207
69ed180a 208/*
2dccc728
MK
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.
69ed180a 217 */
2dccc728 218fixjobc(p, pgrp, entering)
69ed180a 219 register struct proc *p;
2dccc728
MK
220 register struct pgrp *pgrp;
221 int entering;
69ed180a 222{
2dccc728
MK
223 register struct pgrp *hispgrp;
224 register struct session *mysession = pgrp->pg_session;
69ed180a 225
2dccc728
MK
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 &&
69ed180a 231 hispgrp->pg_session == mysession)
2dccc728
MK
232 if (entering)
233 pgrp->pg_jobc++;
234 else if (--pgrp->pg_jobc == 0)
235 orphanpg(pgrp);
69ed180a 236
2dccc728
MK
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 &&
69ed180a
MT
244 hispgrp->pg_session == mysession &&
245 p->p_stat != SZOMB)
2dccc728 246 if (entering)
69ed180a 247 hispgrp->pg_jobc++;
2dccc728
MK
248 else if (--hispgrp->pg_jobc == 0)
249 orphanpg(hispgrp);
250}
69ed180a 251
2dccc728
MK
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 */
257static
258orphanpg(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);
69ed180a 268 }
2dccc728
MK
269 return;
270 }
271 }
69ed180a 272}
2dccc728 273
1d348849
MK
274/*
275 * init the process queues
276 */
277pqinit()
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}
8fe87cbb 300
c4ec2128 301#ifdef debug
8fe87cbb
MT
302/* DEBUG */
303pgrpdump()
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}
c4ec2128 325#endif /* debug */