xref: /original-bsd/usr.bin/systat/pigs.c (revision b1dc0eed)
1 /*-
2  * Copyright (c) 1980, 1992 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.proprietary.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)pigs.c	5.11 (Berkeley) 07/24/92";
10 #endif /* not lint */
11 
12 /*
13  * Pigs display from Bill Reeves at Lucasfilm
14  */
15 
16 #include <sys/param.h>
17 #include <sys/dkstat.h>
18 #include <sys/dir.h>
19 #include <sys/time.h>
20 #include <sys/proc.h>
21 #include <sys/kinfo.h>
22 #include <sys/kinfo_proc.h>
23 
24 #include <pwd.h>
25 #include <math.h>
26 #include <stdlib.h>
27 #include <nlist.h>
28 #include "systat.h"
29 #include "extern.h"
30 
31 int compar __P((const void *, const void *));
32 
33 static int nproc;
34 static struct p_times {
35 	float pt_pctcpu;
36 	struct kinfo_proc *pt_kp;
37 } *pt;
38 
39 static long stime[CPUSTATES];
40 static int     fscale;
41 static double  lccpu;
42 
43 WINDOW *
44 openpigs()
45 {
46 	return (subwin(stdscr, LINES-5-1, 0, 5, 0));
47 }
48 
49 void
50 closepigs(w)
51 	WINDOW *w;
52 {
53 	if (w == NULL)
54 		return;
55 	wclear(w);
56 	wrefresh(w);
57 	delwin(w);
58 }
59 
60 
61 void
62 showpigs()
63 {
64 	register int i, j, y, k;
65 	struct	eproc *ep;
66 	float total;
67 	int factor;
68 	char *uname, *pname, pidname[30];
69 
70 	if (pt == NULL)
71 		return;
72 	/* Accumulate the percent of cpu per user. */
73 	total = 0.0;
74 	for (i = 0; i <= nproc; i++) {
75 		/* Accumulate the percentage. */
76 		total += pt[i].pt_pctcpu;
77 	}
78 
79 	if (total < 1.0)
80  		total = 1.0;
81 	factor = 50.0/total;
82 
83         qsort(pt, nproc + 1, sizeof (struct p_times), compar);
84 	y = 1;
85 	i = nproc + 1;
86 	if (i > wnd->_maxy-1)
87 		i = wnd->_maxy-1;
88 	for (k = 0; i > 0 && pt[k].pt_pctcpu > 0.01; i--, y++, k++) {
89 		if (pt[k].pt_kp == NULL) {
90 			uname = "";
91 			pname = "<idle>";
92 		}
93 		else {
94 			ep = &pt[k].pt_kp->kp_eproc;
95 			uname = (char *)user_from_uid(ep->e_ucred.cr_uid, 0);
96 			pname = pt[k].pt_kp->kp_proc.p_comm;
97 		}
98 		wmove(wnd, y, 0);
99 		wclrtoeol(wnd);
100 		mvwaddstr(wnd, y, 0, uname);
101 		sprintf(pidname, "%10.10s", pname, 0);
102 		mvwaddstr(wnd, y, 9, pidname);
103 		wmove(wnd, y, 20);
104 		for (j = pt[k].pt_pctcpu*factor + 0.5; j > 0; j--)
105 			waddch(wnd, 'X');
106 	}
107 	wmove(wnd, y, 0); wclrtobot(wnd);
108 }
109 
110 static struct nlist nl[] = {
111 #define X_FIRST		0
112 #define X_CPTIME	0
113 	{ "_cp_time" },
114 #define X_CCPU          1
115 	{ "_ccpu" },
116 #define X_FSCALE        2
117 	{ "_fscale" },
118 
119 	{ "" }
120 };
121 
122 int
123 initpigs()
124 {
125 	fixpt_t ccpu;
126 
127 	if (nl[X_FIRST].n_type == 0) {
128 		if (kvm_nlist(kd, nl)) {
129 			nlisterr(nl);
130 		        return(0);
131 		}
132 		if (nl[X_FIRST].n_type == 0) {
133 			error("namelist failed");
134 			return(0);
135 		}
136 	}
137 	KREAD(NPTR(X_CPTIME), stime, sizeof (stime));
138 	NREAD(X_CCPU, &ccpu, LONG);
139 	NREAD(X_FSCALE,  &fscale, LONG);
140 	lccpu = log((double) ccpu / fscale);
141 
142 	return(1);
143 }
144 
145 void
146 fetchpigs()
147 {
148 	register int i;
149 	register float time;
150 	register struct proc *pp;
151 	register float *pctp;
152 	struct kinfo_proc *kpp;
153 	long ctime[CPUSTATES];
154 	double t;
155 	static int lastnproc = 0;
156 
157 	if (nl[X_FIRST].n_type == 0)
158 		return;
159 	if ((kpp =
160 	    kvm_getprocs(kd, KINFO_PROC_ALL, 0, &nproc)) == NULL) {
161 		error("%s", kvm_geterr(kd));
162 		if (pt)
163 			free(pt);
164 		return;
165 	}
166 	if (nproc > lastnproc) {
167 		free(pt);
168 		if ((pt = (struct p_times *) malloc
169 		    ((nproc + 1) * sizeof(struct p_times))) == NULL) {
170 		    error("Out of memory");
171 		    die(0);
172 	    }
173 
174 	}
175 	lastnproc = nproc;
176 	/*
177 	 * calculate %cpu for each proc
178 	 */
179 	for (i = 0; i < nproc; i++) {
180 		pt[i].pt_kp = &kpp[i];
181 		pp = &kpp[i].kp_proc;
182 		pctp = &pt[i].pt_pctcpu;
183 		time = pp->p_time;
184 		if (time == 0 || (pp->p_flag & SLOAD) == 0)
185 			*pctp = 0;
186 		else
187 			*pctp = ((double) pp->p_pctcpu /
188 					fscale) / (1.0 - exp(time * lccpu));
189 	}
190 	/*
191 	 * and for the imaginary "idle" process
192 	 */
193 	KREAD(NPTR(X_CPTIME), ctime, sizeof (ctime));
194 	t = 0;
195 	for (i = 0; i < CPUSTATES; i++)
196 		t += ctime[i] - stime[i];
197 	if (t == 0.0)
198 		t = 1.0;
199 	pt[nproc].pt_kp = NULL;
200 	pt[nproc].pt_pctcpu = (ctime[CP_IDLE] - stime[CP_IDLE]) / t;
201 	for (i = 0; i < CPUSTATES; i++)
202 		stime[i] = ctime[i];
203 }
204 
205 void
206 labelpigs()
207 {
208 	wmove(wnd, 0, 0); wclrtoeol(wnd);
209 	mvwaddstr(wnd, 0, 20,
210 	    "/0   /10  /20  /30  /40  /50  /60  /70  /80  /90  /100");
211 }
212 
213 int
214 compar(a, b)
215 	const void *a, *b;
216 {
217 	return (((struct p_times *) a)->pt_pctcpu >
218 		((struct p_times *) b)->pt_pctcpu)? -1: 1;
219 }
220