]>
git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_proc.c
   2  * Copyright (c) 2000 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> 
  75 #include <ufs/ufs/quota.h> 
  77 #include <sys/malloc.h> 
  79 #include <sys/ioctl.h> 
  81 #include <sys/signalvar.h> 
  84  * Structure associated with user cacheing. 
  87         LIST_ENTRY(uidinfo
) ui_hash
; 
  91 #define UIHASH(uid)     (&uihashtbl[(uid) & uihash]) 
  92 LIST_HEAD(uihashhead
, uidinfo
) *uihashtbl
; 
  93 u_long uihash
;          /* size of hash table - 1 */ 
  98 struct pidhashhead 
*pidhashtbl
; 
 100 struct pgrphashhead 
*pgrphashtbl
; 
 102 struct proclist allproc
; 
 103 struct proclist zombproc
; 
 106  * Initialize global process hashing structures. 
 113         LIST_INIT(&zombproc
); 
 114         pidhashtbl 
= hashinit(maxproc 
/ 4, M_PROC
, &pidhash
); 
 115         pgrphashtbl 
= hashinit(maxproc 
/ 4, M_PROC
, &pgrphash
); 
 116         uihashtbl 
= hashinit(maxproc 
/ 16, M_PROC
, &uihash
); 
 120  * Change the count associated with number of processes 
 121  * a given user is using. 
 124 chgproccnt(uid
, diff
) 
 128         register struct uidinfo 
*uip
; 
 129         register struct uihashhead 
*uipp
; 
 132         for (uip 
= uipp
->lh_first
; uip 
!= 0; uip 
= uip
->ui_hash
.le_next
) 
 133                 if (uip
->ui_uid 
== uid
) 
 136                 uip
->ui_proccnt 
+= diff
; 
 137                 if (uip
->ui_proccnt 
> 0) 
 138                         return (uip
->ui_proccnt
); 
 139                 if (uip
->ui_proccnt 
< 0) 
 140                         panic("chgproccnt: procs < 0"); 
 141                 LIST_REMOVE(uip
, ui_hash
); 
 142                 FREE_ZONE(uip
, sizeof *uip
, M_PROC
); 
 148                 panic("chgproccnt: lost user"); 
 150         MALLOC_ZONE(uip
, struct uidinfo 
*, sizeof(*uip
), M_PROC
, M_WAITOK
); 
 151         LIST_INSERT_HEAD(uipp
, uip
, ui_hash
); 
 153         uip
->ui_proccnt 
= diff
; 
 158  * Is p an inferior of the current process? 
 162         register struct proc 
*p
; 
 165         for (; p 
!= current_proc(); p 
= p
->p_pptr
) 
 172  * Locate a process by number 
 178         register struct proc 
*p
; 
 183         for (p 
= PIDHASH(pid
)->lh_first
; p 
!= 0; p 
= p
->p_hash
.le_next
) 
 190  * Locate a process group by number 
 196         register struct pgrp 
*pgrp
; 
 198         for (pgrp 
= PGRPHASH(pgid
)->lh_first
; pgrp 
!= 0; pgrp 
= pgrp
->pg_hash
.le_next
) 
 199                 if (pgrp
->pg_id 
== pgid
) 
 206  * Move p to a new or existing process group (and session) 
 209 enterpgrp(p
, pgid
, mksess
) 
 210         register struct proc 
*p
; 
 214         register struct pgrp 
*pgrp 
= pgfind(pgid
); 
 217         if (pgrp 
!= NULL 
&& mksess
)     /* firewalls */ 
 218                 panic("enterpgrp: setsid into non-empty pgrp"); 
 220                 panic("enterpgrp: session leader attempted setpgrp"); 
 223                 pid_t savepid 
= p
->p_pid
; 
 229                 if (p
->p_pid 
!= pgid
) 
 230                         panic("enterpgrp: new pgrp and pid != pgid"); 
 232                 MALLOC_ZONE(pgrp
, struct pgrp 
*, sizeof(struct pgrp
), M_PGRP
, 
 234                 if ((np 
= pfind(savepid
)) == NULL 
|| np 
!= p
) 
 237                         register struct session 
*sess
; 
 242                         MALLOC_ZONE(sess
, struct session 
*, 
 243                                 sizeof(struct session
), M_SESSION
, M_WAITOK
); 
 246                         sess
->s_ttyvp 
= NULL
; 
 248                         bcopy(p
->p_session
->s_login
, sess
->s_login
, 
 249                             sizeof(sess
->s_login
)); 
 250                         p
->p_flag 
&= ~P_CONTROLT
; 
 251                         pgrp
->pg_session 
= sess
; 
 253                         if (p 
!= current_proc()) 
 254                                 panic("enterpgrp: mksession and p != curproc"); 
 257                         pgrp
->pg_session 
= p
->p_session
; 
 258                         pgrp
->pg_session
->s_count
++; 
 261                 LIST_INIT(&pgrp
->pg_members
); 
 262                 LIST_INSERT_HEAD(PGRPHASH(pgid
), pgrp
, pg_hash
); 
 264         } else if (pgrp 
== p
->p_pgrp
) 
 268          * Adjust eligibility of affected pgrps to participate in job control. 
 269          * Increment eligibility counts before decrementing, otherwise we 
 270          * could reach 0 spuriously during the first call. 
 273         fixjobc(p
, p
->p_pgrp
, 0); 
 275         LIST_REMOVE(p
, p_pglist
); 
 276         if (p
->p_pgrp
->pg_members
.lh_first 
== 0) 
 279         LIST_INSERT_HEAD(&pgrp
->pg_members
, p
, p_pglist
); 
 284  * remove process from process group 
 288         register struct proc 
*p
; 
 291         LIST_REMOVE(p
, p_pglist
); 
 292         if (p
->p_pgrp
->pg_members
.lh_first 
== 0) 
 299  * delete a process group 
 303         register struct pgrp 
*pgrp
; 
 306         if (pgrp
->pg_session
->s_ttyp 
!= NULL 
&&  
 307             pgrp
->pg_session
->s_ttyp
->t_pgrp 
== pgrp
) 
 308                 pgrp
->pg_session
->s_ttyp
->t_pgrp 
= NULL
; 
 309         LIST_REMOVE(pgrp
, pg_hash
); 
 310         if (--pgrp
->pg_session
->s_count 
== 0) 
 311                 FREE_ZONE(pgrp
->pg_session
, sizeof(struct session
), M_SESSION
); 
 312         FREE_ZONE(pgrp
, sizeof *pgrp
, M_PGRP
); 
 317         struct session 
*sess
; 
 319         if (--sess
->s_count 
== 0) 
 320                 FREE_ZONE(sess
, sizeof (struct session
), M_SESSION
); 
 323 static void orphanpg(); 
 326  * Adjust pgrp jobc counters when specified process changes process group. 
 327  * We count the number of processes in each process group that "qualify" 
 328  * the group for terminal job control (those with a parent in a different 
 329  * process group of the same session).  If that count reaches zero, the 
 330  * process group becomes orphaned.  Check both the specified process' 
 331  * process group and that of its children. 
 332  * entering == 0 => p is leaving specified group. 
 333  * entering == 1 => p is entering specified group. 
 336 fixjobc(p
, pgrp
, entering
) 
 337         register struct proc 
*p
; 
 338         register struct pgrp 
*pgrp
; 
 341         register struct pgrp 
*hispgrp
; 
 342         register struct session 
*mysession 
= pgrp
->pg_session
; 
 345          * Check p's parent to see whether p qualifies its own process 
 346          * group; if so, adjust count for p's process group. 
 348         if ((hispgrp 
= p
->p_pptr
->p_pgrp
) != pgrp 
&& 
 349             hispgrp
->pg_session 
== mysession
) 
 352                 else if (--pgrp
->pg_jobc 
== 0) 
 356          * Check this process' children to see whether they qualify 
 357          * their process groups; if so, adjust counts for children's 
 360         for (p 
= p
->p_children
.lh_first
; p 
!= 0; p 
= p
->p_sibling
.le_next
) 
 361                 if ((hispgrp 
= p
->p_pgrp
) != pgrp 
&& 
 362                     hispgrp
->pg_session 
== mysession 
&& 
 366                         else if (--hispgrp
->pg_jobc 
== 0) 
 371  * A process group has become orphaned; 
 372  * if there are any stopped processes in the group, 
 373  * hang-up all process in that group. 
 379         register struct proc 
*p
; 
 381         for (p 
= pg
->pg_members
.lh_first
; p 
!= 0; p 
= p
->p_pglist
.le_next
) { 
 382                 if (p
->p_stat 
== SSTOP
) { 
 383                         for (p 
= pg
->pg_members
.lh_first
; p 
!= 0; 
 384                             p 
= p
->p_pglist
.le_next
) { 
 398         register struct pgrp 
*pgrp
; 
 399         register struct proc 
*p
; 
 402         for (i 
= 0; i 
<= pgrphash
; i
++) { 
 403                 if (pgrp 
= pgrphashtbl
[i
].lh_first
) { 
 404                         printf("\tindx %d\n", i
); 
 405                         for (; pgrp 
!= 0; pgrp 
= pgrp
->pg_hash
.le_next
) { 
 406                                 printf("\tpgrp 0x%08x, pgid %d, sess %p, sesscnt %d, mem %p\n", 
 407                                     pgrp
, pgrp
->pg_id
, pgrp
->pg_session
, 
 408                                     pgrp
->pg_session
->s_count
, 
 409                                     pgrp
->pg_members
.lh_first
); 
 410                                 for (p 
= pgrp
->pg_members
.lh_first
; p 
!= 0; 
 411                                     p 
= p
->p_pglist
.le_next
) { 
 412                                         printf("\t\tpid %d addr 0x%08x pgrp 0x%08x\n",  
 413                                             p
->p_pid
, p
, p
->p_pgrp
); 
 421 struct proc 
* current_proc_EXTERNAL() 
 423         return (current_proc());