1 /*-
2 * Copyright (c) 1980, 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)pigs.c 8.2 (Berkeley) 09/23/93";
10 #endif /* not lint */
11
12 /*
13 * Pigs display from Bill Reeves at Lucasfilm
14 */
15
16 #include <sys/param.h>
17 #include <sys/dkstat.h>
18 #include <sys/dir.h>
19 #include <sys/time.h>
20 #include <sys/proc.h>
21 #include <sys/sysctl.h>
22
23 #include <curses.h>
24 #include <math.h>
25 #include <nlist.h>
26 #include <pwd.h>
27 #include <stdlib.h>
28
29 #include "extern.h"
30 #include "systat.h"
31
32 int compar __P((const void *, const void *));
33
34 static int nproc;
35 static struct p_times {
36 float pt_pctcpu;
37 struct kinfo_proc *pt_kp;
38 } *pt;
39
40 static long stime[CPUSTATES];
41 static int fscale;
42 static double lccpu;
43
44 WINDOW *
openpigs()45 openpigs()
46 {
47 return (subwin(stdscr, LINES-5-1, 0, 5, 0));
48 }
49
50 void
closepigs(w)51 closepigs(w)
52 WINDOW *w;
53 {
54 if (w == NULL)
55 return;
56 wclear(w);
57 wrefresh(w);
58 delwin(w);
59 }
60
61
62 void
showpigs()63 showpigs()
64 {
65 register int i, j, y, k;
66 struct eproc *ep;
67 float total;
68 int factor;
69 char *uname, *pname, pidname[30];
70
71 if (pt == NULL)
72 return;
73 /* Accumulate the percent of cpu per user. */
74 total = 0.0;
75 for (i = 0; i <= nproc; i++) {
76 /* Accumulate the percentage. */
77 total += pt[i].pt_pctcpu;
78 }
79
80 if (total < 1.0)
81 total = 1.0;
82 factor = 50.0/total;
83
84 qsort(pt, nproc + 1, sizeof (struct p_times), compar);
85 y = 1;
86 i = nproc + 1;
87 if (i > wnd->maxy-1)
88 i = wnd->maxy-1;
89 for (k = 0; i > 0 && pt[k].pt_pctcpu > 0.01; i--, y++, k++) {
90 if (pt[k].pt_kp == NULL) {
91 uname = "";
92 pname = "<idle>";
93 }
94 else {
95 ep = &pt[k].pt_kp->kp_eproc;
96 uname = (char *)user_from_uid(ep->e_ucred.cr_uid, 0);
97 pname = pt[k].pt_kp->kp_proc.p_comm;
98 }
99 wmove(wnd, y, 0);
100 wclrtoeol(wnd);
101 mvwaddstr(wnd, y, 0, uname);
102 sprintf(pidname, "%10.10s", pname, 0);
103 mvwaddstr(wnd, y, 9, pidname);
104 wmove(wnd, y, 20);
105 for (j = pt[k].pt_pctcpu*factor + 0.5; j > 0; j--)
106 waddch(wnd, 'X');
107 }
108 wmove(wnd, y, 0); wclrtobot(wnd);
109 }
110
111 static struct nlist namelist[] = {
112 #define X_FIRST 0
113 #define X_CPTIME 0
114 { "_cp_time" },
115 #define X_CCPU 1
116 { "_ccpu" },
117 #define X_FSCALE 2
118 { "_fscale" },
119
120 { "" }
121 };
122
123 int
initpigs()124 initpigs()
125 {
126 fixpt_t ccpu;
127
128 if (namelist[X_FIRST].n_type == 0) {
129 if (kvm_nlist(kd, namelist)) {
130 nlisterr(namelist);
131 return(0);
132 }
133 if (namelist[X_FIRST].n_type == 0) {
134 error("namelist failed");
135 return(0);
136 }
137 }
138 KREAD(NPTR(X_CPTIME), stime, sizeof (stime));
139 NREAD(X_CCPU, &ccpu, LONG);
140 NREAD(X_FSCALE, &fscale, LONG);
141 lccpu = log((double) ccpu / fscale);
142
143 return(1);
144 }
145
146 void
fetchpigs()147 fetchpigs()
148 {
149 register int i;
150 register float time;
151 register struct proc *pp;
152 register float *pctp;
153 struct kinfo_proc *kpp;
154 long ctime[CPUSTATES];
155 double t;
156 static int lastnproc = 0;
157
158 if (namelist[X_FIRST].n_type == 0)
159 return;
160 if ((kpp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc)) == NULL) {
161 error("%s", kvm_geterr(kd));
162 if (pt)
163 free(pt);
164 return;
165 }
166 if (nproc > lastnproc) {
167 free(pt);
168 if ((pt =
169 malloc((nproc + 1) * sizeof(struct p_times))) == NULL) {
170 error("Out of memory");
171 die(0);
172 }
173 }
174 lastnproc = nproc;
175 /*
176 * calculate %cpu for each proc
177 */
178 for (i = 0; i < nproc; i++) {
179 pt[i].pt_kp = &kpp[i];
180 pp = &kpp[i].kp_proc;
181 pctp = &pt[i].pt_pctcpu;
182 time = pp->p_swtime;
183 if (time == 0 || (pp->p_flag & P_INMEM) == 0)
184 *pctp = 0;
185 else
186 *pctp = ((double) pp->p_pctcpu /
187 fscale) / (1.0 - exp(time * lccpu));
188 }
189 /*
190 * and for the imaginary "idle" process
191 */
192 KREAD(NPTR(X_CPTIME), ctime, sizeof (ctime));
193 t = 0;
194 for (i = 0; i < CPUSTATES; i++)
195 t += ctime[i] - stime[i];
196 if (t == 0.0)
197 t = 1.0;
198 pt[nproc].pt_kp = NULL;
199 pt[nproc].pt_pctcpu = (ctime[CP_IDLE] - stime[CP_IDLE]) / t;
200 for (i = 0; i < CPUSTATES; i++)
201 stime[i] = ctime[i];
202 }
203
204 void
labelpigs()205 labelpigs()
206 {
207 wmove(wnd, 0, 0);
208 wclrtoeol(wnd);
209 mvwaddstr(wnd, 0, 20,
210 "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
211 }
212
213 int
compar(a,b)214 compar(a, b)
215 const void *a, *b;
216 {
217 return (((struct p_times *) a)->pt_pctcpu >
218 ((struct p_times *) b)->pt_pctcpu)? -1: 1;
219 }
220