xref: /original-bsd/usr.bin/systat/pigs.c (revision a5b2b2cf)
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.12 (Berkeley) 09/02/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 namelist[] = {
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 (namelist[X_FIRST].n_type == 0) {
128 		if (kvm_nlist(kd, namelist)) {
129 			nlisterr(namelist);
130 		        return(0);
131 		}
132 		if (namelist[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 (namelist[X_FIRST].n_type == 0)
158 		return;
159 	if ((kpp = kvm_getprocs(kd, KINFO_PROC_ALL, 0, &nproc)) == NULL) {
160 		error("%s", kvm_geterr(kd));
161 		if (pt)
162 			free(pt);
163 		return;
164 	}
165 	if (nproc > lastnproc) {
166 		free(pt);
167 		if ((pt = (struct p_times *) malloc
168 		    ((nproc + 1) * sizeof(struct p_times))) == NULL) {
169 		    error("Out of memory");
170 		    die(0);
171 	    }
172 
173 	}
174 	lastnproc = nproc;
175 	/*
176 	 * calculate %cpu for each proc
177 	 */
178 	for (i = 0; i < nproc; i++) {
179 		pt[i].pt_kp = &kpp[i];
180 		pp = &kpp[i].kp_proc;
181 		pctp = &pt[i].pt_pctcpu;
182 		time = pp->p_time;
183 		if (time == 0 || (pp->p_flag & SLOAD) == 0)
184 			*pctp = 0;
185 		else
186 			*pctp = ((double) pp->p_pctcpu /
187 					fscale) / (1.0 - exp(time * lccpu));
188 	}
189 	/*
190 	 * and for the imaginary "idle" process
191 	 */
192 	KREAD(NPTR(X_CPTIME), ctime, sizeof (ctime));
193 	t = 0;
194 	for (i = 0; i < CPUSTATES; i++)
195 		t += ctime[i] - stime[i];
196 	if (t == 0.0)
197 		t = 1.0;
198 	pt[nproc].pt_kp = NULL;
199 	pt[nproc].pt_pctcpu = (ctime[CP_IDLE] - stime[CP_IDLE]) / t;
200 	for (i = 0; i < CPUSTATES; i++)
201 		stime[i] = ctime[i];
202 }
203 
204 void
205 labelpigs()
206 {
207 	wmove(wnd, 0, 0); wclrtoeol(wnd);
208 	mvwaddstr(wnd, 0, 20,
209 	    "/0   /10  /20  /30  /40  /50  /60  /70  /80  /90  /100");
210 }
211 
212 int
213 compar(a, b)
214 	const void *a, *b;
215 {
216 	return (((struct p_times *) a)->pt_pctcpu >
217 		((struct p_times *) b)->pt_pctcpu)? -1: 1;
218 }
219