]>
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 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
24 * Copyright (c) 1982, 1986, 1989, 1991, 1993
25 * The Regents of the University of California. All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * @(#)kern_proc.c 8.4 (Berkeley) 1/4/94
58 * 04-Aug-97 Umesh Vaishampayan (umeshv@apple.com)
59 * Added current_proc_EXTERNAL() function for the use of kernel
62 * 05-Jun-95 Mac Gillon (mgillon) at NeXT
63 * New version based on 3.3NS and 4.4
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/kernel.h>
70 #include <sys/proc_internal.h>
73 #include <sys/file_internal.h>
74 #include <ufs/ufs/quota.h>
76 #include <sys/malloc.h>
78 #include <sys/ioctl.h>
80 #include <sys/signalvar.h>
81 #include <sys/syslog.h>
82 #include <sys/kernel_types.h>
85 * Structure associated with user cacheing.
88 LIST_ENTRY(uidinfo
) ui_hash
;
92 #define UIHASH(uid) (&uihashtbl[(uid) & uihash])
93 LIST_HEAD(uihashhead
, uidinfo
) *uihashtbl
;
94 u_long uihash
; /* size of hash table - 1 */
99 struct pidhashhead
*pidhashtbl
;
101 struct pgrphashhead
*pgrphashtbl
;
103 struct proclist allproc
;
104 struct proclist zombproc
;
105 extern struct tty cons
;
107 /* Name to give to core files */
108 __private_extern__
char corefilename
[MAXPATHLEN
+1] = {"/cores/core.%P"};
110 static void orphanpg(struct pgrp
*pg
);
113 * Initialize global process hashing structures.
120 LIST_INIT(&zombproc
);
121 pidhashtbl
= hashinit(maxproc
/ 4, M_PROC
, &pidhash
);
122 pgrphashtbl
= hashinit(maxproc
/ 4, M_PROC
, &pgrphash
);
123 uihashtbl
= hashinit(maxproc
/ 16, M_PROC
, &uihash
);
127 * Change the count associated with number of processes
128 * a given user is using.
131 chgproccnt(uid
, diff
)
135 register struct uidinfo
*uip
;
136 register struct uihashhead
*uipp
;
139 for (uip
= uipp
->lh_first
; uip
!= 0; uip
= uip
->ui_hash
.le_next
)
140 if (uip
->ui_uid
== uid
)
143 uip
->ui_proccnt
+= diff
;
144 if (uip
->ui_proccnt
> 0)
145 return (uip
->ui_proccnt
);
146 if (uip
->ui_proccnt
< 0)
147 panic("chgproccnt: procs < 0");
148 LIST_REMOVE(uip
, ui_hash
);
149 FREE_ZONE(uip
, sizeof *uip
, M_PROC
);
155 panic("chgproccnt: lost user");
157 MALLOC_ZONE(uip
, struct uidinfo
*, sizeof(*uip
), M_PROC
, M_WAITOK
);
159 panic("chgproccnt: M_PROC zone depleted");
160 LIST_INSERT_HEAD(uipp
, uip
, ui_hash
);
162 uip
->ui_proccnt
= diff
;
167 * Is p an inferior of the current process?
171 register struct proc
*p
;
174 for (; p
!= current_proc(); p
= p
->p_pptr
)
180 * Is p an inferior of t ?
183 isinferior(struct proc
*p
, struct proc
*t
)
186 /* if p==t they are not inferior */
189 for (; p
!= t
; p
= p
->p_pptr
)
196 proc_isinferior(int pid1
, int pid2
)
201 if (((p
= pfind(pid1
)) != (struct proc
*)0 ) && ((t
= pfind(pid2
)) != (struct proc
*)0))
202 return (isinferior(p
, t
));
213 proc_rele(__unused proc_t p
)
221 return(current_proc());
225 proc_findref(int pid
)
227 boolean_t funnel_state
;
230 funnel_state
= thread_funnel_set(kernel_flock
,TRUE
);
233 if (p
!= proc_refinternal(p
, 1))
236 thread_funnel_set(kernel_flock
, funnel_state
);
241 proc_dropref(proc_t p
)
244 proc_dropinternal(p
, 0);
249 proc_refinternal(proc_t p
, int funneled
)
253 boolean_t funnel_state
= TRUE
; /* need to init just to avoid warnings and build failure */
256 funnel_state
= thread_funnel_set(kernel_flock
,TRUE
);
258 if ((p
!= PROC_NULL
) &&(p
->p_stat
!= SZOMB
) && ((p
->p_lflag
& (P_LREFDRAINWAIT
| P_LREFDRAIN
| P_LREFDEAD
)) == 0))
264 thread_funnel_set(kernel_flock
,funnel_state
);
269 proc_dropinternal(proc_t p
, int funneled
)
271 boolean_t funnel_state
= TRUE
; /* need to init just to avoid warnings and build failure */
274 funnel_state
= thread_funnel_set(kernel_flock
,TRUE
);
276 if (p
->p_internalref
> 0) {
278 if ((p
->p_internalref
== 0) && ((p
->p_lflag
& P_LREFDRAINWAIT
) == P_LREFDRAINWAIT
)) {
279 p
->p_lflag
&= ~P_LREFDRAINWAIT
;
280 wakeup(&p
->p_internalref
);
283 printf("proc_dropreg -ve ref\n");
286 thread_funnel_set(kernel_flock
,funnel_state
);
299 if (p
->p_pptr
!= (struct proc
*)0)
300 return(p
->p_pptr
->p_pid
);
307 struct proc
*p
= current_proc();
315 struct proc
*p
= current_proc();
317 return(p
->p_pptr
->p_pid
);
323 proc_name(int pid
, char * buf
, int size
)
327 if ((p
= pfind(pid
))!= (struct proc
*)0) {
328 strncpy(buf
, &p
->p_comm
[0], size
);
334 proc_selfname(char * buf
, int size
)
338 if ((p
= current_proc())!= (struct proc
*)0) {
339 strncpy(buf
, &p
->p_comm
[0], size
);
345 proc_signal(int pid
, int signum
)
349 if ((p
= pfind(pid
))!= (struct proc
*)0) {
355 proc_issignal(int pid
, sigset_t mask
)
359 if ((p
= pfind(pid
))!= (struct proc
*)0) {
360 return(proc_pendingsignals(p
, mask
));
366 proc_noremotehang(proc_t p
)
371 retval
= p
->p_flag
& P_NOREMOTEHANG
;
372 return(retval
? 1: 0);
377 proc_exiting(proc_t p
)
382 retval
= p
->p_flag
& P_WEXIT
;
383 return(retval
? 1: 0);
388 proc_forcequota(proc_t p
)
393 retval
= p
->p_flag
& P_FORCEQUOTA
;
394 return(retval
? 1: 0);
404 retval
= p
->p_flag
& P_TBE
;
405 return(retval
? 1: 0);
412 return(suser(p
->p_ucred
, NULL
));
424 proc_is64bit(proc_t p
)
426 return(IS_64BIT_PROCESS(p
));
429 /* LP64todo - figure out how to identify 64-bit processes if NULL procp */
431 IS_64BIT_PROCESS(proc_t p
)
433 if (p
&& (p
->p_flag
& P_LP64
))
441 * Locate a process by number
447 register struct proc
*p
;
452 for (p
= PIDHASH(pid
)->lh_first
; p
!= 0; p
= p
->p_hash
.le_next
)
459 * Locate a zombie by PID
461 __private_extern__
struct proc
*
465 register struct proc
*p
;
467 for (p
= zombproc
.lh_first
; p
!= 0; p
= p
->p_list
.le_next
)
474 * Locate a process group by number
480 register struct pgrp
*pgrp
;
482 for (pgrp
= PGRPHASH(pgid
)->lh_first
; pgrp
!= 0; pgrp
= pgrp
->pg_hash
.le_next
)
483 if (pgrp
->pg_id
== pgid
)
490 * Move p to a new or existing process group (and session)
493 enterpgrp(p
, pgid
, mksess
)
494 register struct proc
*p
;
498 register struct pgrp
*pgrp
= pgfind(pgid
);
501 if (pgrp
!= NULL
&& mksess
) /* firewalls */
502 panic("enterpgrp: setsid into non-empty pgrp");
504 panic("enterpgrp: session leader attempted setpgrp");
507 pid_t savepid
= p
->p_pid
;
513 if (p
->p_pid
!= pgid
)
514 panic("enterpgrp: new pgrp and pid != pgid");
516 MALLOC_ZONE(pgrp
, struct pgrp
*, sizeof(struct pgrp
), M_PGRP
,
519 panic("enterpgrp: M_PGRP zone depleted");
520 if ((np
= pfind(savepid
)) == NULL
|| np
!= p
) {
521 FREE_ZONE(pgrp
, sizeof(struct pgrp
), M_PGRP
);
525 register struct session
*sess
;
530 MALLOC_ZONE(sess
, struct session
*,
531 sizeof(struct session
), M_SESSION
, M_WAITOK
);
533 panic("enterpgrp: M_SESSION zone depleted");
535 sess
->s_sid
= p
->p_pid
;
537 sess
->s_ttyvp
= NULL
;
539 bcopy(p
->p_session
->s_login
, sess
->s_login
,
540 sizeof(sess
->s_login
));
541 p
->p_flag
&= ~P_CONTROLT
;
542 pgrp
->pg_session
= sess
;
544 if (p
!= current_proc())
545 panic("enterpgrp: mksession and p != curproc");
548 pgrp
->pg_session
= p
->p_session
;
549 pgrp
->pg_session
->s_count
++;
552 LIST_INIT(&pgrp
->pg_members
);
553 LIST_INSERT_HEAD(PGRPHASH(pgid
), pgrp
, pg_hash
);
555 } else if (pgrp
== p
->p_pgrp
)
559 * Adjust eligibility of affected pgrps to participate in job control.
560 * Increment eligibility counts before decrementing, otherwise we
561 * could reach 0 spuriously during the first call.
564 fixjobc(p
, p
->p_pgrp
, 0);
566 LIST_REMOVE(p
, p_pglist
);
567 if (p
->p_pgrp
->pg_members
.lh_first
== 0)
570 LIST_INSERT_HEAD(&pgrp
->pg_members
, p
, p_pglist
);
575 * remove process from process group
579 register struct proc
*p
;
582 LIST_REMOVE(p
, p_pglist
);
583 if (p
->p_pgrp
->pg_members
.lh_first
== 0)
590 * delete a process group
594 register struct pgrp
*pgrp
;
598 ttyp
= pgrp
->pg_session
->s_ttyp
;
599 if (ttyp
!= NULL
&& pgrp
->pg_session
->s_ttyp
->t_pgrp
== pgrp
) {
600 pgrp
->pg_session
->s_ttyp
->t_pgrp
= NULL
;
602 LIST_REMOVE(pgrp
, pg_hash
);
603 if (--pgrp
->pg_session
->s_count
== 0) {
604 if (ttyp
!= NULL
&& (ttyp
->t_session
== pgrp
->pg_session
))
606 FREE_ZONE(pgrp
->pg_session
, sizeof(struct session
), M_SESSION
);
608 FREE_ZONE(pgrp
, sizeof *pgrp
, M_PGRP
);
613 struct session
*sess
;
615 if (--sess
->s_count
== 0)
616 FREE_ZONE(sess
, sizeof (struct session
), M_SESSION
);
620 * Adjust pgrp jobc counters when specified process changes process group.
621 * We count the number of processes in each process group that "qualify"
622 * the group for terminal job control (those with a parent in a different
623 * process group of the same session). If that count reaches zero, the
624 * process group becomes orphaned. Check both the specified process'
625 * process group and that of its children.
626 * entering == 0 => p is leaving specified group.
627 * entering == 1 => p is entering specified group.
630 fixjobc(struct proc
*p
, struct pgrp
*pgrp
, int entering
)
632 register struct pgrp
*hispgrp
;
633 register struct session
*mysession
= pgrp
->pg_session
;
636 * Check p's parent to see whether p qualifies its own process
637 * group; if so, adjust count for p's process group.
639 if ((hispgrp
= p
->p_pptr
->p_pgrp
) != pgrp
&&
640 hispgrp
->pg_session
== mysession
) {
643 else if (--pgrp
->pg_jobc
== 0)
648 * Check this process' children to see whether they qualify
649 * their process groups; if so, adjust counts for children's
652 for (p
= p
->p_children
.lh_first
; p
!= 0; p
= p
->p_sibling
.le_next
)
653 if ((hispgrp
= p
->p_pgrp
) != pgrp
&&
654 hispgrp
->pg_session
== mysession
&&
655 p
->p_stat
!= SZOMB
) {
658 else if (--hispgrp
->pg_jobc
== 0)
664 * A process group has become orphaned;
665 * if there are any stopped processes in the group,
666 * hang-up all process in that group.
669 orphanpg(struct pgrp
*pg
)
671 register struct proc
*p
;
673 for (p
= pg
->pg_members
.lh_first
; p
!= 0; p
= p
->p_pglist
.le_next
) {
674 if (p
->p_stat
== SSTOP
) {
675 for (p
= pg
->pg_members
.lh_first
; p
!= 0;
676 p
= p
->p_pglist
.le_next
) {
687 void pgrpdump(void); /* forward declare here (called from debugger) */
696 for (i
= 0; i
<= pgrphash
; i
++) {
697 if ((pgrp
= pgrphashtbl
[i
].lh_first
) != NULL
) {
698 printf("\tindx %d\n", i
);
699 for (; pgrp
!= 0; pgrp
= pgrp
->pg_hash
.le_next
) {
700 printf("\tpgrp 0x%08x, pgid %d, sess %p, sesscnt %d, mem %p\n",
701 pgrp
, pgrp
->pg_id
, pgrp
->pg_session
,
702 pgrp
->pg_session
->s_count
,
703 pgrp
->pg_members
.lh_first
);
704 for (p
= pgrp
->pg_members
.lh_first
; p
!= 0;
705 p
= p
->p_pglist
.le_next
) {
706 printf("\t\tpid %d addr 0x%08x pgrp 0x%08x\n",
707 p
->p_pid
, p
, p
->p_pgrp
);
715 /* XXX should be __private_extern__ */
717 proc_is_classic(struct proc
*p
)
719 return (p
->p_flag
& P_CLASSIC
) ? 1 : 0;
722 /* XXX Why does this function exist? Need to kill it off... */
724 current_proc_EXTERNAL(void)
726 return (current_proc());
730 * proc_core_name(name, uid, pid)
731 * Expand the name described in corefilename, using name, uid, and pid.
732 * corefilename is a printf-like string, with three format specifiers:
733 * %N name of process ("name")
734 * %P process id (pid)
736 * For example, "%N.core" is the default; they can be disabled completely
737 * by using "/dev/null", or all core files can be stored in "/cores/%U/%N-%P".
738 * This is controlled by the sysctl variable kern.corefile (see above).
740 __private_extern__
char *
741 proc_core_name(const char *name
, uid_t uid
, pid_t pid
)
743 const char *format
, *appendstr
;
745 char id_buf
[11]; /* Buffer for pid/uid -- max 4B */
748 format
= corefilename
;
749 MALLOC(temp
, char *, MAXPATHLEN
, M_TEMP
, M_NOWAIT
| M_ZERO
);
752 for (i
= 0, n
= 0; n
< MAXPATHLEN
&& format
[i
]; i
++) {
754 case '%': /* Format character */
760 case 'N': /* process name */
763 case 'P': /* process id */
764 sprintf(id_buf
, "%u", pid
);
767 case 'U': /* user id */
768 sprintf(id_buf
, "%u", uid
);
774 "Unknown format character %c in `%s'\n",
777 l
= strlen(appendstr
);
778 if ((n
+ l
) >= MAXPATHLEN
)
780 bcopy(appendstr
, temp
+ n
, l
);
784 temp
[n
++] = format
[i
];
787 if (format
[i
] != '\0')
791 log(LOG_ERR
, "pid %ld (%s), uid (%lu): corename is too long\n",
792 (long)pid
, name
, (u_long
)uid
);