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