pigs.c revision 158160
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 3494610Sdwmalone#if 0 3594610Sdwmalone#ifndef lint 3694610Sdwmalonestatic char sccsid[] = "@(#)pigs.c 8.2 (Berkeley) 9/23/93"; 3794610Sdwmalone#endif /* not lint */ 3894610Sdwmalone#endif 3994610Sdwmalone 4087715Smarkm#include <sys/cdefs.h> 4187715Smarkm__FBSDID("$FreeBSD: head/usr.bin/systat/pigs.c 158160 2006-04-30 04:26:46Z bde $"); 4287715Smarkm 431590Srgrimes/* 441590Srgrimes * Pigs display from Bill Reeves at Lucasfilm 451590Srgrimes */ 461590Srgrimes 471590Srgrimes#include <sys/param.h> 48128230Sbde#include <sys/proc.h> 49128230Sbde#include <sys/sysctl.h> 501590Srgrimes#include <sys/time.h> 5111914Sphk#include <sys/user.h> 521590Srgrimes 531590Srgrimes#include <curses.h> 541590Srgrimes#include <math.h> 551590Srgrimes#include <pwd.h> 561590Srgrimes#include <stdlib.h> 571590Srgrimes 58145800Sdelphij#include "systat.h" 591590Srgrimes#include "extern.h" 601590Srgrimes 6192922Simpint compar(const void *, const void *); 621590Srgrimes 631590Srgrimesstatic int nproc; 641590Srgrimesstatic struct p_times { 651590Srgrimes float pt_pctcpu; 661590Srgrimes struct kinfo_proc *pt_kp; 671590Srgrimes} *pt; 681590Srgrimes 691590Srgrimesstatic long stime[CPUSTATES]; 7069493Sgallatinstatic int fscale; 711590Srgrimesstatic double lccpu; 721590Srgrimes 731590SrgrimesWINDOW * 741590Srgrimesopenpigs() 751590Srgrimes{ 76158160Sbde return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0)); 771590Srgrimes} 781590Srgrimes 791590Srgrimesvoid 801590Srgrimesclosepigs(w) 811590Srgrimes WINDOW *w; 821590Srgrimes{ 831590Srgrimes if (w == NULL) 841590Srgrimes return; 851590Srgrimes wclear(w); 861590Srgrimes wrefresh(w); 871590Srgrimes delwin(w); 881590Srgrimes} 891590Srgrimes 901590Srgrimes 911590Srgrimesvoid 921590Srgrimesshowpigs() 931590Srgrimes{ 941590Srgrimes register int i, j, y, k; 951590Srgrimes float total; 961590Srgrimes int factor; 9787715Smarkm const char *uname, *pname; 9887715Smarkm char pidname[30]; 991590Srgrimes 1001590Srgrimes if (pt == NULL) 1011590Srgrimes return; 1021590Srgrimes /* Accumulate the percent of cpu per user. */ 1031590Srgrimes total = 0.0; 1041590Srgrimes for (i = 0; i <= nproc; i++) { 1051590Srgrimes /* Accumulate the percentage. */ 1061590Srgrimes total += pt[i].pt_pctcpu; 1071590Srgrimes } 1081590Srgrimes 1091590Srgrimes if (total < 1.0) 1101590Srgrimes total = 1.0; 1111590Srgrimes factor = 50.0/total; 1121590Srgrimes 1131590Srgrimes qsort(pt, nproc + 1, sizeof (struct p_times), compar); 1141590Srgrimes y = 1; 1151590Srgrimes i = nproc + 1; 11650635Speter if (i > wnd->_maxy-1) 11750635Speter i = wnd->_maxy-1; 1181590Srgrimes for (k = 0; i > 0 && pt[k].pt_pctcpu > 0.01; i--, y++, k++) { 1191590Srgrimes if (pt[k].pt_kp == NULL) { 1201590Srgrimes uname = ""; 1211590Srgrimes pname = "<idle>"; 1221590Srgrimes } 1231590Srgrimes else { 12494610Sdwmalone uname = user_from_uid(pt[k].pt_kp->ki_uid, 0); 12569896Smckusick pname = pt[k].pt_kp->ki_comm; 1261590Srgrimes } 1271590Srgrimes wmove(wnd, y, 0); 1281590Srgrimes wclrtoeol(wnd); 1291590Srgrimes mvwaddstr(wnd, y, 0, uname); 13036789Simp snprintf(pidname, sizeof(pidname), "%10.10s", pname); 1311590Srgrimes mvwaddstr(wnd, y, 9, pidname); 1321590Srgrimes wmove(wnd, y, 20); 1331590Srgrimes for (j = pt[k].pt_pctcpu*factor + 0.5; j > 0; j--) 1341590Srgrimes waddch(wnd, 'X'); 1351590Srgrimes } 1361590Srgrimes wmove(wnd, y, 0); wclrtobot(wnd); 1371590Srgrimes} 1381590Srgrimes 1391590Srgrimesint 1401590Srgrimesinitpigs() 1411590Srgrimes{ 1421590Srgrimes fixpt_t ccpu; 14369142Srwatson size_t len; 14469142Srwatson int err; 1451590Srgrimes 14669142Srwatson len = sizeof(stime); 14769142Srwatson err = sysctlbyname("kern.cp_time", &stime, &len, NULL, 0); 14869142Srwatson if (err || len != sizeof(stime)) { 14969142Srwatson perror("kern.cp_time"); 15069142Srwatson return (0); 1511590Srgrimes } 15269142Srwatson 15369142Srwatson len = sizeof(ccpu); 15469142Srwatson err = sysctlbyname("kern.ccpu", &ccpu, &len, NULL, 0); 15569142Srwatson if (err || len != sizeof(ccpu)) { 15669142Srwatson perror("kern.ccpu"); 15769142Srwatson return (0); 15869142Srwatson } 15969142Srwatson 16069142Srwatson len = sizeof(fscale); 16169142Srwatson err = sysctlbyname("kern.fscale", &fscale, &len, NULL, 0); 16269142Srwatson if (err || len != sizeof(fscale)) { 16369142Srwatson perror("kern.fscale"); 16469142Srwatson return (0); 16569142Srwatson } 16669142Srwatson 1671590Srgrimes lccpu = log((double) ccpu / fscale); 1681590Srgrimes 1691590Srgrimes return(1); 1701590Srgrimes} 1711590Srgrimes 1721590Srgrimesvoid 1731590Srgrimesfetchpigs() 1741590Srgrimes{ 17587715Smarkm int i; 17687715Smarkm float ftime; 17787715Smarkm float *pctp; 1781590Srgrimes struct kinfo_proc *kpp; 17987715Smarkm long c_time[CPUSTATES]; 1801590Srgrimes double t; 1811590Srgrimes static int lastnproc = 0; 18269142Srwatson size_t len; 18369142Srwatson int err; 1841590Srgrimes 1851590Srgrimes if ((kpp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc)) == NULL) { 1861590Srgrimes error("%s", kvm_geterr(kd)); 1871590Srgrimes if (pt) 1881590Srgrimes free(pt); 1891590Srgrimes return; 1901590Srgrimes } 1911590Srgrimes if (nproc > lastnproc) { 1921590Srgrimes free(pt); 1931590Srgrimes if ((pt = 1941590Srgrimes malloc((nproc + 1) * sizeof(struct p_times))) == NULL) { 1951590Srgrimes error("Out of memory"); 1961590Srgrimes die(0); 1971590Srgrimes } 1981590Srgrimes } 1991590Srgrimes lastnproc = nproc; 2001590Srgrimes /* 2011590Srgrimes * calculate %cpu for each proc 2021590Srgrimes */ 2031590Srgrimes for (i = 0; i < nproc; i++) { 2041590Srgrimes pt[i].pt_kp = &kpp[i]; 2051590Srgrimes pctp = &pt[i].pt_pctcpu; 20687715Smarkm ftime = kpp[i].ki_swtime; 20787715Smarkm if (ftime == 0 || (kpp[i].ki_sflag & PS_INMEM) == 0) 2081590Srgrimes *pctp = 0; 2091590Srgrimes else 21069896Smckusick *pctp = ((double) kpp[i].ki_pctcpu / 21187715Smarkm fscale) / (1.0 - exp(ftime * lccpu)); 2121590Srgrimes } 2131590Srgrimes /* 2141590Srgrimes * and for the imaginary "idle" process 2151590Srgrimes */ 21687715Smarkm len = sizeof(c_time); 21787715Smarkm err = sysctlbyname("kern.cp_time", &c_time, &len, NULL, 0); 21887715Smarkm if (err || len != sizeof(c_time)) { 21969142Srwatson perror("kern.cp_time"); 22069142Srwatson return; 22169142Srwatson } 2221590Srgrimes t = 0; 2231590Srgrimes for (i = 0; i < CPUSTATES; i++) 22487715Smarkm t += c_time[i] - stime[i]; 2251590Srgrimes if (t == 0.0) 2261590Srgrimes t = 1.0; 2271590Srgrimes pt[nproc].pt_kp = NULL; 22887715Smarkm pt[nproc].pt_pctcpu = (c_time[CP_IDLE] - stime[CP_IDLE]) / t; 2291590Srgrimes for (i = 0; i < CPUSTATES; i++) 23087715Smarkm stime[i] = c_time[i]; 2311590Srgrimes} 2321590Srgrimes 2331590Srgrimesvoid 2341590Srgrimeslabelpigs() 2351590Srgrimes{ 2361590Srgrimes wmove(wnd, 0, 0); 2371590Srgrimes wclrtoeol(wnd); 2381590Srgrimes mvwaddstr(wnd, 0, 20, 2391590Srgrimes "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100"); 2401590Srgrimes} 2411590Srgrimes 2421590Srgrimesint 2431590Srgrimescompar(a, b) 2441590Srgrimes const void *a, *b; 2451590Srgrimes{ 24687715Smarkm return (((const struct p_times *) a)->pt_pctcpu > 24787715Smarkm ((const struct p_times *) b)->pt_pctcpu)? -1: 1; 2481590Srgrimes} 249