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