convert VOP_UNLOCK and vrele into vput's; add proc parameter to union_dircache
[unix-history] / usr / src / sys / kern / kern_proc.c
CommitLineData
da7c5cc6 1/*
c34daa85
KB
2 * Copyright (c) 1982, 1986, 1989, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
da7c5cc6 4 *
dbf0c423 5 * %sccs.include.redist.c%
c4ec2128 6 *
29e5014e 7 * @(#)kern_proc.c 8.7 (Berkeley) %G%
da7c5cc6 8 */
961945a8 9
4f6e87b7
KB
10#include <sys/param.h>
11#include <sys/systm.h>
12#include <sys/map.h>
13#include <sys/kernel.h>
14#include <sys/proc.h>
15#include <sys/buf.h>
4f6e87b7
KB
16#include <sys/acct.h>
17#include <sys/wait.h>
18#include <sys/file.h>
19#include <ufs/ufs/quota.h>
20#include <sys/uio.h>
21#include <sys/malloc.h>
22#include <sys/mbuf.h>
23#include <sys/ioctl.h>
24#include <sys/tty.h>
a1bce776 25
0c06af94
KM
26/*
27 * Structure associated with user cacheing.
28 */
29struct uidinfo {
3ef0a118 30 LIST_ENTRY(uidinfo) ui_hash;
0c06af94
KM
31 uid_t ui_uid;
32 long ui_proccnt;
3ef0a118
KM
33};
34#define UIHASH(uid) (&uihashtbl[(uid) & uihash])
35LIST_HEAD(uihashhead, uidinfo) *uihashtbl;
36u_long uihash; /* size of hash table - 1 */
0c06af94
KM
37
38/*
3ef0a118 39 * Other process lists
0c06af94 40 */
3ef0a118
KM
41struct pidhashhead *pidhashtbl;
42u_long pidhash;
43struct pgrphashhead *pgrphashtbl;
44u_long pgrphash;
45struct proclist allproc;
46struct proclist zombproc;
47
48/*
49 * Initialize global process hashing structures.
50 */
5d263ebe 51void
3ef0a118 52procinit()
0c06af94
KM
53{
54
3ef0a118
KM
55 LIST_INIT(&allproc);
56 LIST_INIT(&zombproc);
57 pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash);
58 pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash);
0c06af94
KM
59 uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash);
60}
61
62/*
63 * Change the count associated with number of processes
64 * a given user is using.
65 */
66int
67chgproccnt(uid, diff)
68 uid_t uid;
69 int diff;
70{
3ef0a118
KM
71 register struct uidinfo *uip;
72 register struct uihashhead *uipp;
0c06af94 73
3ef0a118
KM
74 uipp = UIHASH(uid);
75 for (uip = uipp->lh_first; uip != 0; uip = uip->ui_hash.le_next)
0c06af94
KM
76 if (uip->ui_uid == uid)
77 break;
78 if (uip) {
79 uip->ui_proccnt += diff;
80 if (uip->ui_proccnt > 0)
81 return (uip->ui_proccnt);
82 if (uip->ui_proccnt < 0)
83 panic("chgproccnt: procs < 0");
3ef0a118 84 LIST_REMOVE(uip, ui_hash);
0c06af94
KM
85 FREE(uip, M_PROC);
86 return (0);
87 }
88 if (diff <= 0) {
89 if (diff == 0)
90 return(0);
91 panic("chgproccnt: lost user");
92 }
93 MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK);
3ef0a118 94 LIST_INSERT_HEAD(uipp, uip, ui_hash);
0c06af94
KM
95 uip->ui_uid = uid;
96 uip->ui_proccnt = diff;
97 return (diff);
98}
99
29dd101b 100/*
4147b3f6 101 * Is p an inferior of the current process?
29dd101b 102 */
4147b3f6 103inferior(p)
a2a2a0d6 104 register struct proc *p;
29dd101b 105{
2dccc728 106
bed84066
MK
107 for (; p != curproc; p = p->p_pptr)
108 if (p->p_pid == 0)
4147b3f6
BJ
109 return (0);
110 return (1);
29dd101b 111}
a2a2a0d6 112
b3ce9b0f
MK
113/*
114 * Locate a process by number
115 */
a2a2a0d6
BJ
116struct proc *
117pfind(pid)
cb84e0ab 118 register pid_t pid;
a2a2a0d6 119{
cb84e0ab 120 register struct proc *p;
a2a2a0d6 121
3ef0a118 122 for (p = PIDHASH(pid)->lh_first; p != 0; p = p->p_hash.le_next)
a2a2a0d6
BJ
123 if (p->p_pid == pid)
124 return (p);
cb84e0ab 125 return (NULL);
a2a2a0d6 126}
1d348849 127
8fe87cbb
MT
128/*
129 * Locate a process group by number
130 */
131struct pgrp *
132pgfind(pgid)
133 register pid_t pgid;
134{
cb84e0ab 135 register struct pgrp *pgrp;
8fe87cbb 136
3ef0a118
KM
137 for (pgrp = PGRPHASH(pgid)->lh_first; pgrp != 0;
138 pgrp = pgrp->pg_hash.le_next)
8fe87cbb 139 if (pgrp->pg_id == pgid)
b3ce9b0f 140 return (pgrp);
cb84e0ab 141 return (NULL);
8fe87cbb
MT
142}
143
144/*
145 * Move p to a new or existing process group (and session)
146 */
29e5014e 147int
bed84066 148enterpgrp(p, pgid, mksess)
8fe87cbb
MT
149 register struct proc *p;
150 pid_t pgid;
4d808bff 151 int mksess;
8fe87cbb
MT
152{
153 register struct pgrp *pgrp = pgfind(pgid);
8fe87cbb 154
944e89dc 155#ifdef DIAGNOSTIC
cb84e0ab 156 if (pgrp != NULL && mksess) /* firewalls */
bed84066 157 panic("enterpgrp: setsid into non-empty pgrp");
8fe87cbb 158 if (SESS_LEADER(p))
bed84066 159 panic("enterpgrp: session leader attempted setpgrp");
944e89dc 160#endif
2e8f8cae 161 if (pgrp == NULL) {
f9e28ab9
MT
162 pid_t savepid = p->p_pid;
163 struct proc *np;
8fe87cbb
MT
164 /*
165 * new process group
166 */
944e89dc 167#ifdef DIAGNOSTIC
8fe87cbb 168 if (p->p_pid != pgid)
bed84066 169 panic("enterpgrp: new pgrp and pid != pgid");
944e89dc 170#endif
8fe87cbb 171 MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
3ef0a118 172 M_WAITOK);
f9e28ab9
MT
173 if ((np = pfind(savepid)) == NULL || np != p)
174 return (ESRCH);
8fe87cbb
MT
175 if (mksess) {
176 register struct session *sess;
f3aac35d 177
8fe87cbb
MT
178 /*
179 * new session
180 */
181 MALLOC(sess, struct session *, sizeof(struct session),
3ef0a118 182 M_SESSION, M_WAITOK);
8fe87cbb
MT
183 sess->s_leader = p;
184 sess->s_count = 1;
944e89dc
MT
185 sess->s_ttyvp = NULL;
186 sess->s_ttyp = NULL;
f3aac35d
MK
187 bcopy(p->p_session->s_login, sess->s_login,
188 sizeof(sess->s_login));
cf5ef508 189 p->p_flag &= ~P_CONTROLT;
8fe87cbb 190 pgrp->pg_session = sess;
944e89dc 191#ifdef DIAGNOSTIC
bed84066
MK
192 if (p != curproc)
193 panic("enterpgrp: mksession and p != curproc");
944e89dc 194#endif
8fe87cbb
MT
195 } else {
196 pgrp->pg_session = p->p_session;
197 pgrp->pg_session->s_count++;
198 }
199 pgrp->pg_id = pgid;
3ef0a118
KM
200 LIST_INIT(&pgrp->pg_members);
201 LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash);
8fe87cbb 202 pgrp->pg_jobc = 0;
69ed180a 203 } else if (pgrp == p->p_pgrp)
f9e28ab9 204 return (0);
2dccc728 205
8fe87cbb 206 /*
2dccc728
MK
207 * Adjust eligibility of affected pgrps to participate in job control.
208 * Increment eligibility counts before decrementing, otherwise we
209 * could reach 0 spuriously during the first call.
8fe87cbb 210 */
2dccc728
MK
211 fixjobc(p, pgrp, 1);
212 fixjobc(p, p->p_pgrp, 0);
213
3ef0a118
KM
214 LIST_REMOVE(p, p_pglist);
215 if (p->p_pgrp->pg_members.lh_first == 0)
2dccc728 216 pgdelete(p->p_pgrp);
2dccc728 217 p->p_pgrp = pgrp;
3ef0a118 218 LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist);
f9e28ab9 219 return (0);
8fe87cbb
MT
220}
221
222/*
223 * remove process from process group
224 */
29e5014e 225int
bed84066 226leavepgrp(p)
8fe87cbb
MT
227 register struct proc *p;
228{
8fe87cbb 229
3ef0a118
KM
230 LIST_REMOVE(p, p_pglist);
231 if (p->p_pgrp->pg_members.lh_first == 0)
8fe87cbb
MT
232 pgdelete(p->p_pgrp);
233 p->p_pgrp = 0;
f9e28ab9 234 return (0);
8fe87cbb
MT
235}
236
237/*
238 * delete a process group
239 */
5d263ebe 240void
8fe87cbb
MT
241pgdelete(pgrp)
242 register struct pgrp *pgrp;
243{
8fe87cbb 244
944e89dc
MT
245 if (pgrp->pg_session->s_ttyp != NULL &&
246 pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
247 pgrp->pg_session->s_ttyp->t_pgrp = NULL;
3ef0a118 248 LIST_REMOVE(pgrp, pg_hash);
8fe87cbb
MT
249 if (--pgrp->pg_session->s_count == 0)
250 FREE(pgrp->pg_session, M_SESSION);
251 FREE(pgrp, M_PGRP);
252}
253
4d808bff 254static void orphanpg();
3fb7685a 255
69ed180a 256/*
2dccc728
MK
257 * Adjust pgrp jobc counters when specified process changes process group.
258 * We count the number of processes in each process group that "qualify"
259 * the group for terminal job control (those with a parent in a different
260 * process group of the same session). If that count reaches zero, the
261 * process group becomes orphaned. Check both the specified process'
262 * process group and that of its children.
263 * entering == 0 => p is leaving specified group.
264 * entering == 1 => p is entering specified group.
69ed180a 265 */
5d263ebe 266void
2dccc728 267fixjobc(p, pgrp, entering)
69ed180a 268 register struct proc *p;
2dccc728
MK
269 register struct pgrp *pgrp;
270 int entering;
69ed180a 271{
2dccc728
MK
272 register struct pgrp *hispgrp;
273 register struct session *mysession = pgrp->pg_session;
69ed180a 274
2dccc728
MK
275 /*
276 * Check p's parent to see whether p qualifies its own process
277 * group; if so, adjust count for p's process group.
278 */
279 if ((hispgrp = p->p_pptr->p_pgrp) != pgrp &&
69ed180a 280 hispgrp->pg_session == mysession)
2dccc728
MK
281 if (entering)
282 pgrp->pg_jobc++;
283 else if (--pgrp->pg_jobc == 0)
284 orphanpg(pgrp);
69ed180a 285
2dccc728
MK
286 /*
287 * Check this process' children to see whether they qualify
288 * their process groups; if so, adjust counts for children's
289 * process groups.
290 */
3ef0a118 291 for (p = p->p_children.lh_first; p != 0; p = p->p_sibling.le_next)
2dccc728 292 if ((hispgrp = p->p_pgrp) != pgrp &&
69ed180a
MT
293 hispgrp->pg_session == mysession &&
294 p->p_stat != SZOMB)
2dccc728 295 if (entering)
69ed180a 296 hispgrp->pg_jobc++;
2dccc728
MK
297 else if (--hispgrp->pg_jobc == 0)
298 orphanpg(hispgrp);
299}
69ed180a 300
2dccc728
MK
301/*
302 * A process group has become orphaned;
303 * if there are any stopped processes in the group,
304 * hang-up all process in that group.
305 */
4d808bff 306static void
2dccc728
MK
307orphanpg(pg)
308 struct pgrp *pg;
309{
310 register struct proc *p;
311
3ef0a118 312 for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) {
2dccc728 313 if (p->p_stat == SSTOP) {
3ef0a118
KM
314 for (p = pg->pg_members.lh_first; p != 0;
315 p = p->p_pglist.le_next) {
2dccc728
MK
316 psignal(p, SIGHUP);
317 psignal(p, SIGCONT);
69ed180a 318 }
2dccc728
MK
319 return;
320 }
321 }
69ed180a 322}
2dccc728 323
3ef0a118 324#ifdef DEBUG
8fe87cbb
MT
325pgrpdump()
326{
327 register struct pgrp *pgrp;
328 register struct proc *p;
329 register i;
330
3ef0a118
KM
331 for (i = 0; i <= pgrphash; i++) {
332 if (pgrp = pgrphashtbl[i].lh_first) {
333 printf("\tindx %d\n", i);
334 for (; pgrp != 0; pgrp = pgrp->pg_hash.le_next) {
335 printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n",
336 pgrp, pgrp->pg_id, pgrp->pg_session,
337 pgrp->pg_session->s_count,
338 pgrp->pg_members.lh_first);
339 for (p = pgrp->pg_members.lh_first; p != 0;
340 p = p->p_pglist.le_next) {
341 printf("\t\tpid %d addr %x pgrp %x\n",
342 p->p_pid, p, p->p_pgrp);
343 }
344 }
8fe87cbb
MT
345 }
346 }
347}
3ef0a118 348#endif /* DEBUG */