BSD 4_4_Lite1 release
[unix-history] / usr / src / usr.bin / systat / pigs.c
index 9b057c2..4c49494 100644 (file)
@@ -1,35 +1,71 @@
-/*
- * Copyright (c) 1980 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+/*-
+ * Copyright (c) 1980, 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)pigs.c     5.9 (Berkeley) %G%";
-#endif not lint
+static char sccsid[] = "@(#)pigs.c     8.2 (Berkeley) 9/23/93";
+#endif /* not lint */
 
 /*
  * Pigs display from Bill Reeves at Lucasfilm
  */
 
 
 /*
  * Pigs display from Bill Reeves at Lucasfilm
  */
 
-#include "systat.h"
+#include <sys/param.h>
+#include <sys/dkstat.h>
 #include <sys/dir.h>
 #include <sys/time.h>
 #include <sys/proc.h>
 #include <sys/dir.h>
 #include <sys/time.h>
 #include <sys/proc.h>
-#include <sys/kinfo.h>
-#include <sys/kinfo_proc.h>
+#include <sys/sysctl.h>
+
+#include <curses.h>
+#include <math.h>
+#include <nlist.h>
 #include <pwd.h>
 #include <pwd.h>
-#include <kvm.h>
+#include <stdlib.h>
+
+#include "extern.h"
+#include "systat.h"
 
 
-struct p_times {
-       float   pt_pctcpu;
-       struct  proc *pt_pp;
+int compar __P((const void *, const void *));
+
+static int nproc;
+static struct p_times {
+       float pt_pctcpu;
+       struct kinfo_proc *pt_kp;
 } *pt;
 } *pt;
-int    ptsize;
-int    nproc;
-int     fscale;
-double  lccpu;
 
 
+static long stime[CPUSTATES];
+static int     fscale;
+static double  lccpu;
 
 WINDOW *
 openpigs()
 
 WINDOW *
 openpigs()
@@ -37,6 +73,7 @@ openpigs()
        return (subwin(stdscr, LINES-5-1, 0, 5, 0));
 }
 
        return (subwin(stdscr, LINES-5-1, 0, 5, 0));
 }
 
+void
 closepigs(w)
        WINDOW *w;
 {
 closepigs(w)
        WINDOW *w;
 {
@@ -47,74 +84,43 @@ closepigs(w)
        delwin(w);
 }
 
        delwin(w);
 }
 
-int    maxind;
-int     factor;
-float   total;
-char    pidname[30];
-long   stime[CPUSTATES];
 
 
+void
 showpigs()
 {
 showpigs()
 {
-       register short auid;
-       register int i, j, y;
-       register float max;
-       register struct p_times *ptptr;
-       struct  p_times temppt;
+       register int i, j, y, k;
        struct  eproc *ep;
        struct  eproc *ep;
-       char *uname, *pname;
+       float total;
+       int factor;
+       char *uname, *pname, pidname[30];
 
        if (pt == NULL)
                return;
        /* Accumulate the percent of cpu per user. */
 
        if (pt == NULL)
                return;
        /* Accumulate the percent of cpu per user. */
-       ptptr = pt;
        total = 0.0;
        total = 0.0;
-       for (i = 0; i < nproc; i++) {
+       for (i = 0; i <= nproc; i++) {
                /* Accumulate the percentage. */
                /* Accumulate the percentage. */
-               total += ptptr->pt_pctcpu;
-               ptptr++;
+               total += pt[i].pt_pctcpu;
        }
 
        }
 
-       total += pt[nproc].pt_pctcpu;   /* idle "process" */
-
        if (total < 1.0)
        if (total < 1.0)
-               total = 1.0;
+               total = 1.0;
        factor = 50.0/total;
 
        factor = 50.0/total;
 
-       /* Find the top few by executing a "bubble pass" ten times. */
-       y = nproc + 1;
-       if (y > wnd->_maxy-1)
-               y = wnd->_maxy-1;
-       for (i = 0; i < y; i++) {
-               ptptr = &pt[i];
-               max = -10000.0;
-               maxind = i;
-               for (j = i; j < nproc + 1; j++) {
-                       if (ptptr->pt_pctcpu > max) {
-                               max = ptptr->pt_pctcpu;
-                               maxind = j;
-                       }
-                       ptptr++;
-               }
-               if (maxind != i) {
-                       temppt = pt[i];
-                       pt[i] = pt[maxind];
-                       pt[maxind] = temppt;
-               }
-       }
+        qsort(pt, nproc + 1, sizeof (struct p_times), compar);
        y = 1;
        y = 1;
-       ptptr = pt;
        i = nproc + 1;
        i = nproc + 1;
-       if (i > wnd->_maxy-1)
-               i = wnd->_maxy-1;
-       for (; i > 0 && ptptr->pt_pctcpu > 0.01; i--, y++, ptptr++) {
-               if (ptptr->pt_pp == NULL) {
+       if (i > wnd->maxy-1)
+               i = wnd->maxy-1;
+       for (k = 0; i > 0 && pt[k].pt_pctcpu > 0.01; i--, y++, k++) {
+               if (pt[k].pt_kp == NULL) {
                        uname = "";
                        pname = "<idle>";
                }
                else {
                        uname = "";
                        pname = "<idle>";
                }
                else {
-                       ep = kvm_geteproc(ptptr->pt_pp);
+                       ep = &pt[k].pt_kp->kp_eproc;
                        uname = (char *)user_from_uid(ep->e_ucred.cr_uid, 0);
                        uname = (char *)user_from_uid(ep->e_ucred.cr_uid, 0);
-                       pname = ptptr->pt_pp->p_comm;
+                       pname = pt[k].pt_kp->kp_proc.p_comm;
                }
                wmove(wnd, y, 0);
                wclrtoeol(wnd);
                }
                wmove(wnd, y, 0);
                wclrtoeol(wnd);
@@ -122,13 +128,13 @@ showpigs()
                sprintf(pidname, "%10.10s", pname, 0);
                mvwaddstr(wnd, y, 9, pidname);
                wmove(wnd, y, 20);
                sprintf(pidname, "%10.10s", pname, 0);
                mvwaddstr(wnd, y, 9, pidname);
                wmove(wnd, y, 20);
-               for (j = ptptr->pt_pctcpu*factor + 0.5; j > 0; j--)
+               for (j = pt[k].pt_pctcpu*factor + 0.5; j > 0; j--)
                        waddch(wnd, 'X');
        }
        wmove(wnd, y, 0); wclrtobot(wnd);
 }
 
                        waddch(wnd, 'X');
        }
        wmove(wnd, y, 0); wclrtobot(wnd);
 }
 
-static struct nlist nlst[] = {
+static struct nlist namelist[] = {
 #define X_FIRST                0
 #define X_CPTIME       0
        { "_cp_time" },
 #define X_FIRST                0
 #define X_CPTIME       0
        { "_cp_time" },
@@ -140,13 +146,17 @@ static struct nlist nlst[] = {
        { "" }
 };
 
        { "" }
 };
 
+int
 initpigs()
 {
        fixpt_t ccpu;
 
 initpigs()
 {
        fixpt_t ccpu;
 
-       if (nlst[X_FIRST].n_type == 0) {
-               kvm_nlist(nlst);
-               if (nlst[X_FIRST].n_type == 0) {
+       if (namelist[X_FIRST].n_type == 0) {
+               if (kvm_nlist(kd, namelist)) {
+                       nlisterr(namelist);
+                       return(0);
+               }
+               if (namelist[X_FIRST].n_type == 0) {
                        error("namelist failed");
                        return(0);
                }
                        error("namelist failed");
                        return(0);
                }
@@ -159,52 +169,51 @@ initpigs()
        return(1);
 }
 
        return(1);
 }
 
+void
 fetchpigs()
 {
        register int i;
 fetchpigs()
 {
        register int i;
-       register struct p_times *prt;
        register float time;
        register struct proc *pp;
        register float time;
        register struct proc *pp;
+       register float *pctp;
+       struct kinfo_proc *kpp;
        long ctime[CPUSTATES];
        double t;
        long ctime[CPUSTATES];
        double t;
+       static int lastnproc = 0;
 
 
-       if (nlst[X_FIRST].n_type == 0)
+       if (namelist[X_FIRST].n_type == 0)
                return;
                return;
-       kvm_freeprocs();        /* clear previous buffer */
-       if ((nproc = kvm_getprocs(KINFO_PROC_ALL, 0)) == -1) {
-               error("%s", kvm_geterr());
+       if ((kpp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc)) == NULL) {
+               error("%s", kvm_geterr(kd));
                if (pt)
                        free(pt);
                if (pt)
                        free(pt);
-               ptsize = 0;
                return;
        }
                return;
        }
-       /*
-        * The nproc + 1'th entry is for the imaginary "idle"
-        * process to which we attribute the unused part of the cpu
-        */
-       if ((nproc + 1) * sizeof (struct p_times) > ptsize) {
-               if (pt)
-                       free(pt);
-               ptsize = (nproc + 1) * sizeof (struct p_times);
-               if ((pt = (struct p_times *)malloc(ptsize)) == NULL) {
-                       error("out of memory");
-                       die();
+       if (nproc > lastnproc) {
+               free(pt);
+               if ((pt =
+                   malloc((nproc + 1) * sizeof(struct p_times))) == NULL) {
+                       error("Out of memory");
+                       die(0);
                }
        }
                }
        }
+       lastnproc = nproc;
        /*
         * calculate %cpu for each proc
         */
        /*
         * calculate %cpu for each proc
         */
-       for (prt = pt; (pp = kvm_nextproc()) != NULL; prt++) {
-               prt->pt_pp = pp;
-               time = pp->p_time;
-               if (time == 0 || (pp->p_flag & SLOAD) == 0)
-                       prt->pt_pctcpu = 0;
+       for (i = 0; i < nproc; i++) {
+               pt[i].pt_kp = &kpp[i];
+               pp = &kpp[i].kp_proc;
+               pctp = &pt[i].pt_pctcpu;
+               time = pp->p_swtime;
+               if (time == 0 || (pp->p_flag & P_INMEM) == 0)
+                       *pctp = 0;
                else
                else
-                       prt->pt_pctcpu = ((double) pp->p_pctcpu / 
+                       *pctp = ((double) pp->p_pctcpu / 
                                        fscale) / (1.0 - exp(time * lccpu));
        }
        /*
                                        fscale) / (1.0 - exp(time * lccpu));
        }
        /*
-        * and for the imaginary "idle" process, pt[nproc]
+        * and for the imaginary "idle" process
         */
        KREAD(NPTR(X_CPTIME), ctime, sizeof (ctime));
        t = 0;
         */
        KREAD(NPTR(X_CPTIME), ctime, sizeof (ctime));
        t = 0;
@@ -212,15 +221,25 @@ fetchpigs()
                t += ctime[i] - stime[i];
        if (t == 0.0)
                t = 1.0;
                t += ctime[i] - stime[i];
        if (t == 0.0)
                t = 1.0;
-       pt[nproc].pt_pp = NULL; 
+       pt[nproc].pt_kp = NULL;
        pt[nproc].pt_pctcpu = (ctime[CP_IDLE] - stime[CP_IDLE]) / t;
        for (i = 0; i < CPUSTATES; i++)
                stime[i] = ctime[i];
 }
 
        pt[nproc].pt_pctcpu = (ctime[CP_IDLE] - stime[CP_IDLE]) / t;
        for (i = 0; i < CPUSTATES; i++)
                stime[i] = ctime[i];
 }
 
+void
 labelpigs()
 {
 labelpigs()
 {
-       wmove(wnd, 0, 0); wclrtoeol(wnd);
+       wmove(wnd, 0, 0);
+       wclrtoeol(wnd);
        mvwaddstr(wnd, 0, 20,
            "/0   /10  /20  /30  /40  /50  /60  /70  /80  /90  /100");
 }
        mvwaddstr(wnd, 0, 20,
            "/0   /10  /20  /30  /40  /50  /60  /70  /80  /90  /100");
 }
+
+int
+compar(a, b)
+       const void *a, *b;
+{
+       return (((struct p_times *) a)->pt_pctcpu >
+               ((struct p_times *) b)->pt_pctcpu)? -1: 1;
+}