* Copyright (c) 1982, 1986, 1989, 1991, 1993
* The Regents of the University of California. All rights reserved.
* %sccs.include.redist.c%
* @(#)kern_proc.c 8.7 (Berkeley) %G%
#include <ufs/ufs/quota.h>
* Structure associated with user cacheing.
LIST_ENTRY(uidinfo
) ui_hash
;
#define UIHASH(uid) (&uihashtbl[(uid) & uihash])
LIST_HEAD(uihashhead
, uidinfo
) *uihashtbl
;
u_long uihash
; /* size of hash table - 1 */
struct pidhashhead
*pidhashtbl
;
struct pgrphashhead
*pgrphashtbl
;
struct proclist zombproc
;
* Initialize global process hashing structures.
pidhashtbl
= hashinit(maxproc
/ 4, M_PROC
, &pidhash
);
pgrphashtbl
= hashinit(maxproc
/ 4, M_PROC
, &pgrphash
);
uihashtbl
= hashinit(maxproc
/ 16, M_PROC
, &uihash
);
* Change the count associated with number of processes
register struct uidinfo
*uip
;
register struct uihashhead
*uipp
;
for (uip
= uipp
->lh_first
; uip
!= 0; uip
= uip
->ui_hash
.le_next
)
return (uip
->ui_proccnt
);
panic("chgproccnt: procs < 0");
LIST_REMOVE(uip
, ui_hash
);
panic("chgproccnt: lost user");
MALLOC(uip
, struct uidinfo
*, sizeof(*uip
), M_PROC
, M_WAITOK
);
LIST_INSERT_HEAD(uipp
, uip
, ui_hash
);
* Is p an inferior of the current process?
for (; p
!= curproc
; p
= p
->p_pptr
)
* Locate a process by number
for (p
= PIDHASH(pid
)->lh_first
; p
!= 0; p
= p
->p_hash
.le_next
)
* Locate a process group by number
register struct pgrp
*pgrp
;
for (pgrp
= PGRPHASH(pgid
)->lh_first
; pgrp
!= 0;
pgrp
= pgrp
->pg_hash
.le_next
)
* Move p to a new or existing process group (and session)
enterpgrp(p
, pgid
, mksess
)
register struct pgrp
*pgrp
= pgfind(pgid
);
if (pgrp
!= NULL
&& 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
,
p
->p_flag
&= ~P_CONTROLT
;
panic("enterpgrp: mksession and p != curproc");
pgrp
->pg_session
= p
->p_session
;
pgrp
->pg_session
->s_count
++;
LIST_INIT(&pgrp
->pg_members
);
LIST_INSERT_HEAD(PGRPHASH(pgid
), pgrp
, pg_hash
);
} 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);
LIST_REMOVE(p
, p_pglist
);
if (p
->p_pgrp
->pg_members
.lh_first
== 0)
LIST_INSERT_HEAD(&pgrp
->pg_members
, p
, p_pglist
);
* remove process from process group
LIST_REMOVE(p
, p_pglist
);
if (p
->p_pgrp
->pg_members
.lh_first
== 0)
register struct pgrp
*pgrp
;
if (pgrp
->pg_session
->s_ttyp
!= NULL
&&
pgrp
->pg_session
->s_ttyp
->t_pgrp
== pgrp
)
pgrp
->pg_session
->s_ttyp
->t_pgrp
= NULL
;
LIST_REMOVE(pgrp
, pg_hash
);
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_children
.lh_first
; p
!= 0; p
= p
->p_sibling
.le_next
)
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_members
.lh_first
; p
!= 0; p
= p
->p_pglist
.le_next
) {
if (p
->p_stat
== SSTOP
) {
for (p
= pg
->pg_members
.lh_first
; p
!= 0;
p
= p
->p_pglist
.le_next
) {
register struct pgrp
*pgrp
;
for (i
= 0; i
<= pgrphash
; i
++) {
if (pgrp
= pgrphashtbl
[i
].lh_first
) {
printf("\tindx %d\n", i
);
for (; pgrp
!= 0; pgrp
= pgrp
->pg_hash
.le_next
) {
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_members
.lh_first
);
for (p
= pgrp
->pg_members
.lh_first
; p
!= 0;
p
= p
->p_pglist
.le_next
) {
printf("\t\tpid %d addr %x pgrp %x\n",