1 /*- 2 * Copyright (c) 1980, 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 static char sccsid[] = "@(#)pigs.c 8.2 (Berkeley) 9/23/93"; 36 #endif /* not lint */ 37 38 /* 39 * Pigs display from Bill Reeves at Lucasfilm 40 */ 41 42 #include <sys/param.h> 43 #include <sys/dkstat.h> 44 #include <sys/dir.h> 45 #include <sys/time.h> 46 #include <sys/proc.h> 47 #include <sys/sysctl.h> 48 49 #include <curses.h> 50 #include <math.h> 51 #include <nlist.h> 52 #include <pwd.h> 53 #include <stdlib.h> 54 55 #include "extern.h" 56 #include "systat.h" 57 58 int compar __P((const void *, const void *)); 59 60 static int nproc; 61 static struct p_times { 62 float pt_pctcpu; 63 struct kinfo_proc *pt_kp; 64 } *pt; 65 66 static long stime[CPUSTATES]; 67 static int fscale; 68 static double lccpu; 69 70 WINDOW * 71 openpigs() 72 { 73 return (subwin(stdscr, LINES-5-1, 0, 5, 0)); 74 } 75 76 void 77 closepigs(w) 78 WINDOW *w; 79 { 80 if (w == NULL) 81 return; 82 wclear(w); 83 wrefresh(w); 84 delwin(w); 85 } 86 87 88 void 89 showpigs() 90 { 91 register int i, j, y, k; 92 struct eproc *ep; 93 float total; 94 int factor; 95 char *uname, *pname, pidname[30]; 96 97 if (pt == NULL) 98 return; 99 /* Accumulate the percent of cpu per user. */ 100 total = 0.0; 101 for (i = 0; i <= nproc; i++) { 102 /* Accumulate the percentage. */ 103 total += pt[i].pt_pctcpu; 104 } 105 106 if (total < 1.0) 107 total = 1.0; 108 factor = 50.0/total; 109 110 qsort(pt, nproc + 1, sizeof (struct p_times), compar); 111 y = 1; 112 i = nproc + 1; 113 if (i > wnd->maxy-1) 114 i = wnd->maxy-1; 115 for (k = 0; i > 0 && pt[k].pt_pctcpu > 0.01; i--, y++, k++) { 116 if (pt[k].pt_kp == NULL) { 117 uname = ""; 118 pname = "<idle>"; 119 } 120 else { 121 ep = &pt[k].pt_kp->kp_eproc; 122 uname = (char *)user_from_uid(ep->e_ucred.cr_uid, 0); 123 pname = pt[k].pt_kp->kp_proc.p_comm; 124 } 125 wmove(wnd, y, 0); 126 wclrtoeol(wnd); 127 mvwaddstr(wnd, y, 0, uname); 128 sprintf(pidname, "%10.10s", pname, 0); 129 mvwaddstr(wnd, y, 9, pidname); 130 wmove(wnd, y, 20); 131 for (j = pt[k].pt_pctcpu*factor + 0.5; j > 0; j--) 132 waddch(wnd, 'X'); 133 } 134 wmove(wnd, y, 0); wclrtobot(wnd); 135 } 136 137 static struct nlist namelist[] = { 138 #define X_FIRST 0 139 #define X_CPTIME 0 140 { "_cp_time" }, 141 #define X_CCPU 1 142 { "_ccpu" }, 143 #define X_FSCALE 2 144 { "_fscale" }, 145 146 { "" } 147 }; 148 149 int 150 initpigs() 151 { 152 fixpt_t ccpu; 153 154 if (namelist[X_FIRST].n_type == 0) { 155 if (kvm_nlist(kd, namelist)) { 156 nlisterr(namelist); 157 return(0); 158 } 159 if (namelist[X_FIRST].n_type == 0) { 160 error("namelist failed"); 161 return(0); 162 } 163 } 164 KREAD(NPTR(X_CPTIME), stime, sizeof (stime)); 165 NREAD(X_CCPU, &ccpu, LONG); 166 NREAD(X_FSCALE, &fscale, LONG); 167 lccpu = log((double) ccpu / fscale); 168 169 return(1); 170 } 171 172 void 173 fetchpigs() 174 { 175 register int i; 176 register float time; 177 register struct proc *pp; 178 register float *pctp; 179 struct kinfo_proc *kpp; 180 long ctime[CPUSTATES]; 181 double t; 182 static int lastnproc = 0; 183 184 if (namelist[X_FIRST].n_type == 0) 185 return; 186 if ((kpp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc)) == NULL) { 187 error("%s", kvm_geterr(kd)); 188 if (pt) 189 free(pt); 190 return; 191 } 192 if (nproc > lastnproc) { 193 free(pt); 194 if ((pt = 195 malloc((nproc + 1) * sizeof(struct p_times))) == NULL) { 196 error("Out of memory"); 197 die(0); 198 } 199 } 200 lastnproc = nproc; 201 /* 202 * calculate %cpu for each proc 203 */ 204 for (i = 0; i < nproc; i++) { 205 pt[i].pt_kp = &kpp[i]; 206 pp = &kpp[i].kp_proc; 207 pctp = &pt[i].pt_pctcpu; 208 time = pp->p_swtime; 209 if (time == 0 || (pp->p_flag & P_INMEM) == 0) 210 *pctp = 0; 211 else 212 *pctp = ((double) pp->p_pctcpu / 213 fscale) / (1.0 - exp(time * lccpu)); 214 } 215 /* 216 * and for the imaginary "idle" process 217 */ 218 KREAD(NPTR(X_CPTIME), ctime, sizeof (ctime)); 219 t = 0; 220 for (i = 0; i < CPUSTATES; i++) 221 t += ctime[i] - stime[i]; 222 if (t == 0.0) 223 t = 1.0; 224 pt[nproc].pt_kp = NULL; 225 pt[nproc].pt_pctcpu = (ctime[CP_IDLE] - stime[CP_IDLE]) / t; 226 for (i = 0; i < CPUSTATES; i++) 227 stime[i] = ctime[i]; 228 } 229 230 void 231 labelpigs() 232 { 233 wmove(wnd, 0, 0); 234 wclrtoeol(wnd); 235 mvwaddstr(wnd, 0, 20, 236 "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100"); 237 } 238 239 int 240 compar(a, b) 241 const void *a, *b; 242 { 243 return (((struct p_times *) a)->pt_pctcpu > 244 ((struct p_times *) b)->pt_pctcpu)? -1: 1; 245 } 246