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 * $FreeBSD$ 34 */ 35 36 #ifndef lint 37 static char sccsid[] = "@(#)pigs.c 8.2 (Berkeley) 9/23/93"; 38 #endif /* not lint */ 39 40 /* 41 * Pigs display from Bill Reeves at Lucasfilm 42 */ 43 44 #include <sys/param.h> 45 #include <sys/dkstat.h> 46 #include <sys/time.h> 47 #include <sys/proc.h> 48 #include <sys/user.h> 49 #include <sys/sysctl.h> 50 51 #include <curses.h> 52 #include <math.h> 53 #include <nlist.h> 54 #include <pwd.h> 55 #include <stdlib.h> 56 57 #include "extern.h" 58 #include "systat.h" 59 60 int compar __P((const void *, const void *)); 61 62 static int nproc; 63 static struct p_times { 64 float pt_pctcpu; 65 struct kinfo_proc *pt_kp; 66 } *pt; 67 68 static long stime[CPUSTATES]; 69 static long fscale; 70 static double lccpu; 71 72 WINDOW * 73 openpigs() 74 { 75 return (subwin(stdscr, LINES-5-1, 0, 5, 0)); 76 } 77 78 void 79 closepigs(w) 80 WINDOW *w; 81 { 82 if (w == NULL) 83 return; 84 wclear(w); 85 wrefresh(w); 86 delwin(w); 87 } 88 89 90 void 91 showpigs() 92 { 93 register int i, j, y, k; 94 struct eproc *ep; 95 float total; 96 int factor; 97 char *uname, *pname, pidname[30]; 98 99 if (pt == NULL) 100 return; 101 /* Accumulate the percent of cpu per user. */ 102 total = 0.0; 103 for (i = 0; i <= nproc; i++) { 104 /* Accumulate the percentage. */ 105 total += pt[i].pt_pctcpu; 106 } 107 108 if (total < 1.0) 109 total = 1.0; 110 factor = 50.0/total; 111 112 qsort(pt, nproc + 1, sizeof (struct p_times), compar); 113 y = 1; 114 i = nproc + 1; 115 if (i > wnd->_maxy-1) 116 i = wnd->_maxy-1; 117 for (k = 0; i > 0 && pt[k].pt_pctcpu > 0.01; i--, y++, k++) { 118 if (pt[k].pt_kp == NULL) { 119 uname = ""; 120 pname = "<idle>"; 121 } 122 else { 123 ep = &pt[k].pt_kp->kp_eproc; 124 uname = (char *)user_from_uid(ep->e_ucred.cr_uid, 0); 125 pname = pt[k].pt_kp->kp_proc.p_comm; 126 } 127 wmove(wnd, y, 0); 128 wclrtoeol(wnd); 129 mvwaddstr(wnd, y, 0, uname); 130 snprintf(pidname, sizeof(pidname), "%10.10s", pname); 131 mvwaddstr(wnd, y, 9, pidname); 132 wmove(wnd, y, 20); 133 for (j = pt[k].pt_pctcpu*factor + 0.5; j > 0; j--) 134 waddch(wnd, 'X'); 135 } 136 wmove(wnd, y, 0); wclrtobot(wnd); 137 } 138 139 int 140 initpigs() 141 { 142 fixpt_t ccpu; 143 size_t len; 144 int err; 145 146 len = sizeof(stime); 147 err = sysctlbyname("kern.cp_time", &stime, &len, NULL, 0); 148 if (err || len != sizeof(stime)) { 149 perror("kern.cp_time"); 150 return (0); 151 } 152 153 len = sizeof(ccpu); 154 err = sysctlbyname("kern.ccpu", &ccpu, &len, NULL, 0); 155 if (err || len != sizeof(ccpu)) { 156 perror("kern.ccpu"); 157 return (0); 158 } 159 160 len = sizeof(fscale); 161 err = sysctlbyname("kern.fscale", &fscale, &len, NULL, 0); 162 if (err || len != sizeof(fscale)) { 163 perror("kern.fscale"); 164 return (0); 165 } 166 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 size_t len; 184 int err; 185 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 len = sizeof(ctime); 219 err = sysctlbyname("kern.cp_time", &ctime, &len, NULL, 0); 220 if (err || len != sizeof(ctime)) { 221 perror("kern.cp_time"); 222 return; 223 } 224 t = 0; 225 for (i = 0; i < CPUSTATES; i++) 226 t += ctime[i] - stime[i]; 227 if (t == 0.0) 228 t = 1.0; 229 pt[nproc].pt_kp = NULL; 230 pt[nproc].pt_pctcpu = (ctime[CP_IDLE] - stime[CP_IDLE]) / t; 231 for (i = 0; i < CPUSTATES; i++) 232 stime[i] = ctime[i]; 233 } 234 235 void 236 labelpigs() 237 { 238 wmove(wnd, 0, 0); 239 wclrtoeol(wnd); 240 mvwaddstr(wnd, 0, 20, 241 "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100"); 242 } 243 244 int 245 compar(a, b) 246 const void *a, *b; 247 { 248 return (((struct p_times *) a)->pt_pctcpu > 249 ((struct p_times *) b)->pt_pctcpu)? -1: 1; 250 } 251