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