1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 static char sccsid[] = "@(#)pigs.c 5.9 (Berkeley) 06/26/91"; 9 #endif not lint 10 11 /* 12 * Pigs display from Bill Reeves at Lucasfilm 13 */ 14 15 #include "systat.h" 16 #include <sys/dir.h> 17 #include <sys/time.h> 18 #include <sys/proc.h> 19 #include <sys/kinfo.h> 20 #include <sys/kinfo_proc.h> 21 #include <pwd.h> 22 #include <kvm.h> 23 24 struct p_times { 25 float pt_pctcpu; 26 struct proc *pt_pp; 27 } *pt; 28 int ptsize; 29 int nproc; 30 int fscale; 31 double lccpu; 32 33 34 WINDOW * 35 openpigs() 36 { 37 return (subwin(stdscr, LINES-5-1, 0, 5, 0)); 38 } 39 40 closepigs(w) 41 WINDOW *w; 42 { 43 if (w == NULL) 44 return; 45 wclear(w); 46 wrefresh(w); 47 delwin(w); 48 } 49 50 int maxind; 51 int factor; 52 float total; 53 char pidname[30]; 54 long stime[CPUSTATES]; 55 56 showpigs() 57 { 58 register short auid; 59 register int i, j, y; 60 register float max; 61 register struct p_times *ptptr; 62 struct p_times temppt; 63 struct eproc *ep; 64 char *uname, *pname; 65 66 if (pt == NULL) 67 return; 68 /* Accumulate the percent of cpu per user. */ 69 ptptr = pt; 70 total = 0.0; 71 for (i = 0; i < nproc; i++) { 72 /* Accumulate the percentage. */ 73 total += ptptr->pt_pctcpu; 74 ptptr++; 75 } 76 77 total += pt[nproc].pt_pctcpu; /* idle "process" */ 78 79 if (total < 1.0) 80 total = 1.0; 81 factor = 50.0/total; 82 83 /* Find the top few by executing a "bubble pass" ten times. */ 84 y = nproc + 1; 85 if (y > wnd->_maxy-1) 86 y = wnd->_maxy-1; 87 for (i = 0; i < y; i++) { 88 ptptr = &pt[i]; 89 max = -10000.0; 90 maxind = i; 91 for (j = i; j < nproc + 1; j++) { 92 if (ptptr->pt_pctcpu > max) { 93 max = ptptr->pt_pctcpu; 94 maxind = j; 95 } 96 ptptr++; 97 } 98 if (maxind != i) { 99 temppt = pt[i]; 100 pt[i] = pt[maxind]; 101 pt[maxind] = temppt; 102 } 103 } 104 y = 1; 105 ptptr = pt; 106 i = nproc + 1; 107 if (i > wnd->_maxy-1) 108 i = wnd->_maxy-1; 109 for (; i > 0 && ptptr->pt_pctcpu > 0.01; i--, y++, ptptr++) { 110 if (ptptr->pt_pp == NULL) { 111 uname = ""; 112 pname = "<idle>"; 113 } 114 else { 115 ep = kvm_geteproc(ptptr->pt_pp); 116 uname = (char *)user_from_uid(ep->e_ucred.cr_uid, 0); 117 pname = ptptr->pt_pp->p_comm; 118 } 119 wmove(wnd, y, 0); 120 wclrtoeol(wnd); 121 mvwaddstr(wnd, y, 0, uname); 122 sprintf(pidname, "%10.10s", pname, 0); 123 mvwaddstr(wnd, y, 9, pidname); 124 wmove(wnd, y, 20); 125 for (j = ptptr->pt_pctcpu*factor + 0.5; j > 0; j--) 126 waddch(wnd, 'X'); 127 } 128 wmove(wnd, y, 0); wclrtobot(wnd); 129 } 130 131 static struct nlist nlst[] = { 132 #define X_FIRST 0 133 #define X_CPTIME 0 134 { "_cp_time" }, 135 #define X_CCPU 1 136 { "_ccpu" }, 137 #define X_FSCALE 2 138 { "_fscale" }, 139 140 { "" } 141 }; 142 143 initpigs() 144 { 145 fixpt_t ccpu; 146 147 if (nlst[X_FIRST].n_type == 0) { 148 kvm_nlist(nlst); 149 if (nlst[X_FIRST].n_type == 0) { 150 error("namelist failed"); 151 return(0); 152 } 153 } 154 KREAD(NPTR(X_CPTIME), stime, sizeof (stime)); 155 NREAD(X_CCPU, &ccpu, LONG); 156 NREAD(X_FSCALE, &fscale, LONG); 157 lccpu = log((double) ccpu / fscale); 158 159 return(1); 160 } 161 162 fetchpigs() 163 { 164 register int i; 165 register struct p_times *prt; 166 register float time; 167 register struct proc *pp; 168 long ctime[CPUSTATES]; 169 double t; 170 171 if (nlst[X_FIRST].n_type == 0) 172 return; 173 kvm_freeprocs(); /* clear previous buffer */ 174 if ((nproc = kvm_getprocs(KINFO_PROC_ALL, 0)) == -1) { 175 error("%s", kvm_geterr()); 176 if (pt) 177 free(pt); 178 ptsize = 0; 179 return; 180 } 181 /* 182 * The nproc + 1'th entry is for the imaginary "idle" 183 * process to which we attribute the unused part of the cpu 184 */ 185 if ((nproc + 1) * sizeof (struct p_times) > ptsize) { 186 if (pt) 187 free(pt); 188 ptsize = (nproc + 1) * sizeof (struct p_times); 189 if ((pt = (struct p_times *)malloc(ptsize)) == NULL) { 190 error("out of memory"); 191 die(); 192 } 193 } 194 /* 195 * calculate %cpu for each proc 196 */ 197 for (prt = pt; (pp = kvm_nextproc()) != NULL; prt++) { 198 prt->pt_pp = pp; 199 time = pp->p_time; 200 if (time == 0 || (pp->p_flag & SLOAD) == 0) 201 prt->pt_pctcpu = 0; 202 else 203 prt->pt_pctcpu = ((double) pp->p_pctcpu / 204 fscale) / (1.0 - exp(time * lccpu)); 205 } 206 /* 207 * and for the imaginary "idle" process, pt[nproc] 208 */ 209 KREAD(NPTR(X_CPTIME), ctime, sizeof (ctime)); 210 t = 0; 211 for (i = 0; i < CPUSTATES; i++) 212 t += ctime[i] - stime[i]; 213 if (t == 0.0) 214 t = 1.0; 215 pt[nproc].pt_pp = NULL; 216 pt[nproc].pt_pctcpu = (ctime[CP_IDLE] - stime[CP_IDLE]) / t; 217 for (i = 0; i < CPUSTATES; i++) 218 stime[i] = ctime[i]; 219 } 220 221 labelpigs() 222 { 223 wmove(wnd, 0, 0); wclrtoeol(wnd); 224 mvwaddstr(wnd, 0, 20, 225 "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100"); 226 } 227