1 /*- 2 * Copyright (c) 1980, 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)pigs.c 8.1 (Berkeley) 06/06/93"; 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/sysctl.h> 22 23 #include <curses.h> 24 #include <math.h> 25 #include <nlist.h> 26 #include <pwd.h> 27 #include <stdlib.h> 28 29 #include "extern.h" 30 #include "systat.h" 31 32 int compar __P((const void *, const void *)); 33 34 static int nproc; 35 static struct p_times { 36 float pt_pctcpu; 37 struct kinfo_proc *pt_kp; 38 } *pt; 39 40 static long stime[CPUSTATES]; 41 static int fscale; 42 static double lccpu; 43 44 WINDOW * 45 openpigs() 46 { 47 return (subwin(stdscr, LINES-5-1, 0, 5, 0)); 48 } 49 50 void 51 closepigs(w) 52 WINDOW *w; 53 { 54 if (w == NULL) 55 return; 56 wclear(w); 57 wrefresh(w); 58 delwin(w); 59 } 60 61 62 void 63 showpigs() 64 { 65 register int i, j, y, k; 66 struct eproc *ep; 67 float total; 68 int factor; 69 char *uname, *pname, pidname[30]; 70 71 if (pt == NULL) 72 return; 73 /* Accumulate the percent of cpu per user. */ 74 total = 0.0; 75 for (i = 0; i <= nproc; i++) { 76 /* Accumulate the percentage. */ 77 total += pt[i].pt_pctcpu; 78 } 79 80 if (total < 1.0) 81 total = 1.0; 82 factor = 50.0/total; 83 84 qsort(pt, nproc + 1, sizeof (struct p_times), compar); 85 y = 1; 86 i = nproc + 1; 87 if (i > wnd->maxy-1) 88 i = wnd->maxy-1; 89 for (k = 0; i > 0 && pt[k].pt_pctcpu > 0.01; i--, y++, k++) { 90 if (pt[k].pt_kp == NULL) { 91 uname = ""; 92 pname = "<idle>"; 93 } 94 else { 95 ep = &pt[k].pt_kp->kp_eproc; 96 uname = (char *)user_from_uid(ep->e_ucred.cr_uid, 0); 97 pname = pt[k].pt_kp->kp_proc.p_comm; 98 } 99 wmove(wnd, y, 0); 100 wclrtoeol(wnd); 101 mvwaddstr(wnd, y, 0, uname); 102 sprintf(pidname, "%10.10s", pname, 0); 103 mvwaddstr(wnd, y, 9, pidname); 104 wmove(wnd, y, 20); 105 for (j = pt[k].pt_pctcpu*factor + 0.5; j > 0; j--) 106 waddch(wnd, 'X'); 107 } 108 wmove(wnd, y, 0); wclrtobot(wnd); 109 } 110 111 static struct nlist namelist[] = { 112 #define X_FIRST 0 113 #define X_CPTIME 0 114 { "_cp_time" }, 115 #define X_CCPU 1 116 { "_ccpu" }, 117 #define X_FSCALE 2 118 { "_fscale" }, 119 120 { "" } 121 }; 122 123 int 124 initpigs() 125 { 126 fixpt_t ccpu; 127 128 if (namelist[X_FIRST].n_type == 0) { 129 if (kvm_nlist(kd, namelist)) { 130 nlisterr(namelist); 131 return(0); 132 } 133 if (namelist[X_FIRST].n_type == 0) { 134 error("namelist failed"); 135 return(0); 136 } 137 } 138 KREAD(NPTR(X_CPTIME), stime, sizeof (stime)); 139 NREAD(X_CCPU, &ccpu, LONG); 140 NREAD(X_FSCALE, &fscale, LONG); 141 lccpu = log((double) ccpu / fscale); 142 143 return(1); 144 } 145 146 void 147 fetchpigs() 148 { 149 register int i; 150 register float time; 151 register struct proc *pp; 152 register float *pctp; 153 struct kinfo_proc *kpp; 154 long ctime[CPUSTATES]; 155 double t; 156 static int lastnproc = 0; 157 158 if (namelist[X_FIRST].n_type == 0) 159 return; 160 if ((kpp = kvm_getprocs(kd, KERN_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