pigs.c revision 145800
1251881Speter/*-
2251881Speter * Copyright (c) 1980, 1992, 1993
3251881Speter *	The Regents of the University of California.  All rights reserved.
4251881Speter *
5251881Speter * Redistribution and use in source and binary forms, with or without
6251881Speter * modification, are permitted provided that the following conditions
7251881Speter * are met:
8251881Speter * 1. Redistributions of source code must retain the above copyright
9251881Speter *    notice, this list of conditions and the following disclaimer.
10251881Speter * 2. Redistributions in binary form must reproduce the above copyright
11251881Speter *    notice, this list of conditions and the following disclaimer in the
12251881Speter *    documentation and/or other materials provided with the distribution.
13251881Speter * 3. All advertising materials mentioning features or use of this software
14251881Speter *    must display the following acknowledgement:
15251881Speter *	This product includes software developed by the University of
16251881Speter *	California, Berkeley and its contributors.
17251881Speter * 4. Neither the name of the University nor the names of its contributors
18251881Speter *    may be used to endorse or promote products derived from this software
19251881Speter *    without specific prior written permission.
20251881Speter *
21251881Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22251881Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23251881Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24251881Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25251881Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26251881Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27251881Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28251881Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29251881Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30251881Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31251881Speter * SUCH DAMAGE.
32251881Speter */
33251881Speter
34251881Speter#if 0
35251881Speter#ifndef lint
36251881Speterstatic char sccsid[] = "@(#)pigs.c	8.2 (Berkeley) 9/23/93";
37251881Speter#endif /* not lint */
38251881Speter#endif
39251881Speter
40251881Speter#include <sys/cdefs.h>
41251881Speter__FBSDID("$FreeBSD: head/usr.bin/systat/pigs.c 145800 2005-05-02 10:50:10Z delphij $");
42251881Speter
43251881Speter/*
44251881Speter * Pigs display from Bill Reeves at Lucasfilm
45251881Speter */
46251881Speter
47251881Speter#include <sys/param.h>
48251881Speter#include <sys/proc.h>
49251881Speter#include <sys/sysctl.h>
50251881Speter#include <sys/time.h>
51251881Speter#include <sys/user.h>
52251881Speter
53251881Speter#include <curses.h>
54251881Speter#include <math.h>
55251881Speter#include <pwd.h>
56251881Speter#include <stdlib.h>
57251881Speter
58251881Speter#include "systat.h"
59251881Speter#include "extern.h"
60251881Speter
61251881Speterint compar(const void *, const void *);
62251881Speter
63251881Speterstatic int nproc;
64251881Speterstatic struct p_times {
65251881Speter	float pt_pctcpu;
66251881Speter	struct kinfo_proc *pt_kp;
67251881Speter} *pt;
68251881Speter
69251881Speterstatic long stime[CPUSTATES];
70251881Speterstatic int    fscale;
71251881Speterstatic double  lccpu;
72251881Speter
73251881SpeterWINDOW *
74251881Speteropenpigs()
75251881Speter{
76251881Speter	return (subwin(stdscr, LINES-5-1, 0, 5, 0));
77251881Speter}
78251881Speter
79251881Spetervoid
80251881Speterclosepigs(w)
81251881Speter	WINDOW *w;
82251881Speter{
83251881Speter	if (w == NULL)
84251881Speter		return;
85251881Speter	wclear(w);
86251881Speter	wrefresh(w);
87251881Speter	delwin(w);
88251881Speter}
89251881Speter
90251881Speter
91251881Spetervoid
92251881Spetershowpigs()
93251881Speter{
94251881Speter	register int i, j, y, k;
95251881Speter	float total;
96251881Speter	int factor;
97251881Speter	const char *uname, *pname;
98251881Speter	char pidname[30];
99251881Speter
100251881Speter	if (pt == NULL)
101251881Speter		return;
102251881Speter	/* Accumulate the percent of cpu per user. */
103251881Speter	total = 0.0;
104251881Speter	for (i = 0; i <= nproc; i++) {
105251881Speter		/* Accumulate the percentage. */
106251881Speter		total += pt[i].pt_pctcpu;
107251881Speter	}
108251881Speter
109251881Speter	if (total < 1.0)
110251881Speter 		total = 1.0;
111251881Speter	factor = 50.0/total;
112251881Speter
113251881Speter        qsort(pt, nproc + 1, sizeof (struct p_times), compar);
114251881Speter	y = 1;
115251881Speter	i = nproc + 1;
116251881Speter	if (i > wnd->_maxy-1)
117251881Speter		i = wnd->_maxy-1;
118251881Speter	for (k = 0; i > 0 && pt[k].pt_pctcpu > 0.01; i--, y++, k++) {
119251881Speter		if (pt[k].pt_kp == NULL) {
120251881Speter			uname = "";
121251881Speter			pname = "<idle>";
122251881Speter		}
123251881Speter		else {
124251881Speter			uname = user_from_uid(pt[k].pt_kp->ki_uid, 0);
125251881Speter			pname = pt[k].pt_kp->ki_comm;
126251881Speter		}
127251881Speter		wmove(wnd, y, 0);
128251881Speter		wclrtoeol(wnd);
129251881Speter		mvwaddstr(wnd, y, 0, uname);
130251881Speter		snprintf(pidname, sizeof(pidname), "%10.10s", pname);
131251881Speter		mvwaddstr(wnd, y, 9, pidname);
132251881Speter		wmove(wnd, y, 20);
133251881Speter		for (j = pt[k].pt_pctcpu*factor + 0.5; j > 0; j--)
134251881Speter			waddch(wnd, 'X');
135251881Speter	}
136251881Speter	wmove(wnd, y, 0); wclrtobot(wnd);
137251881Speter}
138251881Speter
139251881Speterint
140251881Speterinitpigs()
141251881Speter{
142251881Speter	fixpt_t ccpu;
143251881Speter	size_t len;
144251881Speter	int err;
145251881Speter
146251881Speter	len = sizeof(stime);
147251881Speter	err = sysctlbyname("kern.cp_time", &stime, &len, NULL, 0);
148251881Speter	if (err || len != sizeof(stime)) {
149251881Speter		perror("kern.cp_time");
150251881Speter		return (0);
151251881Speter	}
152251881Speter
153251881Speter	len = sizeof(ccpu);
154251881Speter	err = sysctlbyname("kern.ccpu", &ccpu, &len, NULL, 0);
155251881Speter	if (err || len != sizeof(ccpu)) {
156251881Speter		perror("kern.ccpu");
157251881Speter		return (0);
158251881Speter	}
159251881Speter
160251881Speter	len = sizeof(fscale);
161251881Speter	err = sysctlbyname("kern.fscale", &fscale, &len, NULL, 0);
162251881Speter	if (err || len != sizeof(fscale)) {
163251881Speter		perror("kern.fscale");
164251881Speter		return (0);
165251881Speter	}
166251881Speter
167251881Speter	lccpu = log((double) ccpu / fscale);
168251881Speter
169251881Speter	return(1);
170251881Speter}
171251881Speter
172251881Spetervoid
173251881Speterfetchpigs()
174251881Speter{
175251881Speter	int i;
176251881Speter	float ftime;
177251881Speter	float *pctp;
178251881Speter	struct kinfo_proc *kpp;
179251881Speter	long c_time[CPUSTATES];
180251881Speter	double t;
181251881Speter	static int lastnproc = 0;
182251881Speter	size_t len;
183251881Speter	int err;
184251881Speter
185251881Speter	if ((kpp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc)) == NULL) {
186251881Speter		error("%s", kvm_geterr(kd));
187		if (pt)
188			free(pt);
189		return;
190	}
191	if (nproc > lastnproc) {
192		free(pt);
193		if ((pt =
194		    malloc((nproc + 1) * sizeof(struct p_times))) == NULL) {
195			error("Out of memory");
196			die(0);
197		}
198	}
199	lastnproc = nproc;
200	/*
201	 * calculate %cpu for each proc
202	 */
203	for (i = 0; i < nproc; i++) {
204		pt[i].pt_kp = &kpp[i];
205		pctp = &pt[i].pt_pctcpu;
206		ftime = kpp[i].ki_swtime;
207		if (ftime == 0 || (kpp[i].ki_sflag & PS_INMEM) == 0)
208			*pctp = 0;
209		else
210			*pctp = ((double) kpp[i].ki_pctcpu /
211					fscale) / (1.0 - exp(ftime * lccpu));
212	}
213	/*
214	 * and for the imaginary "idle" process
215	 */
216	len = sizeof(c_time);
217	err = sysctlbyname("kern.cp_time", &c_time, &len, NULL, 0);
218	if (err || len != sizeof(c_time)) {
219		perror("kern.cp_time");
220		return;
221	}
222	t = 0;
223	for (i = 0; i < CPUSTATES; i++)
224		t += c_time[i] - stime[i];
225	if (t == 0.0)
226		t = 1.0;
227	pt[nproc].pt_kp = NULL;
228	pt[nproc].pt_pctcpu = (c_time[CP_IDLE] - stime[CP_IDLE]) / t;
229	for (i = 0; i < CPUSTATES; i++)
230		stime[i] = c_time[i];
231}
232
233void
234labelpigs()
235{
236	wmove(wnd, 0, 0);
237	wclrtoeol(wnd);
238	mvwaddstr(wnd, 0, 20,
239	    "/0   /10  /20  /30  /40  /50  /60  /70  /80  /90  /100");
240}
241
242int
243compar(a, b)
244	const void *a, *b;
245{
246	return (((const struct p_times *) a)->pt_pctcpu >
247		((const struct p_times *) b)->pt_pctcpu)? -1: 1;
248}
249