pigs.c revision 128230
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 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if 0
35#ifndef lint
36static char sccsid[] = "@(#)pigs.c	8.2 (Berkeley) 9/23/93";
37#endif /* not lint */
38#endif
39
40#include <sys/cdefs.h>
41__FBSDID("$FreeBSD: head/usr.bin/systat/pigs.c 128230 2004-04-14 09:01:56Z bde $");
42
43/*
44 * Pigs display from Bill Reeves at Lucasfilm
45 */
46
47#include <sys/param.h>
48#include <sys/proc.h>
49#include <sys/sysctl.h>
50#include <sys/time.h>
51#include <sys/user.h>
52
53#include <curses.h>
54#include <math.h>
55#include <pwd.h>
56#include <stdlib.h>
57
58#include "extern.h"
59
60int compar(const void *, const void *);
61
62static int nproc;
63static struct p_times {
64	float pt_pctcpu;
65	struct kinfo_proc *pt_kp;
66} *pt;
67
68static long stime[CPUSTATES];
69static int    fscale;
70static double  lccpu;
71
72WINDOW *
73openpigs()
74{
75	return (subwin(stdscr, LINES-5-1, 0, 5, 0));
76}
77
78void
79closepigs(w)
80	WINDOW *w;
81{
82	if (w == NULL)
83		return;
84	wclear(w);
85	wrefresh(w);
86	delwin(w);
87}
88
89
90void
91showpigs()
92{
93	register int i, j, y, k;
94	float total;
95	int factor;
96	const char *uname, *pname;
97	char pidname[30];
98
99	if (pt == NULL)
100		return;
101	/* Accumulate the percent of cpu per user. */
102	total = 0.0;
103	for (i = 0; i <= nproc; i++) {
104		/* Accumulate the percentage. */
105		total += pt[i].pt_pctcpu;
106	}
107
108	if (total < 1.0)
109 		total = 1.0;
110	factor = 50.0/total;
111
112        qsort(pt, nproc + 1, sizeof (struct p_times), compar);
113	y = 1;
114	i = nproc + 1;
115	if (i > wnd->_maxy-1)
116		i = wnd->_maxy-1;
117	for (k = 0; i > 0 && pt[k].pt_pctcpu > 0.01; i--, y++, k++) {
118		if (pt[k].pt_kp == NULL) {
119			uname = "";
120			pname = "<idle>";
121		}
122		else {
123			uname = user_from_uid(pt[k].pt_kp->ki_uid, 0);
124			pname = pt[k].pt_kp->ki_comm;
125		}
126		wmove(wnd, y, 0);
127		wclrtoeol(wnd);
128		mvwaddstr(wnd, y, 0, uname);
129		snprintf(pidname, sizeof(pidname), "%10.10s", pname);
130		mvwaddstr(wnd, y, 9, pidname);
131		wmove(wnd, y, 20);
132		for (j = pt[k].pt_pctcpu*factor + 0.5; j > 0; j--)
133			waddch(wnd, 'X');
134	}
135	wmove(wnd, y, 0); wclrtobot(wnd);
136}
137
138int
139initpigs()
140{
141	fixpt_t ccpu;
142	size_t len;
143	int err;
144
145	len = sizeof(stime);
146	err = sysctlbyname("kern.cp_time", &stime, &len, NULL, 0);
147	if (err || len != sizeof(stime)) {
148		perror("kern.cp_time");
149		return (0);
150	}
151
152	len = sizeof(ccpu);
153	err = sysctlbyname("kern.ccpu", &ccpu, &len, NULL, 0);
154	if (err || len != sizeof(ccpu)) {
155		perror("kern.ccpu");
156		return (0);
157	}
158
159	len = sizeof(fscale);
160	err = sysctlbyname("kern.fscale", &fscale, &len, NULL, 0);
161	if (err || len != sizeof(fscale)) {
162		perror("kern.fscale");
163		return (0);
164	}
165
166	lccpu = log((double) ccpu / fscale);
167
168	return(1);
169}
170
171void
172fetchpigs()
173{
174	int i;
175	float ftime;
176	float *pctp;
177	struct kinfo_proc *kpp;
178	long c_time[CPUSTATES];
179	double t;
180	static int lastnproc = 0;
181	size_t len;
182	int err;
183
184	if ((kpp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc)) == NULL) {
185		error("%s", kvm_geterr(kd));
186		if (pt)
187			free(pt);
188		return;
189	}
190	if (nproc > lastnproc) {
191		free(pt);
192		if ((pt =
193		    malloc((nproc + 1) * sizeof(struct p_times))) == NULL) {
194			error("Out of memory");
195			die(0);
196		}
197	}
198	lastnproc = nproc;
199	/*
200	 * calculate %cpu for each proc
201	 */
202	for (i = 0; i < nproc; i++) {
203		pt[i].pt_kp = &kpp[i];
204		pctp = &pt[i].pt_pctcpu;
205		ftime = kpp[i].ki_swtime;
206		if (ftime == 0 || (kpp[i].ki_sflag & PS_INMEM) == 0)
207			*pctp = 0;
208		else
209			*pctp = ((double) kpp[i].ki_pctcpu /
210					fscale) / (1.0 - exp(ftime * lccpu));
211	}
212	/*
213	 * and for the imaginary "idle" process
214	 */
215	len = sizeof(c_time);
216	err = sysctlbyname("kern.cp_time", &c_time, &len, NULL, 0);
217	if (err || len != sizeof(c_time)) {
218		perror("kern.cp_time");
219		return;
220	}
221	t = 0;
222	for (i = 0; i < CPUSTATES; i++)
223		t += c_time[i] - stime[i];
224	if (t == 0.0)
225		t = 1.0;
226	pt[nproc].pt_kp = NULL;
227	pt[nproc].pt_pctcpu = (c_time[CP_IDLE] - stime[CP_IDLE]) / t;
228	for (i = 0; i < CPUSTATES; i++)
229		stime[i] = c_time[i];
230}
231
232void
233labelpigs()
234{
235	wmove(wnd, 0, 0);
236	wclrtoeol(wnd);
237	mvwaddstr(wnd, 0, 20,
238	    "/0   /10  /20  /30  /40  /50  /60  /70  /80  /90  /100");
239}
240
241int
242compar(a, b)
243	const void *a, *b;
244{
245	return (((const struct p_times *) a)->pt_pctcpu >
246		((const struct p_times *) b)->pt_pctcpu)? -1: 1;
247}
248