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;
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to