Index: sys/kern/kern_proc.c =================================================================== RCS file: /cvsroot/src/sys/kern/kern_proc.c,v retrieving revision 1.210 diff -u -r1.210 kern_proc.c --- sys/kern/kern_proc.c 11 Mar 2018 15:13:05 -0000 1.210 +++ sys/kern/kern_proc.c 12 Mar 2018 22:53:00 -0000 @@ -1674,12 +1674,16 @@ marker->p_flag = PK_MARKER; mutex_enter(proc_lock); - mmmbrains = false; - for (p = LIST_FIRST(&allproc);; p = next) { + /* + * Start with zombies to prevent reporting processes twice, in case they + * are dying and being moved from the list of alive processes to zombies. + */ + mmmbrains = true; + for (p = LIST_FIRST(&zombproc);; p = next) { if (p == NULL) { - if (!mmmbrains) { - p = LIST_FIRST(&zombproc); - mmmbrains = true; + if (mmmbrains) { + p = LIST_FIRST(&allproc); + mmmbrains = false; } if (p == NULL) break; @@ -1704,17 +1708,17 @@ } /* - * TODO - make more efficient (see notes below). - * do by session. + * Hande all the operations in one switch on the cost of + * algorithm complexity is on purpose. The win splitting this + * function into several similar copies makes maintenance burden + * burden, code grow and boost is neglible in practical systems. */ switch (op) { case KERN_PROC_PID: - /* could do this with just a lookup */ match = (p->p_pid == (pid_t)arg); break; case KERN_PROC_PGRP: - /* could do this by traversing pgrp */ match = (p->p_pgrp->pg_id == (pid_t)arg); break; @@ -1820,6 +1824,12 @@ rw_exit(&p->p_reflock); next = LIST_NEXT(p, p_list); } + + /* + * Short-circuit break quickly! + */ + if (op == KERN_PROC_PID) + break; } mutex_exit(proc_lock); @@ -1833,10 +1843,8 @@ needed += KERN_PROCSLOP; *oldlenp = needed; } - if (kbuf) - kmem_free(kbuf, sizeof(*kbuf)); - if (marker) - kmem_free(marker, sizeof(*marker)); + kmem_free(kbuf, sizeof(*kbuf)); + kmem_free(marker, sizeof(*marker)); sysctl_relock(); return 0; bah: @@ -1847,10 +1855,8 @@ cleanup: mutex_exit(proc_lock); out: - if (kbuf) - kmem_free(kbuf, sizeof(*kbuf)); - if (marker) - kmem_free(marker, sizeof(*marker)); + kmem_free(kbuf, sizeof(*kbuf)); + kmem_free(marker, sizeof(*marker)); sysctl_relock(); return error; }