]>
git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_proc.c
2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
27 * Copyright (c) 1982, 1986, 1989, 1991, 1993
28 * The Regents of the University of California. All rights reserved.
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the University of
41 * California, Berkeley and its contributors.
42 * 4. Neither the name of the University nor the names of its contributors
43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * @(#)kern_proc.c 8.4 (Berkeley) 1/4/94
61 * 04-Aug-97 Umesh Vaishampayan (umeshv@apple.com)
62 * Added current_proc_EXTERNAL() function for the use of kernel
65 * 05-Jun-95 Mac Gillon (mgillon) at NeXT
66 * New version based on 3.3NS and 4.4
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/kernel.h>
78 #include <ufs/ufs/quota.h>
80 #include <sys/malloc.h>
82 #include <sys/ioctl.h>
84 #include <sys/signalvar.h>
87 * Structure associated with user cacheing.
90 LIST_ENTRY(uidinfo
) ui_hash
;
94 #define UIHASH(uid) (&uihashtbl[(uid) & uihash])
95 LIST_HEAD(uihashhead
, uidinfo
) *uihashtbl
;
96 u_long uihash
; /* size of hash table - 1 */
101 struct pidhashhead
*pidhashtbl
;
103 struct pgrphashhead
*pgrphashtbl
;
105 struct proclist allproc
;
106 struct proclist zombproc
;
109 * Initialize global process hashing structures.
116 LIST_INIT(&zombproc
);
117 pidhashtbl
= hashinit(maxproc
/ 4, M_PROC
, &pidhash
);
118 pgrphashtbl
= hashinit(maxproc
/ 4, M_PROC
, &pgrphash
);
119 uihashtbl
= hashinit(maxproc
/ 16, M_PROC
, &uihash
);
123 * Change the count associated with number of processes
124 * a given user is using.
127 chgproccnt(uid
, diff
)
131 register struct uidinfo
*uip
;
132 register struct uihashhead
*uipp
;
135 for (uip
= uipp
->lh_first
; uip
!= 0; uip
= uip
->ui_hash
.le_next
)
136 if (uip
->ui_uid
== uid
)
139 uip
->ui_proccnt
+= diff
;
140 if (uip
->ui_proccnt
> 0)
141 return (uip
->ui_proccnt
);
142 if (uip
->ui_proccnt
< 0)
143 panic("chgproccnt: procs < 0");
144 LIST_REMOVE(uip
, ui_hash
);
145 FREE_ZONE(uip
, sizeof *uip
, M_PROC
);
151 panic("chgproccnt: lost user");
153 MALLOC_ZONE(uip
, struct uidinfo
*, sizeof(*uip
), M_PROC
, M_WAITOK
);
154 LIST_INSERT_HEAD(uipp
, uip
, ui_hash
);
156 uip
->ui_proccnt
= diff
;
161 * Is p an inferior of the current process?
165 register struct proc
*p
;
168 for (; p
!= current_proc(); p
= p
->p_pptr
)
174 * Is p an inferior of t ?
178 register struct proc
*p
;
179 register struct proc
*t
;
182 /* if p==t they are not inferior */
185 for (; p
!= t
; p
= p
->p_pptr
)
192 * Locate a process by number
198 register struct proc
*p
;
203 for (p
= PIDHASH(pid
)->lh_first
; p
!= 0; p
= p
->p_hash
.le_next
)
210 * Locate a zombie by PID
212 __private_extern__
struct proc
*
216 register struct proc
*p
;
218 for (p
= zombproc
.lh_first
; p
!= 0; p
= p
->p_list
.le_next
)
225 * Locate a process group by number
231 register struct pgrp
*pgrp
;
233 for (pgrp
= PGRPHASH(pgid
)->lh_first
; pgrp
!= 0; pgrp
= pgrp
->pg_hash
.le_next
)
234 if (pgrp
->pg_id
== pgid
)
241 * Move p to a new or existing process group (and session)
244 enterpgrp(p
, pgid
, mksess
)
245 register struct proc
*p
;
249 register struct pgrp
*pgrp
= pgfind(pgid
);
252 if (pgrp
!= NULL
&& mksess
) /* firewalls */
253 panic("enterpgrp: setsid into non-empty pgrp");
255 panic("enterpgrp: session leader attempted setpgrp");
258 pid_t savepid
= p
->p_pid
;
264 if (p
->p_pid
!= pgid
)
265 panic("enterpgrp: new pgrp and pid != pgid");
267 MALLOC_ZONE(pgrp
, struct pgrp
*, sizeof(struct pgrp
), M_PGRP
,
269 if ((np
= pfind(savepid
)) == NULL
|| np
!= p
) {
270 FREE_ZONE(pgrp
, sizeof(struct pgrp
), M_PGRP
);
274 register struct session
*sess
;
279 MALLOC_ZONE(sess
, struct session
*,
280 sizeof(struct session
), M_SESSION
, M_WAITOK
);
282 sess
->s_sid
= p
->p_pid
;
284 sess
->s_ttyvp
= NULL
;
286 bcopy(p
->p_session
->s_login
, sess
->s_login
,
287 sizeof(sess
->s_login
));
288 p
->p_flag
&= ~P_CONTROLT
;
289 pgrp
->pg_session
= sess
;
291 if (p
!= current_proc())
292 panic("enterpgrp: mksession and p != curproc");
295 pgrp
->pg_session
= p
->p_session
;
296 pgrp
->pg_session
->s_count
++;
299 LIST_INIT(&pgrp
->pg_members
);
300 LIST_INSERT_HEAD(PGRPHASH(pgid
), pgrp
, pg_hash
);
302 } else if (pgrp
== p
->p_pgrp
)
306 * Adjust eligibility of affected pgrps to participate in job control.
307 * Increment eligibility counts before decrementing, otherwise we
308 * could reach 0 spuriously during the first call.
311 fixjobc(p
, p
->p_pgrp
, 0);
313 LIST_REMOVE(p
, p_pglist
);
314 if (p
->p_pgrp
->pg_members
.lh_first
== 0)
317 LIST_INSERT_HEAD(&pgrp
->pg_members
, p
, p_pglist
);
322 * remove process from process group
326 register struct proc
*p
;
329 LIST_REMOVE(p
, p_pglist
);
330 if (p
->p_pgrp
->pg_members
.lh_first
== 0)
337 * delete a process group
341 register struct pgrp
*pgrp
;
344 if (pgrp
->pg_session
->s_ttyp
!= NULL
&&
345 pgrp
->pg_session
->s_ttyp
->t_pgrp
== pgrp
)
346 pgrp
->pg_session
->s_ttyp
->t_pgrp
= NULL
;
347 LIST_REMOVE(pgrp
, pg_hash
);
348 if (--pgrp
->pg_session
->s_count
== 0)
349 FREE_ZONE(pgrp
->pg_session
, sizeof(struct session
), M_SESSION
);
350 FREE_ZONE(pgrp
, sizeof *pgrp
, M_PGRP
);
355 struct session
*sess
;
357 if (--sess
->s_count
== 0)
358 FREE_ZONE(sess
, sizeof (struct session
), M_SESSION
);
361 static void orphanpg();
364 * Adjust pgrp jobc counters when specified process changes process group.
365 * We count the number of processes in each process group that "qualify"
366 * the group for terminal job control (those with a parent in a different
367 * process group of the same session). If that count reaches zero, the
368 * process group becomes orphaned. Check both the specified process'
369 * process group and that of its children.
370 * entering == 0 => p is leaving specified group.
371 * entering == 1 => p is entering specified group.
374 fixjobc(p
, pgrp
, entering
)
375 register struct proc
*p
;
376 register struct pgrp
*pgrp
;
379 register struct pgrp
*hispgrp
;
380 register struct session
*mysession
= pgrp
->pg_session
;
383 * Check p's parent to see whether p qualifies its own process
384 * group; if so, adjust count for p's process group.
386 if ((hispgrp
= p
->p_pptr
->p_pgrp
) != pgrp
&&
387 hispgrp
->pg_session
== mysession
)
390 else if (--pgrp
->pg_jobc
== 0)
394 * Check this process' children to see whether they qualify
395 * their process groups; if so, adjust counts for children's
398 for (p
= p
->p_children
.lh_first
; p
!= 0; p
= p
->p_sibling
.le_next
)
399 if ((hispgrp
= p
->p_pgrp
) != pgrp
&&
400 hispgrp
->pg_session
== mysession
&&
404 else if (--hispgrp
->pg_jobc
== 0)
409 * A process group has become orphaned;
410 * if there are any stopped processes in the group,
411 * hang-up all process in that group.
417 register struct proc
*p
;
419 for (p
= pg
->pg_members
.lh_first
; p
!= 0; p
= p
->p_pglist
.le_next
) {
420 if (p
->p_stat
== SSTOP
) {
421 for (p
= pg
->pg_members
.lh_first
; p
!= 0;
422 p
= p
->p_pglist
.le_next
) {
436 register struct pgrp
*pgrp
;
437 register struct proc
*p
;
440 for (i
= 0; i
<= pgrphash
; i
++) {
441 if (pgrp
= pgrphashtbl
[i
].lh_first
) {
442 printf("\tindx %d\n", i
);
443 for (; pgrp
!= 0; pgrp
= pgrp
->pg_hash
.le_next
) {
444 printf("\tpgrp 0x%08x, pgid %d, sess %p, sesscnt %d, mem %p\n",
445 pgrp
, pgrp
->pg_id
, pgrp
->pg_session
,
446 pgrp
->pg_session
->s_count
,
447 pgrp
->pg_members
.lh_first
);
448 for (p
= pgrp
->pg_members
.lh_first
; p
!= 0;
449 p
= p
->p_pglist
.le_next
) {
450 printf("\t\tpid %d addr 0x%08x pgrp 0x%08x\n",
451 p
->p_pid
, p
, p
->p_pgrp
);
460 proc_is_classic(struct proc
*p
)
462 return (p
->p_flag
& P_CLASSIC
) ? 1 : 0;
465 struct proc
* current_proc_EXTERNAL()
467 return (current_proc());