svn commit: r351572 - in head/sys: ddb kern sys

Mateusz Guzik mjg at FreeBSD.org
Wed Aug 28 16:18:25 UTC 2019


Author: mjg
Date: Wed Aug 28 16:18:23 2019
New Revision: 351572
URL: https://svnweb.freebsd.org/changeset/base/351572

Log:
  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

Modified:
  head/sys/ddb/db_ps.c
  head/sys/ddb/db_thread.c
  head/sys/kern/kern_exit.c
  head/sys/kern/kern_proc.c
  head/sys/kern/kern_racct.c
  head/sys/sys/proc.h

Modified: head/sys/ddb/db_ps.c
==============================================================================
--- head/sys/ddb/db_ps.c	Wed Aug 28 16:16:35 2019	(r351571)
+++ head/sys/ddb/db_ps.c	Wed Aug 28 16:18:23 2019	(r351572)
@@ -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;
 	}
 }
 

Modified: head/sys/ddb/db_thread.c
==============================================================================
--- head/sys/ddb/db_thread.c	Wed Aug 28 16:16:35 2019	(r351571)
+++ head/sys/ddb/db_thread.c	Wed Aug 28 16:18:23 2019	(r351572)
@@ -125,14 +125,10 @@ db_lookup_thread(db_expr_t addr, bool check_pid)
 	if (td != NULL)
 		return (td);
 	if (check_pid) {
-		FOREACH_PROC_IN_SYSTEM(p) {
+		LIST_FOREACH(p, PIDHASH(decaddr), p_hash) {
 			if (p->p_pid == decaddr)
 				return (FIRST_THREAD_IN_PROC(p));
 		}
-		LIST_FOREACH(p, &zombproc, p_list) {
-			if (p->p_pid == decaddr)
-				return (FIRST_THREAD_IN_PROC(p));
-		}
 	}
 	return ((struct thread *)addr);
 }
@@ -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);
 		}

Modified: head/sys/kern/kern_exit.c
==============================================================================
--- head/sys/kern/kern_exit.c	Wed Aug 28 16:16:35 2019	(r351571)
+++ head/sys/kern/kern_exit.c	Wed Aug 28 16:18:23 2019	(r351572)
@@ -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 *stat
 	 * 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));

Modified: head/sys/kern/kern_proc.c
==============================================================================
--- head/sys/kern/kern_proc.c	Wed Aug 28 16:16:35 2019	(r351571)
+++ head/sys/kern/kern_proc.c	Wed Aug 28 16:18:23 2019	(r351572)
@@ -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)

Modified: head/sys/kern/kern_racct.c
==============================================================================
--- head/sys/kern/kern_racct.c	Wed Aug 28 16:16:35 2019	(r351571)
+++ head/sys/kern/kern_racct.c	Wed Aug 28 16:18:23 2019	(r351572)
@@ -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;
 			}

Modified: head/sys/sys/proc.h
==============================================================================
--- head/sys/sys/proc.h	Wed Aug 28 16:16:35 2019	(r351571)
+++ head/sys/sys/proc.h	Wed Aug 28 16:18:23 2019	(r351572)
@@ -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;


More information about the svn-src-all mailing list