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