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 | * |
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 | 37 | inferior(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 |
50 | struct proc * |
51 | pfind(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 | */ | |
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) | |
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 | */ | |
80 | pgmv(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 | 151 | done: |
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 | */ | |
168 | pgrm(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 |
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 | ||
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 |
202 | done: |
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 | 218 | fixjobc(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 | */ | |
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); | |
69ed180a | 268 | } |
2dccc728 MK |
269 | return; |
270 | } | |
271 | } | |
69ed180a | 272 | } |
2dccc728 | 273 | |
1d348849 MK |
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 | } | |
8fe87cbb | 300 | |
c4ec2128 | 301 | #ifdef debug |
8fe87cbb MT |
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 | } | |
c4ec2128 | 325 | #endif /* debug */ |