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 | * | |
17 | * @(#)kern_proc.c 7.6 (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" |
8fe87cbb | 37 | #include "tty.h" |
a1bce776 | 38 | |
d301d150 KM |
39 | #include "machine/reg.h" |
40 | #include "machine/pte.h" | |
41 | #include "machine/psl.h" | |
42 | ||
bdf8c113 | 43 | /* |
f6ab5a0c | 44 | * Clear any pending stops for top and all descendents. |
bdf8c113 | 45 | */ |
f6ab5a0c | 46 | spgrp(top) |
bdf8c113 | 47 | struct proc *top; |
4147b3f6 | 48 | { |
bdf8c113 | 49 | register struct proc *p; |
4147b3f6 BJ |
50 | int f = 0; |
51 | ||
bdf8c113 MK |
52 | p = top; |
53 | for (;;) { | |
f6ab5a0c | 54 | p->p_sig &= |
bdf8c113 | 55 | ~(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU)); |
4147b3f6 BJ |
56 | f++; |
57 | /* | |
bdf8c113 MK |
58 | * If this process has children, descend to them next, |
59 | * otherwise do any siblings, and if done with this level, | |
60 | * follow back up the tree (but not past top). | |
4147b3f6 | 61 | */ |
bdf8c113 MK |
62 | if (p->p_cptr) |
63 | p = p->p_cptr; | |
64 | else if (p == top) | |
65 | return (f); | |
66 | else if (p->p_osptr) | |
67 | p = p->p_osptr; | |
68 | else for (;;) { | |
69 | p = p->p_pptr; | |
70 | if (p == top) | |
71 | return (f); | |
bdf8c113 MK |
72 | if (p->p_osptr) { |
73 | p = p->p_osptr; | |
74 | break; | |
75 | } | |
76 | } | |
4147b3f6 | 77 | } |
4147b3f6 BJ |
78 | } |
79 | ||
29dd101b | 80 | /* |
4147b3f6 | 81 | * Is p an inferior of the current process? |
29dd101b | 82 | */ |
4147b3f6 | 83 | inferior(p) |
a2a2a0d6 | 84 | register struct proc *p; |
29dd101b | 85 | { |
4147b3f6 BJ |
86 | for (; p != u.u_procp; p = p->p_pptr) |
87 | if (p->p_ppid == 0) | |
88 | return (0); | |
89 | return (1); | |
29dd101b | 90 | } |
a2a2a0d6 BJ |
91 | |
92 | struct proc * | |
93 | pfind(pid) | |
8fe87cbb | 94 | register pid; |
a2a2a0d6 BJ |
95 | { |
96 | register struct proc *p; | |
97 | ||
8fe87cbb MT |
98 | for (p = &proc[pidhash[PIDHASH(pid)]] ; |
99 | p != &proc[0]; p = &proc[p->p_idhash]) | |
a2a2a0d6 BJ |
100 | if (p->p_pid == pid) |
101 | return (p); | |
102 | return ((struct proc *)0); | |
103 | } | |
1d348849 | 104 | |
8fe87cbb MT |
105 | /* |
106 | * Locate a process group by number | |
107 | */ | |
108 | struct pgrp * | |
109 | pgfind(pgid) | |
110 | register pid_t pgid; | |
111 | { | |
112 | register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)]; | |
113 | ||
114 | for (; pgrp; pgrp = pgrp->pg_hforw) | |
115 | if (pgrp->pg_id == pgid) | |
116 | return(pgrp); | |
117 | return ((struct pgrp *)0); | |
118 | } | |
119 | ||
120 | /* | |
121 | * Move p to a new or existing process group (and session) | |
122 | */ | |
123 | pgmv(p, pgid, mksess) | |
124 | register struct proc *p; | |
125 | pid_t pgid; | |
126 | { | |
127 | register struct pgrp *pgrp = pgfind(pgid); | |
128 | register struct proc **pp = &p->p_pgrp->pg_mem; | |
129 | register struct proc *cp; | |
2e8f8cae | 130 | struct pgrp *opgrp; |
8fe87cbb MT |
131 | register n; |
132 | ||
133 | if (pgrp && mksess) /* firewalls */ | |
2e8f8cae | 134 | panic("pgmv: setsid into non-empty pgrp"); |
8fe87cbb | 135 | if (SESS_LEADER(p)) |
2e8f8cae MT |
136 | panic("pgmv: session leader attempted setpgrp"); |
137 | if (pgrp == NULL) { | |
8fe87cbb MT |
138 | /* |
139 | * new process group | |
140 | */ | |
141 | if (p->p_pid != pgid) | |
2e8f8cae | 142 | panic("pgmv: new pgrp and pid != pgid"); |
8fe87cbb MT |
143 | MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, |
144 | M_WAITOK); | |
145 | if (mksess) { | |
146 | register struct session *sess; | |
147 | /* | |
148 | * new session | |
149 | */ | |
150 | MALLOC(sess, struct session *, sizeof(struct session), | |
151 | M_SESSION, M_WAITOK); | |
152 | sess->s_leader = p; | |
153 | sess->s_count = 1; | |
154 | pgrp->pg_session = sess; | |
155 | if (p != u.u_procp) | |
156 | panic("pgmv: mksession and p != u.u_procp"); | |
2e8f8cae | 157 | u.u_ttyp = NULL; |
8fe87cbb MT |
158 | u.u_ttyd = 0; |
159 | } else { | |
160 | pgrp->pg_session = p->p_session; | |
161 | pgrp->pg_session->s_count++; | |
162 | } | |
163 | pgrp->pg_id = pgid; | |
164 | pgrp->pg_hforw = pgrphash[n=PIDHASH(pgid)]; | |
165 | pgrphash[n] = pgrp; | |
166 | pgrp->pg_jobc = 0; | |
167 | pgrp->pg_mem = 0; | |
168 | } | |
169 | /* | |
170 | * adjust eligibility of affected pgrps to participate in job control | |
171 | */ | |
172 | if (PGRP_JOBC(p)) | |
173 | p->p_pgrp->pg_jobc--; | |
174 | for (cp = p->p_cptr; cp; cp = cp->p_osptr) | |
175 | if (PGRP_JOBC(cp)) | |
176 | cp->p_pgrp->pg_jobc--; | |
177 | /* | |
178 | * unlink p from old process group | |
179 | */ | |
180 | for (; *pp; pp = &(*pp)->p_pgrpnxt) | |
181 | if (*pp == p) { | |
182 | *pp = p->p_pgrpnxt; | |
183 | goto done; | |
184 | } | |
2e8f8cae | 185 | panic("pgmv: can't find p on old pgrp"); |
8fe87cbb MT |
186 | done: |
187 | /* | |
188 | * link into new one | |
189 | */ | |
190 | p->p_pgrpnxt = pgrp->pg_mem; | |
191 | pgrp->pg_mem = p; | |
2e8f8cae | 192 | opgrp = p->p_pgrp; |
8fe87cbb MT |
193 | p->p_pgrp = pgrp; |
194 | /* | |
195 | * adjust eligibility of affected pgrps to participate in job control | |
196 | */ | |
197 | if (PGRP_JOBC(p)) | |
198 | p->p_pgrp->pg_jobc++; | |
199 | for (cp = p->p_cptr; cp; cp = cp->p_osptr) | |
200 | if (PGRP_JOBC(cp)) | |
201 | cp->p_pgrp->pg_jobc++; | |
202 | /* | |
203 | * old pgrp empty? | |
204 | */ | |
2e8f8cae MT |
205 | if (!opgrp->pg_mem) |
206 | pgdelete(opgrp); | |
8fe87cbb MT |
207 | } |
208 | ||
209 | /* | |
210 | * remove process from process group | |
211 | */ | |
212 | pgrm(p) | |
213 | register struct proc *p; | |
214 | { | |
215 | register struct proc **pp = &p->p_pgrp->pg_mem; | |
8fe87cbb MT |
216 | |
217 | for (; *pp; pp = &(*pp)->p_pgrpnxt) | |
218 | if (*pp == p) { | |
219 | *pp = p->p_pgrpnxt; | |
220 | goto done; | |
221 | } | |
2e8f8cae | 222 | panic("pgrm: can't find p in pgrp"); |
8fe87cbb MT |
223 | done: |
224 | if (!p->p_pgrp->pg_mem) | |
225 | pgdelete(p->p_pgrp); | |
226 | p->p_pgrp = 0; | |
227 | } | |
228 | ||
229 | /* | |
230 | * delete a process group | |
231 | */ | |
232 | pgdelete(pgrp) | |
233 | register struct pgrp *pgrp; | |
234 | { | |
235 | register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; | |
236 | ||
237 | for (; *pgp; pgp = &(*pgp)->pg_hforw) | |
238 | if (*pgp == pgrp) { | |
239 | *pgp = pgrp->pg_hforw; | |
240 | goto done; | |
241 | } | |
2e8f8cae | 242 | panic("pgdelete: can't find pgrp on hash chain"); |
8fe87cbb MT |
243 | done: |
244 | if (--pgrp->pg_session->s_count == 0) | |
245 | FREE(pgrp->pg_session, M_SESSION); | |
246 | FREE(pgrp, M_PGRP); | |
247 | } | |
248 | ||
1d348849 MK |
249 | /* |
250 | * init the process queues | |
251 | */ | |
252 | pqinit() | |
253 | { | |
254 | register struct proc *p; | |
255 | ||
256 | /* | |
257 | * most procs are initially on freequeue | |
258 | * nb: we place them there in their "natural" order. | |
259 | */ | |
260 | ||
261 | freeproc = NULL; | |
262 | for (p = procNPROC; --p > proc; freeproc = p) | |
263 | p->p_nxt = freeproc; | |
264 | ||
265 | /* | |
266 | * but proc[0] is special ... | |
267 | */ | |
268 | ||
269 | allproc = p; | |
270 | p->p_nxt = NULL; | |
271 | p->p_prev = &allproc; | |
272 | ||
273 | zombproc = NULL; | |
274 | } | |
8fe87cbb | 275 | |
c4ec2128 | 276 | #ifdef debug |
8fe87cbb MT |
277 | /* DEBUG */ |
278 | pgrpdump() | |
279 | { | |
280 | register struct pgrp *pgrp; | |
281 | register struct proc *p; | |
282 | register i; | |
283 | ||
284 | for (i=0; i<PIDHSZ; i++) { | |
285 | if (pgrphash[i]) { | |
286 | printf("\tindx %d\n", i); | |
287 | for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) { | |
288 | printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", | |
289 | pgrp, pgrp->pg_id, pgrp->pg_session, | |
290 | pgrp->pg_session->s_count, pgrp->pg_mem); | |
291 | for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { | |
292 | printf("\t\tpid %d addr %x pgrp %x\n", | |
293 | p->p_pid, p, p->p_pgrp); | |
294 | } | |
295 | } | |
296 | ||
297 | } | |
298 | } | |
299 | } | |
c4ec2128 | 300 | #endif /* debug */ |