pigs.c revision 11914
11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1980, 1992, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 351590Srgrimesstatic char sccsid[] = "@(#)pigs.c 8.2 (Berkeley) 9/23/93"; 361590Srgrimes#endif /* not lint */ 371590Srgrimes 381590Srgrimes/* 391590Srgrimes * Pigs display from Bill Reeves at Lucasfilm 401590Srgrimes */ 411590Srgrimes 421590Srgrimes#include <sys/param.h> 431590Srgrimes#include <sys/dkstat.h> 441590Srgrimes#include <sys/dir.h> 451590Srgrimes#include <sys/time.h> 461590Srgrimes#include <sys/proc.h> 4711914Sphk#include <sys/user.h> 481590Srgrimes#include <sys/sysctl.h> 491590Srgrimes 501590Srgrimes#include <curses.h> 511590Srgrimes#include <math.h> 521590Srgrimes#include <nlist.h> 531590Srgrimes#include <pwd.h> 541590Srgrimes#include <stdlib.h> 551590Srgrimes 561590Srgrimes#include "extern.h" 571590Srgrimes#include "systat.h" 581590Srgrimes 591590Srgrimesint compar __P((const void *, const void *)); 601590Srgrimes 611590Srgrimesstatic int nproc; 621590Srgrimesstatic struct p_times { 631590Srgrimes float pt_pctcpu; 641590Srgrimes struct kinfo_proc *pt_kp; 651590Srgrimes} *pt; 661590Srgrimes 671590Srgrimesstatic long stime[CPUSTATES]; 681590Srgrimesstatic int fscale; 691590Srgrimesstatic double lccpu; 701590Srgrimes 711590SrgrimesWINDOW * 721590Srgrimesopenpigs() 731590Srgrimes{ 741590Srgrimes return (subwin(stdscr, LINES-5-1, 0, 5, 0)); 751590Srgrimes} 761590Srgrimes 771590Srgrimesvoid 781590Srgrimesclosepigs(w) 791590Srgrimes WINDOW *w; 801590Srgrimes{ 811590Srgrimes if (w == NULL) 821590Srgrimes return; 831590Srgrimes wclear(w); 841590Srgrimes wrefresh(w); 851590Srgrimes delwin(w); 861590Srgrimes} 871590Srgrimes 881590Srgrimes 891590Srgrimesvoid 901590Srgrimesshowpigs() 911590Srgrimes{ 921590Srgrimes register int i, j, y, k; 931590Srgrimes struct eproc *ep; 941590Srgrimes float total; 951590Srgrimes int factor; 961590Srgrimes char *uname, *pname, pidname[30]; 971590Srgrimes 981590Srgrimes if (pt == NULL) 991590Srgrimes return; 1001590Srgrimes /* Accumulate the percent of cpu per user. */ 1011590Srgrimes total = 0.0; 1021590Srgrimes for (i = 0; i <= nproc; i++) { 1031590Srgrimes /* Accumulate the percentage. */ 1041590Srgrimes total += pt[i].pt_pctcpu; 1051590Srgrimes } 1061590Srgrimes 1071590Srgrimes if (total < 1.0) 1081590Srgrimes total = 1.0; 1091590Srgrimes factor = 50.0/total; 1101590Srgrimes 1111590Srgrimes qsort(pt, nproc + 1, sizeof (struct p_times), compar); 1121590Srgrimes y = 1; 1131590Srgrimes i = nproc + 1; 1141590Srgrimes if (i > wnd->maxy-1) 1151590Srgrimes i = wnd->maxy-1; 1161590Srgrimes for (k = 0; i > 0 && pt[k].pt_pctcpu > 0.01; i--, y++, k++) { 1171590Srgrimes if (pt[k].pt_kp == NULL) { 1181590Srgrimes uname = ""; 1191590Srgrimes pname = "<idle>"; 1201590Srgrimes } 1211590Srgrimes else { 1221590Srgrimes ep = &pt[k].pt_kp->kp_eproc; 1231590Srgrimes uname = (char *)user_from_uid(ep->e_ucred.cr_uid, 0); 1241590Srgrimes pname = pt[k].pt_kp->kp_proc.p_comm; 1251590Srgrimes } 1261590Srgrimes wmove(wnd, y, 0); 1271590Srgrimes wclrtoeol(wnd); 1281590Srgrimes mvwaddstr(wnd, y, 0, uname); 1291590Srgrimes sprintf(pidname, "%10.10s", pname, 0); 1301590Srgrimes mvwaddstr(wnd, y, 9, pidname); 1311590Srgrimes wmove(wnd, y, 20); 1321590Srgrimes for (j = pt[k].pt_pctcpu*factor + 0.5; j > 0; j--) 1331590Srgrimes waddch(wnd, 'X'); 1341590Srgrimes } 1351590Srgrimes wmove(wnd, y, 0); wclrtobot(wnd); 1361590Srgrimes} 1371590Srgrimes 1381590Srgrimesstatic struct nlist namelist[] = { 1391590Srgrimes#define X_FIRST 0 1401590Srgrimes#define X_CPTIME 0 1411590Srgrimes { "_cp_time" }, 1421590Srgrimes#define X_CCPU 1 1431590Srgrimes { "_ccpu" }, 1441590Srgrimes#define X_FSCALE 2 1451590Srgrimes { "_fscale" }, 1461590Srgrimes 1471590Srgrimes { "" } 1481590Srgrimes}; 1491590Srgrimes 1501590Srgrimesint 1511590Srgrimesinitpigs() 1521590Srgrimes{ 1531590Srgrimes fixpt_t ccpu; 1541590Srgrimes 1551590Srgrimes if (namelist[X_FIRST].n_type == 0) { 1561590Srgrimes if (kvm_nlist(kd, namelist)) { 1571590Srgrimes nlisterr(namelist); 1581590Srgrimes return(0); 1591590Srgrimes } 1601590Srgrimes if (namelist[X_FIRST].n_type == 0) { 1611590Srgrimes error("namelist failed"); 1621590Srgrimes return(0); 1631590Srgrimes } 1641590Srgrimes } 1651590Srgrimes KREAD(NPTR(X_CPTIME), stime, sizeof (stime)); 1661590Srgrimes NREAD(X_CCPU, &ccpu, LONG); 1671590Srgrimes NREAD(X_FSCALE, &fscale, LONG); 1681590Srgrimes lccpu = log((double) ccpu / fscale); 1691590Srgrimes 1701590Srgrimes return(1); 1711590Srgrimes} 1721590Srgrimes 1731590Srgrimesvoid 1741590Srgrimesfetchpigs() 1751590Srgrimes{ 1761590Srgrimes register int i; 1771590Srgrimes register float time; 1781590Srgrimes register struct proc *pp; 1791590Srgrimes register float *pctp; 1801590Srgrimes struct kinfo_proc *kpp; 1811590Srgrimes long ctime[CPUSTATES]; 1821590Srgrimes double t; 1831590Srgrimes static int lastnproc = 0; 1841590Srgrimes 1851590Srgrimes if (namelist[X_FIRST].n_type == 0) 1861590Srgrimes return; 1871590Srgrimes if ((kpp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc)) == NULL) { 1881590Srgrimes error("%s", kvm_geterr(kd)); 1891590Srgrimes if (pt) 1901590Srgrimes free(pt); 1911590Srgrimes return; 1921590Srgrimes } 1931590Srgrimes if (nproc > lastnproc) { 1941590Srgrimes free(pt); 1951590Srgrimes if ((pt = 1961590Srgrimes malloc((nproc + 1) * sizeof(struct p_times))) == NULL) { 1971590Srgrimes error("Out of memory"); 1981590Srgrimes die(0); 1991590Srgrimes } 2001590Srgrimes } 2011590Srgrimes lastnproc = nproc; 2021590Srgrimes /* 2031590Srgrimes * calculate %cpu for each proc 2041590Srgrimes */ 2051590Srgrimes for (i = 0; i < nproc; i++) { 2061590Srgrimes pt[i].pt_kp = &kpp[i]; 2071590Srgrimes pp = &kpp[i].kp_proc; 2081590Srgrimes pctp = &pt[i].pt_pctcpu; 2091590Srgrimes time = pp->p_swtime; 2101590Srgrimes if (time == 0 || (pp->p_flag & P_INMEM) == 0) 2111590Srgrimes *pctp = 0; 2121590Srgrimes else 2138874Srgrimes *pctp = ((double) pp->p_pctcpu / 2141590Srgrimes fscale) / (1.0 - exp(time * lccpu)); 2151590Srgrimes } 2161590Srgrimes /* 2171590Srgrimes * and for the imaginary "idle" process 2181590Srgrimes */ 2191590Srgrimes KREAD(NPTR(X_CPTIME), ctime, sizeof (ctime)); 2201590Srgrimes t = 0; 2211590Srgrimes for (i = 0; i < CPUSTATES; i++) 2221590Srgrimes t += ctime[i] - stime[i]; 2231590Srgrimes if (t == 0.0) 2241590Srgrimes t = 1.0; 2251590Srgrimes pt[nproc].pt_kp = NULL; 2261590Srgrimes pt[nproc].pt_pctcpu = (ctime[CP_IDLE] - stime[CP_IDLE]) / t; 2271590Srgrimes for (i = 0; i < CPUSTATES; i++) 2281590Srgrimes stime[i] = ctime[i]; 2291590Srgrimes} 2301590Srgrimes 2311590Srgrimesvoid 2321590Srgrimeslabelpigs() 2331590Srgrimes{ 2341590Srgrimes wmove(wnd, 0, 0); 2351590Srgrimes wclrtoeol(wnd); 2361590Srgrimes mvwaddstr(wnd, 0, 20, 2371590Srgrimes "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100"); 2381590Srgrimes} 2391590Srgrimes 2401590Srgrimesint 2411590Srgrimescompar(a, b) 2421590Srgrimes const void *a, *b; 2431590Srgrimes{ 2441590Srgrimes return (((struct p_times *) a)->pt_pctcpu > 2451590Srgrimes ((struct p_times *) b)->pt_pctcpu)? -1: 1; 2461590Srgrimes} 247