Do some fairly major include file cleanups to further separate kernelland
[dragonfly.git] / usr.bin / systat / pigs.c
CommitLineData
984263bc
MD
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.
1de703da
MD
32 *
33 * @(#)pigs.c 8.2 (Berkeley) 9/23/93
1d1731fa 34 *
05220613 35 * $DragonFly: src/usr.bin/systat/pigs.c,v 1.8 2003/11/21 22:46:14 dillon Exp $
984263bc
MD
36 */
37
984263bc
MD
38/*
39 * Pigs display from Bill Reeves at Lucasfilm
40 */
41
05220613 42#define _KERNEL_STRUCTURES
984263bc
MD
43#include <sys/param.h>
44#include <sys/dkstat.h>
45#include <sys/time.h>
984263bc
MD
46#include <sys/user.h>
47#include <sys/sysctl.h>
48
49#include <curses.h>
50#include <math.h>
51#include <nlist.h>
52#include <pwd.h>
53#include <stdlib.h>
54
55#include "extern.h"
56#include "systat.h"
57
1d1731fa 58int compar(const void *, const void *);
984263bc
MD
59
60static int nproc;
61static struct p_times {
62 float pt_pctcpu;
63 struct kinfo_proc *pt_kp;
64} *pt;
65
66static long stime[CPUSTATES];
67static long fscale;
68static double lccpu;
69
70WINDOW *
1d1731fa 71openpigs(void)
984263bc
MD
72{
73 return (subwin(stdscr, LINES-5-1, 0, 5, 0));
74}
75
76void
1d1731fa 77closepigs(WINDOW *w)
984263bc
MD
78{
79 if (w == NULL)
80 return;
81 wclear(w);
82 wrefresh(w);
83 delwin(w);
84}
85
86
87void
1d1731fa 88showpigs(void)
984263bc
MD
89{
90 register int i, j, y, k;
91 struct eproc *ep;
92 float total;
93 int factor;
94 char *uname, *pname, pidname[30];
95
96 if (pt == NULL)
97 return;
98 /* Accumulate the percent of cpu per user. */
99 total = 0.0;
100 for (i = 0; i <= nproc; i++) {
101 /* Accumulate the percentage. */
102 total += pt[i].pt_pctcpu;
103 }
104
105 if (total < 1.0)
106 total = 1.0;
107 factor = 50.0/total;
108
109 qsort(pt, nproc + 1, sizeof (struct p_times), compar);
110 y = 1;
111 i = nproc + 1;
112 if (i > wnd->_maxy-1)
113 i = wnd->_maxy-1;
48c018df 114 for (k = 0; i > 0; i--, y++, k++) {
64def633 115 char buf[256];
48c018df
MD
116 if (pt[k].pt_pctcpu <= 0.01 &&
117 (pt[k].pt_kp == NULL ||
64def633 118 pt[k].pt_kp->kp_proc.p_slptime > 1)
48c018df 119 ) {
64def633 120 --y;
48c018df
MD
121 continue;
122 }
984263bc
MD
123 if (pt[k].pt_kp == NULL) {
124 uname = "";
125 pname = "<idle>";
48c018df 126 } else {
984263bc
MD
127 ep = &pt[k].pt_kp->kp_eproc;
128 uname = (char *)user_from_uid(ep->e_ucred.cr_uid, 0);
17c88c3a 129 pname = pt[k].pt_kp->kp_thread.td_comm;
984263bc
MD
130 }
131 wmove(wnd, y, 0);
132 wclrtoeol(wnd);
133 mvwaddstr(wnd, y, 0, uname);
134 snprintf(pidname, sizeof(pidname), "%10.10s", pname);
135 mvwaddstr(wnd, y, 9, pidname);
136 wmove(wnd, y, 20);
137 for (j = pt[k].pt_pctcpu*factor + 0.5; j > 0; j--)
138 waddch(wnd, 'X');
139 }
140 wmove(wnd, y, 0); wclrtobot(wnd);
141}
142
143static struct nlist namelist[] = {
144#define X_FIRST 0
145#define X_CPTIME 0
146 { "_cp_time" },
147#define X_CCPU 1
148 { "_ccpu" },
149#define X_FSCALE 2
150 { "_fscale" },
151
152 { "" }
153};
154
155int
1d1731fa 156initpigs(void)
984263bc
MD
157{
158 fixpt_t ccpu;
159
160 if (namelist[X_FIRST].n_type == 0) {
161 if (kvm_nlist(kd, namelist)) {
162 nlisterr(namelist);
163 return(0);
164 }
165 if (namelist[X_FIRST].n_type == 0) {
166 error("namelist failed");
167 return(0);
168 }
169 }
170 KREAD(NPTR(X_CPTIME), stime, sizeof (stime));
171 NREAD(X_CCPU, &ccpu, sizeof(ccpu));
172 NREAD(X_FSCALE, &fscale, LONG);
173 lccpu = log((double) ccpu / fscale);
174
175 return(1);
176}
177
178void
1d1731fa 179fetchpigs(void)
984263bc 180{
543eaf46
MD
181 int i;
182 float time;
183 struct proc *pp;
184 float *pctp;
984263bc
MD
185 struct kinfo_proc *kpp;
186 long ctime[CPUSTATES];
187 double t;
188 static int lastnproc = 0;
189
190 if (namelist[X_FIRST].n_type == 0)
191 return;
192 if ((kpp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc)) == NULL) {
193 error("%s", kvm_geterr(kd));
194 if (pt)
195 free(pt);
196 return;
197 }
198 if (nproc > lastnproc) {
199 free(pt);
200 if ((pt =
201 malloc((nproc + 1) * sizeof(struct p_times))) == NULL) {
202 error("Out of memory");
203 die(0);
204 }
205 }
206 lastnproc = nproc;
207 /*
208 * calculate %cpu for each proc
209 */
210 for (i = 0; i < nproc; i++) {
211 pt[i].pt_kp = &kpp[i];
212 pp = &kpp[i].kp_proc;
213 pctp = &pt[i].pt_pctcpu;
214 time = pp->p_swtime;
215 if (time == 0 || (pp->p_flag & P_INMEM) == 0)
216 *pctp = 0;
217 else
218 *pctp = ((double) pp->p_pctcpu /
219 fscale) / (1.0 - exp(time * lccpu));
220 }
221 /*
222 * and for the imaginary "idle" process
223 */
224 KREAD(NPTR(X_CPTIME), ctime, sizeof (ctime));
225 t = 0;
226 for (i = 0; i < CPUSTATES; i++)
227 t += ctime[i] - stime[i];
228 if (t == 0.0)
229 t = 1.0;
230 pt[nproc].pt_kp = NULL;
231 pt[nproc].pt_pctcpu = (ctime[CP_IDLE] - stime[CP_IDLE]) / t;
232 for (i = 0; i < CPUSTATES; i++)
233 stime[i] = ctime[i];
234}
235
236void
1d1731fa 237labelpigs(void)
984263bc
MD
238{
239 wmove(wnd, 0, 0);
240 wclrtoeol(wnd);
241 mvwaddstr(wnd, 0, 20,
242 "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
243}
244
245int
48c018df 246compar(const void *a, const void *b)
984263bc 247{
48c018df
MD
248 struct p_times *pta = (struct p_times *)a;
249 struct p_times *ptb = (struct p_times *)b;
250 float d;
251
252 /*
253 * Check overall cpu percentage first.
254 */
255 d = pta->pt_pctcpu - ptb->pt_pctcpu;
256 if (d > 0.10)
257 return(-1); /* a is better */
258 else if (d < -0.10)
259 return(1); /* b is better */
260
261 if (pta->pt_kp == NULL && ptb->pt_kp == NULL)
262 return(0);
263 if (ptb->pt_kp == NULL)
264 return(-1); /* a is better */
265 if (pta->pt_kp == NULL)
266 return(1); /* b is better */
267 /*
268 * Then check sleep times and run status.
269 */
270 if (pta->pt_kp->kp_proc.p_slptime < ptb->pt_kp->kp_proc.p_slptime)
271 return(-1);
272 if (pta->pt_kp->kp_proc.p_slptime > ptb->pt_kp->kp_proc.p_slptime)
273 return(1);
274
275 /*
276 * Runnability
277 */
278 if (pta->pt_kp->kp_proc.p_stat != ptb->pt_kp->kp_proc.p_stat) {
279 if (pta->pt_kp->kp_proc.p_stat == SRUN)
280 return(-1);
281 if (ptb->pt_kp->kp_proc.p_stat == SRUN)
282 return(1);
283 }
284 return(0);
984263bc 285}
48c018df
MD
286
287