Commit | Line | Data |
---|---|---|
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 | 34 | inferior(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 |
47 | struct proc * |
48 | pfind(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 | */ | |
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) | |
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 | */ | |
77 | pgmv(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 | 148 | done: |
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 | */ | |
165 | pgrm(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 |
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 | ||
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 |
199 | done: |
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 | 215 | fixjobc(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 | */ | |
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); | |
69ed180a | 265 | } |
2dccc728 MK |
266 | return; |
267 | } | |
268 | } | |
69ed180a | 269 | } |
2dccc728 | 270 | |
1d348849 MK |
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 | } | |
8fe87cbb | 297 | |
c4ec2128 | 298 | #ifdef debug |
8fe87cbb MT |
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 | } | |
c4ec2128 | 322 | #endif /* debug */ |