1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1980, 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 /*
34 * Pigs display from Bill Reeves at Lucasfilm
35 */
36
37 #include <sys/param.h>
38 #include <sys/proc.h>
39 #include <sys/sysctl.h>
40 #include <sys/time.h>
41 #include <sys/user.h>
42
43 #include <curses.h>
44 #include <math.h>
45 #include <pwd.h>
46 #include <stdlib.h>
47
48 #include "systat.h"
49 #include "extern.h"
50
51 int compar(const void *, const void *);
52
53 static int nproc;
54 static struct p_times {
55 float pt_pctcpu;
56 struct kinfo_proc *pt_kp;
57 } *pt = NULL;
58
59 static int fscale;
60 static double lccpu;
61
62 WINDOW *
openpigs(void)63 openpigs(void)
64 {
65 return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
66 }
67
68 void
closepigs(WINDOW * w)69 closepigs(WINDOW *w)
70 {
71 if (w == NULL)
72 return;
73 wclear(w);
74 wrefresh(w);
75 delwin(w);
76 }
77
78 void
showpigs(void)79 showpigs(void)
80 {
81 int i, j, y, k;
82 const char *uname, *pname;
83 char pidname[30];
84
85 if (nproc == 0)
86 return;
87
88 qsort(pt, nproc, sizeof (struct p_times), compar);
89 y = 1;
90 i = nproc;
91 if (i > getmaxy(wnd)-2)
92 i = getmaxy(wnd)-2;
93 for (k = 0; i > 0 && pt[k].pt_pctcpu > 0.01; i--, y++, k++) {
94 uname = user_from_uid(pt[k].pt_kp->ki_uid, 0);
95 pname = pt[k].pt_kp->ki_comm;
96 wmove(wnd, y, 0);
97 wclrtoeol(wnd);
98 mvwaddstr(wnd, y, 0, uname);
99 snprintf(pidname, sizeof(pidname), "%10.10s", pname);
100 mvwaddstr(wnd, y, 9, pidname);
101 wmove(wnd, y, 20);
102 for (j = pt[k].pt_pctcpu * 50 + 0.5; j > 0; j--)
103 waddch(wnd, 'X');
104 }
105 wmove(wnd, y, 0); wclrtobot(wnd);
106 }
107
108 int
initpigs(void)109 initpigs(void)
110 {
111 fixpt_t ccpu;
112 size_t len;
113 int err;
114
115 len = sizeof(ccpu);
116 err = sysctlbyname("kern.ccpu", &ccpu, &len, NULL, 0);
117 if (err || len != sizeof(ccpu)) {
118 perror("kern.ccpu");
119 return (0);
120 }
121
122 len = sizeof(fscale);
123 err = sysctlbyname("kern.fscale", &fscale, &len, NULL, 0);
124 if (err || len != sizeof(fscale)) {
125 perror("kern.fscale");
126 return (0);
127 }
128
129 lccpu = log((double) ccpu / fscale);
130
131 return(1);
132 }
133
134 void
fetchpigs(void)135 fetchpigs(void)
136 {
137 int i;
138 float ftime;
139 float *pctp;
140 struct kinfo_proc *kpp;
141 static int maxnproc = 0;
142
143 if ((kpp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc)) == NULL) {
144 error("%s", kvm_geterr(kd));
145 nproc = 0;
146 return;
147 }
148 if (nproc > maxnproc) {
149 if ((pt = realloc(pt, nproc * sizeof(*pt))) == NULL) {
150 error("Out of memory");
151 die(0);
152 }
153 maxnproc = nproc;
154 }
155 /*
156 * calculate %cpu for each proc
157 */
158 for (i = 0; i < nproc; i++) {
159 pt[i].pt_kp = &kpp[i];
160 pctp = &pt[i].pt_pctcpu;
161 ftime = kpp[i].ki_swtime;
162 if (ftime == 0 || (kpp[i].ki_flag & P_INMEM) == 0)
163 *pctp = 0;
164 else
165 *pctp = ((double) kpp[i].ki_pctcpu /
166 fscale) / (1.0 - exp(ftime * lccpu));
167 }
168 }
169
170 void
labelpigs(void)171 labelpigs(void)
172 {
173 wmove(wnd, 0, 0);
174 wclrtoeol(wnd);
175 mvwaddstr(wnd, 0, 20,
176 "/0% /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
177 }
178
179 int
compar(const void * a,const void * b)180 compar(const void *a, const void *b)
181 {
182 return (((const struct p_times *) a)->pt_pctcpu >
183 ((const struct p_times *) b)->pt_pctcpu)? -1: 1;
184 }
185