* Copyright (c) 1982, 1986, 1989, 1991, 1993
* The Regents of the University of California. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* @(#)kern_proc.c 8.1 (Berkeley) 6/10/93
#include <ufs/ufs/quota.h>
* Structure associated with user cacheing.
struct uidinfo
**ui_prev
;
u_long uihash
; /* size of hash table - 1 */
#define UIHASH(uid) ((uid) & uihash)
uihashtbl
= hashinit(maxproc
/ 16, M_PROC
, &uihash
);
* Change the count associated with number of processes
register struct uidinfo
**uipp
, *uip
, *uiq
;
uipp
= &uihashtbl
[UIHASH(uid
)];
for (uip
= *uipp
; uip
; uip
= uip
->ui_next
)
return (uip
->ui_proccnt
);
panic("chgproccnt: procs < 0");
uiq
->ui_prev
= uip
->ui_prev
;
panic("chgproccnt: lost user");
MALLOC(uip
, struct uidinfo
*, sizeof(*uip
), M_PROC
, M_WAITOK
);
uiq
->ui_prev
= &uip
->ui_next
;
* Is p an inferior of the current process?
for (; p
!= curproc
; p
= p
->p_pptr
)
* Locate a process by number
register struct proc
*p
= pidhash
[PIDHASH(pid
)];
return ((struct proc
*)0);
* Locate a process group by number
register struct pgrp
*pgrp
= pgrphash
[PIDHASH(pgid
)];
for (; pgrp
; pgrp
= pgrp
->pg_hforw
)
return ((struct pgrp
*)0);
* Move p to a new or existing process group (and session)
enterpgrp(p
, pgid
, mksess
)
register struct pgrp
*pgrp
= pgfind(pgid
);
register struct proc
**pp
;
register struct proc
*cp
;
if (pgrp
&& mksess
) /* firewalls */
panic("enterpgrp: setsid into non-empty pgrp");
panic("enterpgrp: session leader attempted setpgrp");
pid_t savepid
= p
->p_pid
;
panic("enterpgrp: new pgrp and pid != pgid");
MALLOC(pgrp
, struct pgrp
*, sizeof(struct pgrp
), M_PGRP
,
if ((np
= pfind(savepid
)) == NULL
|| np
!= p
)
register struct session
*sess
;
MALLOC(sess
, struct session
*, sizeof(struct session
),
bcopy(p
->p_session
->s_login
, sess
->s_login
,
panic("enterpgrp: mksession and p != curproc");
pgrp
->pg_session
= p
->p_session
;
pgrp
->pg_session
->s_count
++;
pgrp
->pg_hforw
= pgrphash
[n
= PIDHASH(pgid
)];
} else if (pgrp
== p
->p_pgrp
)
* Adjust eligibility of affected pgrps to participate in job control.
* Increment eligibility counts before decrementing, otherwise we
* could reach 0 spuriously during the first call.
fixjobc(p
, p
->p_pgrp
, 0);
* unlink p from old process group
for (pp
= &p
->p_pgrp
->pg_mem
; *pp
; pp
= &(*pp
)->p_pgrpnxt
) {
panic("enterpgrp: can't find p on old pgrp");
if (p
->p_pgrp
->pg_mem
== 0)
p
->p_pgrpnxt
= pgrp
->pg_mem
;
* remove process from process group
register struct proc
**pp
= &p
->p_pgrp
->pg_mem
;
for (; *pp
; pp
= &(*pp
)->p_pgrpnxt
) {
panic("leavepgrp: can't find p in pgrp");
register struct pgrp
*pgrp
;
register struct pgrp
**pgp
= &pgrphash
[PIDHASH(pgrp
->pg_id
)];
if (pgrp
->pg_session
->s_ttyp
!= NULL
&&
pgrp
->pg_session
->s_ttyp
->t_pgrp
== pgrp
)
pgrp
->pg_session
->s_ttyp
->t_pgrp
= NULL
;
for (; *pgp
; pgp
= &(*pgp
)->pg_hforw
) {
panic("pgdelete: can't find pgrp on hash chain");
if (--pgrp
->pg_session
->s_count
== 0)
FREE(pgrp
->pg_session
, M_SESSION
);
* Adjust pgrp jobc counters when specified process changes process group.
* We count the number of processes in each process group that "qualify"
* the group for terminal job control (those with a parent in a different
* process group of the same session). If that count reaches zero, the
* process group becomes orphaned. Check both the specified process'
* process group and that of its children.
* entering == 0 => p is leaving specified group.
* entering == 1 => p is entering specified group.
fixjobc(p
, pgrp
, entering
)
register struct pgrp
*pgrp
;
register struct pgrp
*hispgrp
;
register struct session
*mysession
= pgrp
->pg_session
;
* Check p's parent to see whether p qualifies its own process
* group; if so, adjust count for p's process group.
if ((hispgrp
= p
->p_pptr
->p_pgrp
) != pgrp
&&
hispgrp
->pg_session
== mysession
)
else if (--pgrp
->pg_jobc
== 0)
* Check this process' children to see whether they qualify
* their process groups; if so, adjust counts for children's
for (p
= p
->p_cptr
; p
; p
= p
->p_osptr
)
if ((hispgrp
= p
->p_pgrp
) != pgrp
&&
hispgrp
->pg_session
== mysession
&&
else if (--hispgrp
->pg_jobc
== 0)
* A process group has become orphaned;
* if there are any stopped processes in the group,
* hang-up all process in that group.
for (p
= pg
->pg_mem
; p
; p
= p
->p_pgrpnxt
) {
if (p
->p_stat
== SSTOP
) {
for (p
= pg
->pg_mem
; p
; p
= p
->p_pgrpnxt
) {
register struct pgrp
*pgrp
;
for (i
=0; i
<PIDHSZ
; i
++) {
printf("\tindx %d\n", i
);
for (pgrp
=pgrphash
[i
]; pgrp
; pgrp
=pgrp
->pg_hforw
) {
printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n",
pgrp
, pgrp
->pg_id
, pgrp
->pg_session
,
pgrp
->pg_session
->s_count
, pgrp
->pg_mem
);
for (p
=pgrp
->pg_mem
; p
; p
=p
->p_pgrpnxt
) {
printf("\t\tpid %d addr %x pgrp %x\n",