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