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