aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMateusz Guzik <mjg@FreeBSD.org>2019-08-28 16:18:23 +0000
committerMateusz Guzik <mjg@FreeBSD.org>2019-08-28 16:18:23 +0000
commit88cc62e5a53bb1b65416bd4a40e6b6c2981fcc38 (patch)
tree2c9882c9d0e81f093d0d8874379ecf24fddf4784
parentb5d239cb970f97e96deed8bcde7d689b61e47bcf (diff)
downloadsrc-88cc62e5a53bb1b65416bd4a40e6b6c2981fcc38.tar.gz
src-88cc62e5a53bb1b65416bd4a40e6b6c2981fcc38.zip
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
Notes
Notes: svn path=/head/; revision=351572
-rw-r--r--sys/ddb/db_ps.c254
-rw-r--r--sys/ddb/db_thread.c12
-rw-r--r--sys/kern/kern_exit.c8
-rw-r--r--sys/kern/kern_proc.c4
-rw-r--r--sys/kern/kern_racct.c10
-rw-r--r--sys/sys/proc.h2
6 files changed, 138 insertions, 152 deletions
diff --git a/sys/ddb/db_ps.c b/sys/ddb/db_ps.c
index 6eda4a9f7202..3c2ffa863324 100644
--- a/sys/ddb/db_ps.c
+++ b/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;
+ }
+}
+
+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;
+
+ 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);
+ 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 (TD_AWAITING_INTR(td))
- 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 (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");
- }
- FOREACH_THREAD_IN_PROC(p, td) {
- dumpthread(p, td, p->p_flag & P_HADTHREADS);
- if (db_pager_quit)
- break;
+ 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);
}
-
- 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;
}
}
diff --git a/sys/ddb/db_thread.c b/sys/ddb/db_thread.c
index 7d9899b2685c..780301a22106 100644
--- a/sys/ddb/db_thread.c
+++ b/sys/ddb/db_thread.c
@@ -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);
}
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index eb9c7d4c1075..dd227391e5e4 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -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));
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index d7b0e5ebed34..c2aab78a10fd 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -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)
diff --git a/sys/kern/kern_racct.c b/sys/kern/kern_racct.c
index a25d7fa8da52..fb962a411d31 100644
--- a/sys/kern/kern_racct.c
+++ b/sys/kern/kern_racct.c
@@ -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;
}
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 09b318320ca4..8cecf950ebe4 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -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;