xref: /freebsd/usr.bin/systat/pigs.c (revision aa0a1e58)
1 /*-
2  * Copyright (c) 1980, 1992, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 4. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #if 0
31 #ifndef lint
32 static char sccsid[] = "@(#)pigs.c	8.2 (Berkeley) 9/23/93";
33 #endif /* not lint */
34 #endif
35 
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38 
39 /*
40  * Pigs display from Bill Reeves at Lucasfilm
41  */
42 
43 #include <sys/param.h>
44 #include <sys/proc.h>
45 #include <sys/sysctl.h>
46 #include <sys/time.h>
47 #include <sys/user.h>
48 
49 #include <curses.h>
50 #include <math.h>
51 #include <pwd.h>
52 #include <stdlib.h>
53 
54 #include "systat.h"
55 #include "extern.h"
56 
57 int compar(const void *, const void *);
58 
59 static int nproc;
60 static struct p_times {
61 	float pt_pctcpu;
62 	struct kinfo_proc *pt_kp;
63 } *pt;
64 
65 static int    fscale;
66 static double  lccpu;
67 
68 WINDOW *
69 openpigs(void)
70 {
71 	return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
72 }
73 
74 void
75 closepigs(WINDOW *w)
76 {
77 	if (w == NULL)
78 		return;
79 	wclear(w);
80 	wrefresh(w);
81 	delwin(w);
82 }
83 
84 
85 void
86 showpigs(void)
87 {
88 	int i, j, y, k;
89 	const char *uname, *pname;
90 	char pidname[30];
91 
92 	if (pt == NULL)
93 		return;
94 
95 	qsort(pt, nproc, sizeof (struct p_times), compar);
96 	y = 1;
97 	i = nproc;
98 	if (i > wnd->_maxy-1)
99 		i = wnd->_maxy-1;
100 	for (k = 0; i > 0 && pt[k].pt_pctcpu > 0.01; i--, y++, k++) {
101 		uname = user_from_uid(pt[k].pt_kp->ki_uid, 0);
102 		pname = pt[k].pt_kp->ki_comm;
103 		wmove(wnd, y, 0);
104 		wclrtoeol(wnd);
105 		mvwaddstr(wnd, y, 0, uname);
106 		snprintf(pidname, sizeof(pidname), "%10.10s", pname);
107 		mvwaddstr(wnd, y, 9, pidname);
108 		wmove(wnd, y, 20);
109 		for (j = pt[k].pt_pctcpu * 50 + 0.5; j > 0; j--)
110 			waddch(wnd, 'X');
111 	}
112 	wmove(wnd, y, 0); wclrtobot(wnd);
113 }
114 
115 int
116 initpigs(void)
117 {
118 	fixpt_t ccpu;
119 	size_t len;
120 	int err;
121 
122 	len = sizeof(ccpu);
123 	err = sysctlbyname("kern.ccpu", &ccpu, &len, NULL, 0);
124 	if (err || len != sizeof(ccpu)) {
125 		perror("kern.ccpu");
126 		return (0);
127 	}
128 
129 	len = sizeof(fscale);
130 	err = sysctlbyname("kern.fscale", &fscale, &len, NULL, 0);
131 	if (err || len != sizeof(fscale)) {
132 		perror("kern.fscale");
133 		return (0);
134 	}
135 
136 	lccpu = log((double) ccpu / fscale);
137 
138 	return(1);
139 }
140 
141 void
142 fetchpigs(void)
143 {
144 	int i;
145 	float ftime;
146 	float *pctp;
147 	struct kinfo_proc *kpp;
148 	static int lastnproc = 0;
149 
150 	if ((kpp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc)) == NULL) {
151 		error("%s", kvm_geterr(kd));
152 		if (pt)
153 			free(pt);
154 		return;
155 	}
156 	if (nproc > lastnproc) {
157 		free(pt);
158 		if ((pt =
159 		    malloc(nproc * sizeof(struct p_times))) == NULL) {
160 			error("Out of memory");
161 			die(0);
162 		}
163 	}
164 	lastnproc = nproc;
165 	/*
166 	 * calculate %cpu for each proc
167 	 */
168 	for (i = 0; i < nproc; i++) {
169 		pt[i].pt_kp = &kpp[i];
170 		pctp = &pt[i].pt_pctcpu;
171 		ftime = kpp[i].ki_swtime;
172 		if (ftime == 0 || (kpp[i].ki_flag & P_INMEM) == 0)
173 			*pctp = 0;
174 		else
175 			*pctp = ((double) kpp[i].ki_pctcpu /
176 					fscale) / (1.0 - exp(ftime * lccpu));
177 	}
178 }
179 
180 void
181 labelpigs(void)
182 {
183 	wmove(wnd, 0, 0);
184 	wclrtoeol(wnd);
185 	mvwaddstr(wnd, 0, 20,
186 	    "/0%  /10  /20  /30  /40  /50  /60  /70  /80  /90  /100");
187 }
188 
189 int
190 compar(const void *a, const void *b)
191 {
192 	return (((const struct p_times *) a)->pt_pctcpu >
193 		((const struct p_times *) b)->pt_pctcpu)? -1: 1;
194 }
195