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 | * |
c4ec2128 KM |
5 | * Redistribution and use in source and binary forms are permitted |
6 | * provided that the above copyright notice and this paragraph are | |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
16 | * | |
b3ce9b0f | 17 | * @(#)kern_proc.c 7.9 (Berkeley) %G% |
da7c5cc6 | 18 | */ |
961945a8 | 19 | |
94368568 JB |
20 | #include "param.h" |
21 | #include "systm.h" | |
22 | #include "map.h" | |
94368568 JB |
23 | #include "user.h" |
24 | #include "kernel.h" | |
25 | #include "proc.h" | |
26 | #include "buf.h" | |
94368568 JB |
27 | #include "seg.h" |
28 | #include "acct.h" | |
29 | #include "wait.h" | |
30 | #include "vm.h" | |
31 | #include "text.h" | |
32 | #include "file.h" | |
c4ec2128 | 33 | #include "../ufs/quota.h" |
94368568 | 34 | #include "uio.h" |
8fe87cbb | 35 | #include "malloc.h" |
94368568 | 36 | #include "mbuf.h" |
5b6ff773 | 37 | #include "ioctl.h" |
8fe87cbb | 38 | #include "tty.h" |
a1bce776 | 39 | |
d301d150 KM |
40 | #include "machine/reg.h" |
41 | #include "machine/pte.h" | |
42 | #include "machine/psl.h" | |
43 | ||
bdf8c113 | 44 | /* |
f6ab5a0c | 45 | * Clear any pending stops for top and all descendents. |
bdf8c113 | 46 | */ |
f6ab5a0c | 47 | spgrp(top) |
bdf8c113 | 48 | struct proc *top; |
4147b3f6 | 49 | { |
bdf8c113 | 50 | register struct proc *p; |
4147b3f6 BJ |
51 | int f = 0; |
52 | ||
bdf8c113 MK |
53 | p = top; |
54 | for (;;) { | |
f6ab5a0c | 55 | p->p_sig &= |
bdf8c113 | 56 | ~(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU)); |
4147b3f6 BJ |
57 | f++; |
58 | /* | |
bdf8c113 MK |
59 | * If this process has children, descend to them next, |
60 | * otherwise do any siblings, and if done with this level, | |
61 | * follow back up the tree (but not past top). | |
4147b3f6 | 62 | */ |
bdf8c113 MK |
63 | if (p->p_cptr) |
64 | p = p->p_cptr; | |
65 | else if (p == top) | |
66 | return (f); | |
67 | else if (p->p_osptr) | |
68 | p = p->p_osptr; | |
69 | else for (;;) { | |
70 | p = p->p_pptr; | |
71 | if (p == top) | |
72 | return (f); | |
bdf8c113 MK |
73 | if (p->p_osptr) { |
74 | p = p->p_osptr; | |
75 | break; | |
76 | } | |
77 | } | |
4147b3f6 | 78 | } |
4147b3f6 BJ |
79 | } |
80 | ||
29dd101b | 81 | /* |
4147b3f6 | 82 | * Is p an inferior of the current process? |
29dd101b | 83 | */ |
4147b3f6 | 84 | inferior(p) |
a2a2a0d6 | 85 | register struct proc *p; |
29dd101b | 86 | { |
4147b3f6 BJ |
87 | for (; p != u.u_procp; p = p->p_pptr) |
88 | if (p->p_ppid == 0) | |
89 | return (0); | |
90 | return (1); | |
29dd101b | 91 | } |
a2a2a0d6 | 92 | |
b3ce9b0f MK |
93 | /* |
94 | * Locate a process by number | |
95 | */ | |
a2a2a0d6 BJ |
96 | struct proc * |
97 | pfind(pid) | |
8fe87cbb | 98 | register pid; |
a2a2a0d6 | 99 | { |
b3ce9b0f | 100 | register struct proc *p = pidhash[PIDHASH(pid)]; |
a2a2a0d6 | 101 | |
b3ce9b0f | 102 | for (; p; p = p->p_hash) |
a2a2a0d6 BJ |
103 | if (p->p_pid == pid) |
104 | return (p); | |
105 | return ((struct proc *)0); | |
106 | } | |
1d348849 | 107 | |
8fe87cbb MT |
108 | /* |
109 | * Locate a process group by number | |
110 | */ | |
111 | struct pgrp * | |
112 | pgfind(pgid) | |
113 | register pid_t pgid; | |
114 | { | |
115 | register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)]; | |
116 | ||
117 | for (; pgrp; pgrp = pgrp->pg_hforw) | |
118 | if (pgrp->pg_id == pgid) | |
b3ce9b0f | 119 | return (pgrp); |
8fe87cbb MT |
120 | return ((struct pgrp *)0); |
121 | } | |
122 | ||
123 | /* | |
124 | * Move p to a new or existing process group (and session) | |
125 | */ | |
126 | pgmv(p, pgid, mksess) | |
127 | register struct proc *p; | |
128 | pid_t pgid; | |
129 | { | |
130 | register struct pgrp *pgrp = pgfind(pgid); | |
131 | register struct proc **pp = &p->p_pgrp->pg_mem; | |
132 | register struct proc *cp; | |
2e8f8cae | 133 | struct pgrp *opgrp; |
8fe87cbb MT |
134 | register n; |
135 | ||
944e89dc | 136 | #ifdef DIAGNOSTIC |
8fe87cbb | 137 | if (pgrp && mksess) /* firewalls */ |
2e8f8cae | 138 | panic("pgmv: setsid into non-empty pgrp"); |
8fe87cbb | 139 | if (SESS_LEADER(p)) |
2e8f8cae | 140 | panic("pgmv: session leader attempted setpgrp"); |
944e89dc | 141 | #endif |
2e8f8cae | 142 | if (pgrp == NULL) { |
8fe87cbb MT |
143 | /* |
144 | * new process group | |
145 | */ | |
944e89dc | 146 | #ifdef DIAGNOSTIC |
8fe87cbb | 147 | if (p->p_pid != pgid) |
2e8f8cae | 148 | panic("pgmv: new pgrp and pid != pgid"); |
944e89dc | 149 | #endif |
8fe87cbb MT |
150 | MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, |
151 | M_WAITOK); | |
152 | if (mksess) { | |
153 | register struct session *sess; | |
154 | /* | |
155 | * new session | |
156 | */ | |
157 | MALLOC(sess, struct session *, sizeof(struct session), | |
158 | M_SESSION, M_WAITOK); | |
159 | sess->s_leader = p; | |
160 | sess->s_count = 1; | |
944e89dc MT |
161 | sess->s_ttyvp = NULL; |
162 | sess->s_ttyp = NULL; | |
163 | p->p_flag &= ~SCTTY; | |
8fe87cbb | 164 | pgrp->pg_session = sess; |
944e89dc | 165 | #ifdef DIAGNOSTIC |
8fe87cbb MT |
166 | if (p != u.u_procp) |
167 | panic("pgmv: mksession and p != u.u_procp"); | |
944e89dc | 168 | #endif |
8fe87cbb MT |
169 | } else { |
170 | pgrp->pg_session = p->p_session; | |
171 | pgrp->pg_session->s_count++; | |
172 | } | |
173 | pgrp->pg_id = pgid; | |
174 | pgrp->pg_hforw = pgrphash[n=PIDHASH(pgid)]; | |
175 | pgrphash[n] = pgrp; | |
176 | pgrp->pg_jobc = 0; | |
944e89dc | 177 | pgrp->pg_mem = NULL; |
8fe87cbb MT |
178 | } |
179 | /* | |
180 | * adjust eligibility of affected pgrps to participate in job control | |
181 | */ | |
182 | if (PGRP_JOBC(p)) | |
183 | p->p_pgrp->pg_jobc--; | |
184 | for (cp = p->p_cptr; cp; cp = cp->p_osptr) | |
185 | if (PGRP_JOBC(cp)) | |
186 | cp->p_pgrp->pg_jobc--; | |
187 | /* | |
188 | * unlink p from old process group | |
189 | */ | |
190 | for (; *pp; pp = &(*pp)->p_pgrpnxt) | |
191 | if (*pp == p) { | |
192 | *pp = p->p_pgrpnxt; | |
193 | goto done; | |
194 | } | |
2e8f8cae | 195 | panic("pgmv: can't find p on old pgrp"); |
8fe87cbb MT |
196 | done: |
197 | /* | |
198 | * link into new one | |
199 | */ | |
200 | p->p_pgrpnxt = pgrp->pg_mem; | |
201 | pgrp->pg_mem = p; | |
2e8f8cae | 202 | opgrp = p->p_pgrp; |
8fe87cbb MT |
203 | p->p_pgrp = pgrp; |
204 | /* | |
205 | * adjust eligibility of affected pgrps to participate in job control | |
206 | */ | |
207 | if (PGRP_JOBC(p)) | |
208 | p->p_pgrp->pg_jobc++; | |
209 | for (cp = p->p_cptr; cp; cp = cp->p_osptr) | |
210 | if (PGRP_JOBC(cp)) | |
211 | cp->p_pgrp->pg_jobc++; | |
212 | /* | |
213 | * old pgrp empty? | |
214 | */ | |
2e8f8cae MT |
215 | if (!opgrp->pg_mem) |
216 | pgdelete(opgrp); | |
8fe87cbb MT |
217 | } |
218 | ||
219 | /* | |
220 | * remove process from process group | |
221 | */ | |
222 | pgrm(p) | |
223 | register struct proc *p; | |
224 | { | |
225 | register struct proc **pp = &p->p_pgrp->pg_mem; | |
8fe87cbb MT |
226 | |
227 | for (; *pp; pp = &(*pp)->p_pgrpnxt) | |
228 | if (*pp == p) { | |
229 | *pp = p->p_pgrpnxt; | |
230 | goto done; | |
231 | } | |
2e8f8cae | 232 | panic("pgrm: can't find p in pgrp"); |
8fe87cbb MT |
233 | done: |
234 | if (!p->p_pgrp->pg_mem) | |
235 | pgdelete(p->p_pgrp); | |
236 | p->p_pgrp = 0; | |
237 | } | |
238 | ||
239 | /* | |
240 | * delete a process group | |
241 | */ | |
242 | pgdelete(pgrp) | |
243 | register struct pgrp *pgrp; | |
244 | { | |
245 | register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; | |
246 | ||
944e89dc MT |
247 | if (pgrp->pg_session->s_ttyp != NULL && |
248 | pgrp->pg_session->s_ttyp->t_pgrp == pgrp) | |
249 | pgrp->pg_session->s_ttyp->t_pgrp = NULL; | |
8fe87cbb MT |
250 | for (; *pgp; pgp = &(*pgp)->pg_hforw) |
251 | if (*pgp == pgrp) { | |
252 | *pgp = pgrp->pg_hforw; | |
253 | goto done; | |
254 | } | |
2e8f8cae | 255 | panic("pgdelete: can't find pgrp on hash chain"); |
8fe87cbb MT |
256 | done: |
257 | if (--pgrp->pg_session->s_count == 0) | |
258 | FREE(pgrp->pg_session, M_SESSION); | |
259 | FREE(pgrp, M_PGRP); | |
260 | } | |
261 | ||
1d348849 MK |
262 | /* |
263 | * init the process queues | |
264 | */ | |
265 | pqinit() | |
266 | { | |
267 | register struct proc *p; | |
268 | ||
269 | /* | |
270 | * most procs are initially on freequeue | |
271 | * nb: we place them there in their "natural" order. | |
272 | */ | |
273 | ||
274 | freeproc = NULL; | |
275 | for (p = procNPROC; --p > proc; freeproc = p) | |
276 | p->p_nxt = freeproc; | |
277 | ||
278 | /* | |
279 | * but proc[0] is special ... | |
280 | */ | |
281 | ||
282 | allproc = p; | |
283 | p->p_nxt = NULL; | |
284 | p->p_prev = &allproc; | |
285 | ||
286 | zombproc = NULL; | |
287 | } | |
8fe87cbb | 288 | |
c4ec2128 | 289 | #ifdef debug |
8fe87cbb MT |
290 | /* DEBUG */ |
291 | pgrpdump() | |
292 | { | |
293 | register struct pgrp *pgrp; | |
294 | register struct proc *p; | |
295 | register i; | |
296 | ||
297 | for (i=0; i<PIDHSZ; i++) { | |
298 | if (pgrphash[i]) { | |
299 | printf("\tindx %d\n", i); | |
300 | for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) { | |
301 | printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", | |
302 | pgrp, pgrp->pg_id, pgrp->pg_session, | |
303 | pgrp->pg_session->s_count, pgrp->pg_mem); | |
304 | for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { | |
305 | printf("\t\tpid %d addr %x pgrp %x\n", | |
306 | p->p_pid, p, p->p_pgrp); | |
307 | } | |
308 | } | |
309 | ||
310 | } | |
311 | } | |
312 | } | |
c4ec2128 | 313 | #endif /* debug */ |