Annotation of src/usr.bin/systat/pigs.c, Revision 1.27
1.27 ! miod 1: /* $OpenBSD: pigs.c,v 1.26 2013/06/02 06:23:17 guenther 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: /*
34: * Pigs display from Bill Reeves at Lucasfilm
35: */
36:
37: #include <sys/param.h>
1.27 ! miod 38: #include <sys/proc.h>
1.12 deraadt 39: #include <sys/resource.h>
1.27 ! miod 40: #include <sys/sched.h>
! 41: #include <sys/sysctl.h>
1.1 deraadt 42: #include <sys/time.h>
43:
44: #include <curses.h>
45: #include <math.h>
46: #include <pwd.h>
1.8 pvalchev 47: #include <err.h>
1.1 deraadt 48: #include <stdlib.h>
49: #include <string.h>
50:
51: #include "systat.h"
52:
1.13 millert 53: int compar(const void *, const void *);
1.22 canacar 54: void print_pg(void);
55: int read_pg(void);
56: int select_pg(void);
57: void showpigs(int k);
58:
1.25 guenther 59: static struct kinfo_proc *procbase = NULL;
1.22 canacar 60: static int nproc, pigs_cnt, *pb_indices = NULL;
61: static int onproc = -1;
1.1 deraadt 62:
63: static long stime[CPUSTATES];
64: static double lccpu;
1.22 canacar 65: struct loadavg sysload;
66:
67:
1.1 deraadt 68:
1.22 canacar 69: field_def fields_pg[] = {
70: {"USER", 6, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
71: {"NAME", 10, 24, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
72: {"PID", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
73: {"CPU", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
74: {"", 30, 60, 1, FLD_ALIGN_BAR, -1, 0, 0, 100},
75: };
76:
1.24 jasper 77: #define FLD_PG_USER FIELD_ADDR(fields_pg,0)
78: #define FLD_PG_NAME FIELD_ADDR(fields_pg,1)
79: #define FLD_PG_PID FIELD_ADDR(fields_pg,2)
80: #define FLD_PG_VALUE FIELD_ADDR(fields_pg,3)
81: #define FLD_PG_BAR FIELD_ADDR(fields_pg,4)
1.22 canacar 82:
83: /* Define views */
84: field_def *view_pg_0[] = {
85: FLD_PG_PID, FLD_PG_USER, FLD_PG_NAME, FLD_PG_VALUE, FLD_PG_BAR, NULL
86: };
87:
88:
89: /* Define view managers */
90: struct view_manager pigs_mgr = {
91: "Pigs", select_pg, read_pg, NULL, print_header,
92: print_pg, keyboard_callback, NULL, NULL
93: };
94:
95: field_view views_pg[] = {
96: {view_pg_0, "pigs", '5', &pigs_mgr},
97: {NULL, NULL, 0, NULL}
98: };
99:
100:
101: #ifdef FSCALE
102: # define FIXED_LOADAVG FSCALE
103: # define FIXED_PCTCPU FSCALE
104: #endif
105:
106: #ifdef FIXED_PCTCPU
107: typedef long pctcpu;
108: # define pctdouble(p) ((double)(p) / FIXED_PCTCPU)
109: #else
110: typedef double pctcpu;
111: # define pctdouble(p) (p)
112: #endif
113:
114: int
115: select_pg(void)
1.1 deraadt 116: {
1.22 canacar 117: num_disp = pigs_cnt;
118: return (0);
1.1 deraadt 119: }
120:
1.22 canacar 121:
122: int
123: getprocs(void)
1.1 deraadt 124: {
1.22 canacar 125: size_t size;
1.25 guenther 126: int mib[6] = {CTL_KERN, KERN_PROC, KERN_PROC_KTHREAD, 0, sizeof(struct kinfo_proc), 0};
1.22 canacar 127:
128: int st;
129:
130: free(procbase);
131: procbase = NULL;
132:
133: st = sysctl(mib, 6, NULL, &size, NULL, 0);
134: if (st == -1)
135: return (1);
136:
137: size = 5 * size / 4; /* extra slop */
138: if ((procbase = malloc(size + 1)) == NULL)
139: return (1);
140:
1.25 guenther 141: mib[5] = (int)(size / sizeof(struct kinfo_proc));
1.22 canacar 142: st = sysctl(mib, 6, procbase, &size, NULL, 0);
143: if (st == -1)
144: return (1);
145:
1.25 guenther 146: nproc = (int)(size / sizeof(struct kinfo_proc));
1.22 canacar 147: return (0);
1.1 deraadt 148: }
149:
150:
1.22 canacar 151: int
152: read_pg(void)
1.1 deraadt 153: {
1.22 canacar 154: static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME };
1.23 canacar 155: long ctimes[CPUSTATES];
1.22 canacar 156: double t;
157: int i, k;
158: size_t size;
159:
160: num_disp = pigs_cnt = 0;
1.1 deraadt 161:
1.22 canacar 162: if (getprocs()) {
163: error("Failed to read process info!");
164: return 1;
1.1 deraadt 165: }
166:
1.22 canacar 167: if (nproc > onproc) {
168: int *p;
169: p = realloc(pb_indices, (nproc + 1) * sizeof(int));
170: if (p == NULL) {
171: error("Out of Memory!");
172: return 1;
1.1 deraadt 173: }
1.22 canacar 174: pb_indices = p;
175: onproc = nproc;
1.1 deraadt 176: }
1.22 canacar 177:
178: memset(&procbase[nproc], 0, sizeof(*procbase));
179:
180: for (i = 0; i <= nproc; i++)
181: pb_indices[i] = i;
182:
183: /*
184: * and for the imaginary "idle" process
185: */
1.23 canacar 186: size = sizeof(ctimes);
187: sysctl(cp_time_mib, 2, &ctimes, &size, NULL, 0);
1.22 canacar 188:
189: t = 0;
190: for (i = 0; i < CPUSTATES; i++)
1.23 canacar 191: t += ctimes[i] - stime[i];
1.22 canacar 192: if (t == 0.0)
193: t = 1.0;
194:
1.23 canacar 195: procbase[nproc].p_pctcpu = (ctimes[CP_IDLE] - stime[CP_IDLE]) / t / pctdouble(1);
1.22 canacar 196: for (i = 0; i < CPUSTATES; i++)
1.23 canacar 197: stime[i] = ctimes[i];
1.22 canacar 198:
199: qsort(pb_indices, nproc + 1, sizeof (int), compar);
200:
201: pigs_cnt = 0;
202: for (k = 0; k < nproc + 1; k++) {
1.23 canacar 203: int j = pb_indices[k];
204: if (pctdouble(procbase[j].p_pctcpu) < 0.01)
1.22 canacar 205: break;
206: pigs_cnt++;
207: }
208:
209: num_disp = pigs_cnt;
210: return 0;
1.1 deraadt 211: }
212:
1.22 canacar 213:
214: void
215: print_pg(void)
216: {
217: int n, count = 0;
218:
219: for (n = dispstart; n < num_disp; n++) {
220: showpigs(pb_indices[n]);
221: count++;
222: if (maxprint > 0 && count >= maxprint)
223: break;
224: }
225: }
1.1 deraadt 226:
227: int
1.14 deraadt 228: initpigs(void)
1.1 deraadt 229: {
1.12 deraadt 230: static int sysload_mib[] = {CTL_VM, VM_LOADAVG};
231: static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME };
232: static int ccpu_mib[] = { CTL_KERN, KERN_CCPU };
1.22 canacar 233: field_view *v;
1.12 deraadt 234: size_t size;
1.1 deraadt 235: fixpt_t ccpu;
236:
1.12 deraadt 237: size = sizeof(stime);
1.22 canacar 238: sysctl(cp_time_mib, 2, &stime, &size, NULL, 0);
1.12 deraadt 239:
240: size = sizeof(sysload);
1.22 canacar 241: sysctl(sysload_mib, 2, &sysload, &size, NULL, 0);
1.12 deraadt 242:
243: size = sizeof(ccpu);
1.22 canacar 244: sysctl(ccpu_mib, 2, &ccpu, &size, NULL, 0);
1.12 deraadt 245:
246: lccpu = log((double) ccpu / sysload.fscale);
1.1 deraadt 247:
1.22 canacar 248: for (v = views_pg; v->name != NULL; v++)
249: add_view(v);
250:
1.1 deraadt 251: return(1);
252: }
253:
254: void
1.22 canacar 255: showpigs(int k)
1.1 deraadt 256: {
1.25 guenther 257: struct kinfo_proc *kp;
1.22 canacar 258: double value;
259: char *uname, *pname;
1.1 deraadt 260:
1.22 canacar 261: if (procbase == NULL)
1.1 deraadt 262: return;
1.22 canacar 263:
264: value = pctdouble(procbase[k].p_pctcpu) * 100;
265:
266: kp = &procbase[k];
267: if (kp->p_comm[0] == '\0') {
268: uname = "";
269: pname = "<idle>";
270: } else {
271: uname = user_from_uid(kp->p_uid, 0);
272: pname = kp->p_comm;
273: print_fld_uint(FLD_PG_PID, kp->p_pid);
1.1 deraadt 274: }
1.12 deraadt 275:
1.22 canacar 276: tb_start();
277: tbprintf("%.2f", value);
278: print_fld_tb(FLD_PG_VALUE);
279:
280: print_fld_str(FLD_PG_NAME, pname);
281: print_fld_str(FLD_PG_USER, uname);
282: print_fld_bar(FLD_PG_BAR, value);
283:
284: end_line();
1.1 deraadt 285: }
286:
287:
288: int
1.14 deraadt 289: compar(const void *a, const void *b)
1.1 deraadt 290: {
1.22 canacar 291: int i1 = *((int *)a);
292: int i2 = *((int *)b);
293:
294: return procbase[i1].p_pctcpu >
295: procbase[i2].p_pctcpu ? -1 : 1;
1.1 deraadt 296: }
1.22 canacar 297: