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