Annotation of src/usr.bin/systat/pigs.c, Revision 1.25
1.25 ! guenther 1: /* $OpenBSD: pigs.c,v 1.24 2011/03/02 06:48:17 jasper 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>
38: #include <sys/dkstat.h>
1.12 deraadt 39: #include <sys/resource.h>
1.1 deraadt 40: #include <sys/dir.h>
41: #include <sys/time.h>
42: #include <sys/proc.h>
43: #include <sys/sysctl.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:
101:
102: #ifdef FSCALE
103: # define FIXED_LOADAVG FSCALE
104: # define FIXED_PCTCPU FSCALE
105: #endif
106:
107: #ifdef FIXED_PCTCPU
108: typedef long pctcpu;
109: # define pctdouble(p) ((double)(p) / FIXED_PCTCPU)
110: #else
111: typedef double pctcpu;
112: # define pctdouble(p) (p)
113: #endif
114:
115: int
116: select_pg(void)
1.1 deraadt 117: {
1.22 canacar 118: num_disp = pigs_cnt;
119: return (0);
1.1 deraadt 120: }
121:
1.22 canacar 122:
123: int
124: getprocs(void)
1.1 deraadt 125: {
1.22 canacar 126: size_t size;
1.25 ! guenther 127: int mib[6] = {CTL_KERN, KERN_PROC, KERN_PROC_KTHREAD, 0, sizeof(struct kinfo_proc), 0};
1.22 canacar 128:
129: int st;
130:
131: free(procbase);
132: procbase = NULL;
133:
134: st = sysctl(mib, 6, NULL, &size, NULL, 0);
135: if (st == -1)
136: return (1);
137:
138: size = 5 * size / 4; /* extra slop */
139: if ((procbase = malloc(size + 1)) == NULL)
140: return (1);
141:
1.25 ! guenther 142: mib[5] = (int)(size / sizeof(struct kinfo_proc));
1.22 canacar 143: st = sysctl(mib, 6, procbase, &size, NULL, 0);
144: if (st == -1)
145: return (1);
146:
1.25 ! guenther 147: nproc = (int)(size / sizeof(struct kinfo_proc));
1.22 canacar 148: return (0);
1.1 deraadt 149: }
150:
151:
1.22 canacar 152: int
153: read_pg(void)
1.1 deraadt 154: {
1.22 canacar 155: static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME };
1.23 canacar 156: long ctimes[CPUSTATES];
1.22 canacar 157: double t;
158: int i, k;
159: size_t size;
160:
161: num_disp = pigs_cnt = 0;
1.1 deraadt 162:
1.22 canacar 163: if (getprocs()) {
164: error("Failed to read process info!");
165: return 1;
1.1 deraadt 166: }
167:
1.22 canacar 168: if (nproc > onproc) {
169: int *p;
170: p = realloc(pb_indices, (nproc + 1) * sizeof(int));
171: if (p == NULL) {
172: error("Out of Memory!");
173: return 1;
1.1 deraadt 174: }
1.22 canacar 175: pb_indices = p;
176: onproc = nproc;
1.1 deraadt 177: }
1.22 canacar 178:
179: memset(&procbase[nproc], 0, sizeof(*procbase));
180:
181: for (i = 0; i <= nproc; i++)
182: pb_indices[i] = i;
183:
184: /*
185: * and for the imaginary "idle" process
186: */
1.23 canacar 187: size = sizeof(ctimes);
188: sysctl(cp_time_mib, 2, &ctimes, &size, NULL, 0);
1.22 canacar 189:
190: t = 0;
191: for (i = 0; i < CPUSTATES; i++)
1.23 canacar 192: t += ctimes[i] - stime[i];
1.22 canacar 193: if (t == 0.0)
194: t = 1.0;
195:
1.23 canacar 196: procbase[nproc].p_pctcpu = (ctimes[CP_IDLE] - stime[CP_IDLE]) / t / pctdouble(1);
1.22 canacar 197: for (i = 0; i < CPUSTATES; i++)
1.23 canacar 198: stime[i] = ctimes[i];
1.22 canacar 199:
200: qsort(pb_indices, nproc + 1, sizeof (int), compar);
201:
202: pigs_cnt = 0;
203: for (k = 0; k < nproc + 1; k++) {
1.23 canacar 204: int j = pb_indices[k];
205: if (pctdouble(procbase[j].p_pctcpu) < 0.01)
1.22 canacar 206: break;
207: pigs_cnt++;
208: }
209:
210: num_disp = pigs_cnt;
211: return 0;
1.1 deraadt 212: }
213:
1.22 canacar 214:
215: void
216: print_pg(void)
217: {
218: int n, count = 0;
219:
220: for (n = dispstart; n < num_disp; n++) {
221: showpigs(pb_indices[n]);
222: count++;
223: if (maxprint > 0 && count >= maxprint)
224: break;
225: }
226: }
1.1 deraadt 227:
228: int
1.14 deraadt 229: initpigs(void)
1.1 deraadt 230: {
1.12 deraadt 231: static int sysload_mib[] = {CTL_VM, VM_LOADAVG};
232: static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME };
233: static int ccpu_mib[] = { CTL_KERN, KERN_CCPU };
1.22 canacar 234: field_view *v;
1.12 deraadt 235: size_t size;
1.1 deraadt 236: fixpt_t ccpu;
237:
1.12 deraadt 238: size = sizeof(stime);
1.22 canacar 239: sysctl(cp_time_mib, 2, &stime, &size, NULL, 0);
1.12 deraadt 240:
241: size = sizeof(sysload);
1.22 canacar 242: sysctl(sysload_mib, 2, &sysload, &size, NULL, 0);
1.12 deraadt 243:
244: size = sizeof(ccpu);
1.22 canacar 245: sysctl(ccpu_mib, 2, &ccpu, &size, NULL, 0);
1.12 deraadt 246:
247: lccpu = log((double) ccpu / sysload.fscale);
1.1 deraadt 248:
1.22 canacar 249: for (v = views_pg; v->name != NULL; v++)
250: add_view(v);
251:
1.1 deraadt 252: return(1);
253: }
254:
255: void
1.22 canacar 256: showpigs(int k)
1.1 deraadt 257: {
1.25 ! guenther 258: struct kinfo_proc *kp;
1.22 canacar 259: double value;
260: char *uname, *pname;
1.1 deraadt 261:
1.22 canacar 262: if (procbase == NULL)
1.1 deraadt 263: return;
1.22 canacar 264:
265: value = pctdouble(procbase[k].p_pctcpu) * 100;
266:
267: kp = &procbase[k];
268: if (kp->p_comm[0] == '\0') {
269: uname = "";
270: pname = "<idle>";
271: } else {
272: uname = user_from_uid(kp->p_uid, 0);
273: pname = kp->p_comm;
274: print_fld_uint(FLD_PG_PID, kp->p_pid);
1.1 deraadt 275: }
1.12 deraadt 276:
1.22 canacar 277: tb_start();
278: tbprintf("%.2f", value);
279: print_fld_tb(FLD_PG_VALUE);
280:
281: print_fld_str(FLD_PG_NAME, pname);
282: print_fld_str(FLD_PG_USER, uname);
283: print_fld_bar(FLD_PG_BAR, value);
284:
285: end_line();
1.1 deraadt 286: }
287:
288:
289: int
1.14 deraadt 290: compar(const void *a, const void *b)
1.1 deraadt 291: {
1.22 canacar 292: int i1 = *((int *)a);
293: int i2 = *((int *)b);
294:
295: return procbase[i1].p_pctcpu >
296: procbase[i2].p_pctcpu ? -1 : 1;
1.1 deraadt 297: }
1.22 canacar 298: