proc: eliminate the zombproc list
It is not needed by anything in the kernel and it slightly drives up contention on both proctree and allproc locks. Reviewed by: kib Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D21447
This commit is contained in:
parent
b5d239cb97
commit
88cc62e5a5
254
sys/ddb/db_ps.c
254
sys/ddb/db_ps.c
@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
static void dumpthread(volatile struct proc *p, volatile struct thread *td,
|
||||
int all);
|
||||
static void db_ps_proc(struct proc *p);
|
||||
static int ps_mode;
|
||||
|
||||
/*
|
||||
@ -105,146 +106,157 @@ dump_args(volatile struct proc *p)
|
||||
void
|
||||
db_ps(db_expr_t addr, bool hasaddr, db_expr_t count, char *modif)
|
||||
{
|
||||
volatile struct proc *p, *pp;
|
||||
volatile struct thread *td;
|
||||
struct ucred *cred;
|
||||
struct pgrp *pgrp;
|
||||
char state[9];
|
||||
int np, rflag, sflag, dflag, lflag, wflag;
|
||||
struct proc *p;
|
||||
int i, j;
|
||||
|
||||
ps_mode = modif[0] == 'a' ? PRINT_ARGS : PRINT_NONE;
|
||||
np = nprocs;
|
||||
|
||||
if (!LIST_EMPTY(&allproc))
|
||||
p = LIST_FIRST(&allproc);
|
||||
else
|
||||
p = &proc0;
|
||||
|
||||
#ifdef __LP64__
|
||||
db_printf(" pid ppid pgrp uid state wmesg wchan cmd\n");
|
||||
#else
|
||||
db_printf(" pid ppid pgrp uid state wmesg wchan cmd\n");
|
||||
#endif
|
||||
while (--np >= 0 && !db_pager_quit) {
|
||||
if (p == NULL) {
|
||||
db_printf("oops, ran out of processes early!\n");
|
||||
break;
|
||||
|
||||
if (!LIST_EMPTY(&allproc))
|
||||
p = LIST_FIRST(&allproc);
|
||||
else
|
||||
p = &proc0;
|
||||
for (; p != NULL && !db_pager_quit; p = LIST_NEXT(p, p_list))
|
||||
db_ps_proc(p);
|
||||
|
||||
/*
|
||||
* Do zombies.
|
||||
*/
|
||||
for (i = 0; i < pidhashlock + 1 && !db_pager_quit; i++) {
|
||||
for (j = i; j <= pidhash && !db_pager_quit; j += pidhashlock + 1) {
|
||||
LIST_FOREACH(p, &pidhashtbl[j], p_hash) {
|
||||
if (p->p_state == PRS_ZOMBIE)
|
||||
db_ps_proc(p);
|
||||
}
|
||||
}
|
||||
pp = p->p_pptr;
|
||||
if (pp == NULL)
|
||||
pp = p;
|
||||
}
|
||||
}
|
||||
|
||||
cred = p->p_ucred;
|
||||
pgrp = p->p_pgrp;
|
||||
db_printf("%5d %5d %5d %5d ", p->p_pid, pp->p_pid,
|
||||
pgrp != NULL ? pgrp->pg_id : 0,
|
||||
cred != NULL ? cred->cr_ruid : 0);
|
||||
static void
|
||||
db_ps_proc(struct proc *p)
|
||||
{
|
||||
volatile struct proc *pp;
|
||||
volatile struct thread *td;
|
||||
struct ucred *cred;
|
||||
struct pgrp *pgrp;
|
||||
char state[9];
|
||||
int rflag, sflag, dflag, lflag, wflag;
|
||||
|
||||
/* Determine our primary process state. */
|
||||
switch (p->p_state) {
|
||||
case PRS_NORMAL:
|
||||
if (P_SHOULDSTOP(p))
|
||||
state[0] = 'T';
|
||||
else {
|
||||
/*
|
||||
* One of D, L, R, S, W. For a
|
||||
* multithreaded process we will use
|
||||
* the state of the thread with the
|
||||
* highest precedence. The
|
||||
* precendence order from high to low
|
||||
* is R, L, D, S, W. If no thread is
|
||||
* in a sane state we use '?' for our
|
||||
* primary state.
|
||||
*/
|
||||
rflag = sflag = dflag = lflag = wflag = 0;
|
||||
FOREACH_THREAD_IN_PROC(p, td) {
|
||||
if (td->td_state == TDS_RUNNING ||
|
||||
td->td_state == TDS_RUNQ ||
|
||||
td->td_state == TDS_CAN_RUN)
|
||||
rflag++;
|
||||
if (TD_ON_LOCK(td))
|
||||
lflag++;
|
||||
if (TD_IS_SLEEPING(td)) {
|
||||
if (!(td->td_flags & TDF_SINTR))
|
||||
dflag++;
|
||||
else
|
||||
sflag++;
|
||||
}
|
||||
if (TD_AWAITING_INTR(td))
|
||||
wflag++;
|
||||
pp = p->p_pptr;
|
||||
if (pp == NULL)
|
||||
pp = p;
|
||||
|
||||
cred = p->p_ucred;
|
||||
pgrp = p->p_pgrp;
|
||||
db_printf("%5d %5d %5d %5d ", p->p_pid, pp->p_pid,
|
||||
pgrp != NULL ? pgrp->pg_id : 0,
|
||||
cred != NULL ? cred->cr_ruid : 0);
|
||||
|
||||
/* Determine our primary process state. */
|
||||
switch (p->p_state) {
|
||||
case PRS_NORMAL:
|
||||
if (P_SHOULDSTOP(p))
|
||||
state[0] = 'T';
|
||||
else {
|
||||
/*
|
||||
* One of D, L, R, S, W. For a
|
||||
* multithreaded process we will use
|
||||
* the state of the thread with the
|
||||
* highest precedence. The
|
||||
* precendence order from high to low
|
||||
* is R, L, D, S, W. If no thread is
|
||||
* in a sane state we use '?' for our
|
||||
* primary state.
|
||||
*/
|
||||
rflag = sflag = dflag = lflag = wflag = 0;
|
||||
FOREACH_THREAD_IN_PROC(p, td) {
|
||||
if (td->td_state == TDS_RUNNING ||
|
||||
td->td_state == TDS_RUNQ ||
|
||||
td->td_state == TDS_CAN_RUN)
|
||||
rflag++;
|
||||
if (TD_ON_LOCK(td))
|
||||
lflag++;
|
||||
if (TD_IS_SLEEPING(td)) {
|
||||
if (!(td->td_flags & TDF_SINTR))
|
||||
dflag++;
|
||||
else
|
||||
sflag++;
|
||||
}
|
||||
if (rflag)
|
||||
state[0] = 'R';
|
||||
else if (lflag)
|
||||
state[0] = 'L';
|
||||
else if (dflag)
|
||||
state[0] = 'D';
|
||||
else if (sflag)
|
||||
state[0] = 'S';
|
||||
else if (wflag)
|
||||
state[0] = 'W';
|
||||
else
|
||||
state[0] = '?';
|
||||
if (TD_AWAITING_INTR(td))
|
||||
wflag++;
|
||||
}
|
||||
break;
|
||||
case PRS_NEW:
|
||||
state[0] = 'N';
|
||||
break;
|
||||
case PRS_ZOMBIE:
|
||||
state[0] = 'Z';
|
||||
break;
|
||||
default:
|
||||
state[0] = 'U';
|
||||
break;
|
||||
if (rflag)
|
||||
state[0] = 'R';
|
||||
else if (lflag)
|
||||
state[0] = 'L';
|
||||
else if (dflag)
|
||||
state[0] = 'D';
|
||||
else if (sflag)
|
||||
state[0] = 'S';
|
||||
else if (wflag)
|
||||
state[0] = 'W';
|
||||
else
|
||||
state[0] = '?';
|
||||
}
|
||||
state[1] = '\0';
|
||||
break;
|
||||
case PRS_NEW:
|
||||
state[0] = 'N';
|
||||
break;
|
||||
case PRS_ZOMBIE:
|
||||
state[0] = 'Z';
|
||||
break;
|
||||
default:
|
||||
state[0] = 'U';
|
||||
break;
|
||||
}
|
||||
state[1] = '\0';
|
||||
|
||||
/* Additional process state flags. */
|
||||
if (!(p->p_flag & P_INMEM))
|
||||
strlcat(state, "W", sizeof(state));
|
||||
if (p->p_flag & P_TRACED)
|
||||
strlcat(state, "X", sizeof(state));
|
||||
if (p->p_flag & P_WEXIT && p->p_state != PRS_ZOMBIE)
|
||||
strlcat(state, "E", sizeof(state));
|
||||
if (p->p_flag & P_PPWAIT)
|
||||
strlcat(state, "V", sizeof(state));
|
||||
if (p->p_flag & P_SYSTEM || p->p_lock > 0)
|
||||
strlcat(state, "L", sizeof(state));
|
||||
if (p->p_pgrp != NULL && p->p_session != NULL &&
|
||||
SESS_LEADER(p))
|
||||
strlcat(state, "s", sizeof(state));
|
||||
/* Cheated here and didn't compare pgid's. */
|
||||
if (p->p_flag & P_CONTROLT)
|
||||
strlcat(state, "+", sizeof(state));
|
||||
if (cred != NULL && jailed(cred))
|
||||
strlcat(state, "J", sizeof(state));
|
||||
db_printf(" %-6.6s ", state);
|
||||
if (p->p_flag & P_HADTHREADS) {
|
||||
/* Additional process state flags. */
|
||||
if (!(p->p_flag & P_INMEM))
|
||||
strlcat(state, "W", sizeof(state));
|
||||
if (p->p_flag & P_TRACED)
|
||||
strlcat(state, "X", sizeof(state));
|
||||
if (p->p_flag & P_WEXIT && p->p_state != PRS_ZOMBIE)
|
||||
strlcat(state, "E", sizeof(state));
|
||||
if (p->p_flag & P_PPWAIT)
|
||||
strlcat(state, "V", sizeof(state));
|
||||
if (p->p_flag & P_SYSTEM || p->p_lock > 0)
|
||||
strlcat(state, "L", sizeof(state));
|
||||
if (p->p_pgrp != NULL && p->p_session != NULL &&
|
||||
SESS_LEADER(p))
|
||||
strlcat(state, "s", sizeof(state));
|
||||
/* Cheated here and didn't compare pgid's. */
|
||||
if (p->p_flag & P_CONTROLT)
|
||||
strlcat(state, "+", sizeof(state));
|
||||
if (cred != NULL && jailed(cred))
|
||||
strlcat(state, "J", sizeof(state));
|
||||
db_printf(" %-6.6s ", state);
|
||||
if (p->p_flag & P_HADTHREADS) {
|
||||
#ifdef __LP64__
|
||||
db_printf(" (threaded) ");
|
||||
db_printf(" (threaded) ");
|
||||
#else
|
||||
db_printf(" (threaded) ");
|
||||
db_printf(" (threaded) ");
|
||||
#endif
|
||||
if (p->p_flag & P_SYSTEM)
|
||||
db_printf("[");
|
||||
db_printf("%s", p->p_comm);
|
||||
if (p->p_flag & P_SYSTEM)
|
||||
db_printf("]");
|
||||
if (ps_mode == PRINT_ARGS) {
|
||||
db_printf(" ");
|
||||
dump_args(p);
|
||||
}
|
||||
db_printf("\n");
|
||||
if (p->p_flag & P_SYSTEM)
|
||||
db_printf("[");
|
||||
db_printf("%s", p->p_comm);
|
||||
if (p->p_flag & P_SYSTEM)
|
||||
db_printf("]");
|
||||
if (ps_mode == PRINT_ARGS) {
|
||||
db_printf(" ");
|
||||
dump_args(p);
|
||||
}
|
||||
FOREACH_THREAD_IN_PROC(p, td) {
|
||||
dumpthread(p, td, p->p_flag & P_HADTHREADS);
|
||||
if (db_pager_quit)
|
||||
break;
|
||||
}
|
||||
|
||||
p = LIST_NEXT(p, p_list);
|
||||
if (p == NULL && np > 0)
|
||||
p = LIST_FIRST(&zombproc);
|
||||
db_printf("\n");
|
||||
}
|
||||
FOREACH_THREAD_IN_PROC(p, td) {
|
||||
dumpthread(p, td, p->p_flag & P_HADTHREADS);
|
||||
if (db_pager_quit)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,11 +125,7 @@ db_lookup_thread(db_expr_t addr, bool check_pid)
|
||||
if (td != NULL)
|
||||
return (td);
|
||||
if (check_pid) {
|
||||
FOREACH_PROC_IN_SYSTEM(p) {
|
||||
if (p->p_pid == decaddr)
|
||||
return (FIRST_THREAD_IN_PROC(p));
|
||||
}
|
||||
LIST_FOREACH(p, &zombproc, p_list) {
|
||||
LIST_FOREACH(p, PIDHASH(decaddr), p_hash) {
|
||||
if (p->p_pid == decaddr)
|
||||
return (FIRST_THREAD_IN_PROC(p));
|
||||
}
|
||||
@ -151,11 +147,7 @@ db_lookup_proc(db_expr_t addr)
|
||||
|
||||
decaddr = db_hex2dec(addr);
|
||||
if (decaddr != -1) {
|
||||
FOREACH_PROC_IN_SYSTEM(p) {
|
||||
if (p->p_pid == decaddr)
|
||||
return (p);
|
||||
}
|
||||
LIST_FOREACH(p, &zombproc, p_list) {
|
||||
LIST_FOREACH(p, PIDHASH(decaddr), p_hash) {
|
||||
if (p->p_pid == decaddr)
|
||||
return (p);
|
||||
}
|
||||
|
@ -447,13 +447,10 @@ exit1(struct thread *td, int rval, int signo)
|
||||
WITNESS_WARN(WARN_PANIC, NULL, "process (pid %d) exiting", p->p_pid);
|
||||
|
||||
/*
|
||||
* Move proc from allproc queue to zombproc.
|
||||
* Remove from allproc. It still sits in the hash.
|
||||
*/
|
||||
sx_xlock(&allproc_lock);
|
||||
sx_xlock(&zombproc_lock);
|
||||
LIST_REMOVE(p, p_list);
|
||||
LIST_INSERT_HEAD(&zombproc, p, p_list);
|
||||
sx_xunlock(&zombproc_lock);
|
||||
sx_xunlock(&allproc_lock);
|
||||
|
||||
sx_xlock(&proctree_lock);
|
||||
@ -903,9 +900,6 @@ proc_reap(struct thread *td, struct proc *p, int *status, int options)
|
||||
* Remove other references to this process to ensure we have an
|
||||
* exclusive reference.
|
||||
*/
|
||||
sx_xlock(&zombproc_lock);
|
||||
LIST_REMOVE(p, p_list); /* off zombproc */
|
||||
sx_xunlock(&zombproc_lock);
|
||||
sx_xlock(PIDHASHLOCK(p->p_pid));
|
||||
LIST_REMOVE(p, p_hash);
|
||||
sx_xunlock(PIDHASHLOCK(p->p_pid));
|
||||
|
@ -124,9 +124,7 @@ u_long pidhashlock;
|
||||
struct pgrphashhead *pgrphashtbl;
|
||||
u_long pgrphash;
|
||||
struct proclist allproc;
|
||||
struct proclist zombproc;
|
||||
struct sx __exclusive_cache_line allproc_lock;
|
||||
struct sx __exclusive_cache_line zombproc_lock;
|
||||
struct sx __exclusive_cache_line proctree_lock;
|
||||
struct mtx __exclusive_cache_line ppeers_lock;
|
||||
struct mtx __exclusive_cache_line procid_lock;
|
||||
@ -177,12 +175,10 @@ procinit(void)
|
||||
u_long i;
|
||||
|
||||
sx_init(&allproc_lock, "allproc");
|
||||
sx_init(&zombproc_lock, "zombproc");
|
||||
sx_init(&proctree_lock, "proctree");
|
||||
mtx_init(&ppeers_lock, "p_peers", NULL, MTX_DEF);
|
||||
mtx_init(&procid_lock, "procid", NULL, MTX_DEF);
|
||||
LIST_INIT(&allproc);
|
||||
LIST_INIT(&zombproc);
|
||||
pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash);
|
||||
pidhashlock = (pidhash + 1) / 64;
|
||||
if (pidhashlock > 0)
|
||||
|
@ -1256,17 +1256,11 @@ racctd(void)
|
||||
|
||||
sx_slock(&allproc_lock);
|
||||
|
||||
sx_slock(&zombproc_lock);
|
||||
LIST_FOREACH(p, &zombproc, p_list) {
|
||||
PROC_LOCK(p);
|
||||
racct_set(p, RACCT_PCTCPU, 0);
|
||||
PROC_UNLOCK(p);
|
||||
}
|
||||
sx_sunlock(&zombproc_lock);
|
||||
|
||||
FOREACH_PROC_IN_SYSTEM(p) {
|
||||
PROC_LOCK(p);
|
||||
if (p->p_state != PRS_NORMAL) {
|
||||
if (p->p_state == PRS_ZOMBIE)
|
||||
racct_set(p, RACCT_PCTCPU, 0);
|
||||
PROC_UNLOCK(p);
|
||||
continue;
|
||||
}
|
||||
|
@ -967,7 +967,6 @@ extern u_long pgrphash;
|
||||
|
||||
extern struct sx allproc_lock;
|
||||
extern int allproc_gen;
|
||||
extern struct sx zombproc_lock;
|
||||
extern struct sx proctree_lock;
|
||||
extern struct mtx ppeers_lock;
|
||||
extern struct mtx procid_lock;
|
||||
@ -985,7 +984,6 @@ LIST_HEAD(proclist, proc);
|
||||
TAILQ_HEAD(procqueue, proc);
|
||||
TAILQ_HEAD(threadqueue, thread);
|
||||
extern struct proclist allproc; /* List of all processes. */
|
||||
extern struct proclist zombproc; /* List of zombie processes. */
|
||||
extern struct proc *initproc, *pageproc; /* Process slots for init, pager. */
|
||||
|
||||
extern struct uma_zone *proc_zone;
|
||||
|
Loading…
Reference in New Issue
Block a user