wg.conf.5: Fix a typo (in-inline comments are *not* allowed)
[dragonfly.git] / usr.bin / systat / vmmeter.c
blobb035177d62e5d3a0b896f323f2928e969148e36c
1 #define _KERNEL_STRUCTURES
2 #include <sys/param.h>
3 #include <sys/sysctl.h>
4 #include <sys/vmmeter.h>
5 #include "symbols.h"
7 #include <err.h>
8 #include <kinfo.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <string.h>
13 #include <devstat.h>
15 #include "systat.h"
16 #include "extern.h"
18 #define X_START 1
19 #define TOT_START 1
20 #define CPU_START 3
21 #define CPU_STARTX (CPU_START + 1 + vmm_ncpus)
22 #define CPU_LABEL_W 7
24 #define DRAW_ROW(n, y, w, fmt, args...) \
25 do { \
26 mvprintw(y, n, fmt, w - 1, args); \
27 n += w; \
28 } while (0)
30 #define DRAW_ROW2(n, y, w, fmt, args...) \
31 do { \
32 mvprintw(y, n, fmt, w - 1, w - 1, args);\
33 n += w; \
34 } while (0)
36 #define DRAW_ROWX(n, y, w, fmt, args...) \
37 do { \
38 mvprintw(y, n, fmt, args); \
39 n += w; \
40 } while (0)
42 static int vmm_ncpus;
43 static int vmm_fetched;
44 static struct vmmeter vmm_totcur, vmm_totprev;
45 static struct vmmeter *vmm_cur, *vmm_prev;
46 static struct kinfo_cputime *vmm_cptime_cur, *vmm_cptime_prev;
47 static struct save_ctx symctx;
48 static int symbols_read;
50 static void
51 getvmm(void)
53 size_t sz;
54 int i;
56 vmm_totcur.v_timer = 0;
57 vmm_totcur.v_ipi = 0;
58 vmm_totcur.v_intr = 0;
59 vmm_totcur.v_lock_colls = 0;
61 for (i = 0; i < vmm_ncpus; ++i) {
62 struct vmmeter *vmm = &vmm_cur[i];
63 char buf[64];
65 sz = sizeof(*vmm);
66 snprintf(buf, sizeof(buf), "vm.cpu%d.vmmeter", i);
67 if (sysctlbyname(buf, vmm, &sz, NULL, 0))
68 err(1, "sysctlbyname(cpu%d)", i);
70 vmm->v_intr -= (vmm->v_timer + vmm->v_ipi);
72 vmm_totcur.v_timer += vmm->v_timer;
73 vmm_totcur.v_ipi += vmm->v_ipi;
74 vmm_totcur.v_intr += vmm->v_intr;
75 vmm_totcur.v_lock_colls += vmm->v_lock_colls;
78 sz = vmm_ncpus * sizeof(struct kinfo_cputime);
79 if (sysctlbyname("kern.cputime", vmm_cptime_cur, &sz, NULL, 0))
80 err(1, "kern.cputime");
83 int
84 initvmm(void)
86 return 1;
89 #define D(idx, field) \
90 (u_int)((vmm_cur[idx].field - vmm_prev[idx].field) / naptime)
92 #define CPUD(dif, idx, field) \
93 do { \
94 dif.cp_##field = vmm_cptime_cur[idx].cp_##field - \
95 vmm_cptime_prev[idx].cp_##field; \
96 dtot.cp_##field += vmm_cptime_cur[idx].cp_##field - \
97 vmm_cptime_prev[idx].cp_##field; \
98 cp_total += dif.cp_##field; \
99 cp_total_all += dif.cp_##field; \
100 } while (0)
102 #define CPUV(dif, field) \
103 (dif.cp_##field * 100.0) / cp_total
105 #define CPUC(idx, field) vmm_cptime_cur[idx].cp_##field
107 #define CPUVTOT(field) \
108 (dtot.cp_##field * 100.0) / cp_total_all
110 #define DTOT(field) \
111 (u_int)((vmm_totcur.field - vmm_totprev.field) / naptime)
114 void
115 showvmm(void)
117 struct kinfo_cputime dtot;
118 uint64_t cp_total_all = 0;
119 int i, n;
121 if (!vmm_fetched)
122 return;
124 bzero(&dtot, sizeof(dtot));
126 for (i = 0; i < vmm_ncpus; ++i) {
127 struct kinfo_cputime d;
128 uint64_t cp_total = 0;
130 n = X_START + CPU_LABEL_W;
132 DRAW_ROW(n, CPU_START + i, 6, "%*u", D(i, v_timer));
133 DRAW_ROW(n, CPU_START + i, 8, "%*u", D(i, v_ipi));
134 DRAW_ROW(n, CPU_START + i, 8, "%*u", D(i, v_intr));
136 CPUD(d, i, user);
137 CPUD(d, i, idle);
138 CPUD(d, i, intr);
139 CPUD(d, i, nice);
140 CPUD(d, i, sys);
142 if (cp_total == 0)
143 cp_total = 1;
145 DRAW_ROW(n, CPU_START + i, 6, "%*.1f",
146 CPUV(d, user) + CPUV(d, nice));
147 DRAW_ROW(n, CPU_START + i, 6, "%*.1f", CPUV(d, sys));
148 DRAW_ROW(n, CPU_START + i, 6, "%*.1f", CPUV(d, intr));
149 DRAW_ROW(n, CPU_START + i, 6, "%*.1f", CPUV(d, idle));
152 * Display token collision count and the last-colliding
153 * token name.
155 if (D(i, v_lock_colls) > 9999999)
156 DRAW_ROW(n, CPU_START + i, 8, "%*u", 9999999);
157 else
158 DRAW_ROW(n, CPU_START + i, 8, "%*u",
159 D(i, v_lock_colls));
161 if (D(i, v_lock_colls) == 0) {
162 DRAW_ROW2(n, CPU_START + i, (WideMode ? 24 : 16),
163 "%*.*s", "");
164 if (WideMode)
165 DRAW_ROW2(n, CPU_START + i, 17, "%*.*s", "");
166 } else {
167 DRAW_ROW2(n, CPU_START + i, (WideMode ? 24 : 16),
168 "%*.*s",
169 vmm_cur[i].v_lock_name);
170 if (WideMode) {
171 DRAW_ROWX(n, CPU_START + i, 17,
172 "%016lx",
173 (uintmax_t)(uintptr_t)
174 vmm_cur[i].v_lock_addr);
178 if (WideMode && vmm_cptime_cur[i].cp_sample_pc) {
179 void *rip;
181 rip = (void *)(intptr_t)CPUC(i, sample_pc);
182 DRAW_ROW2(n, CPU_START + i, 30, "%*.*s",
183 address_to_symbol(rip, &symctx));
188 * Top row totals and averages
190 if (cp_total_all == 0)
191 cp_total_all = 1;
193 n = X_START + CPU_LABEL_W;
194 DRAW_ROW(n, TOT_START, 6, "%*u", DTOT(v_timer)); /* timer */
195 DRAW_ROW(n, TOT_START, 8, "%*u", DTOT(v_ipi)); /* ipi */
196 DRAW_ROW(n, TOT_START, 8, "%*u", DTOT(v_intr)); /* extint */
198 DRAW_ROW(n, TOT_START, 6, "%*.1f", CPUVTOT(user) + /* user */
199 CPUVTOT(nice));
200 DRAW_ROW(n, TOT_START, 6, "%*.1f", CPUVTOT(sys)); /* sys */
201 DRAW_ROW(n, TOT_START, 6, "%*.1f", CPUVTOT(intr)); /* intr */
202 DRAW_ROW(n, TOT_START, 6, "%*.1f", CPUVTOT(idle)); /* idle */
204 DRAW_ROWX(n, TOT_START, 8, "%7u", DTOT(v_lock_colls));
205 DRAW_ROWX(n, TOT_START, 0, " (%5.2f%% coltot)",
206 (double)DTOT(v_lock_colls) / 1000000.0);
209 void
210 fetchvmm(void)
212 vmm_fetched = 1;
214 memcpy(vmm_prev, vmm_cur, sizeof(struct vmmeter) * vmm_ncpus);
215 memcpy(vmm_cptime_prev, vmm_cptime_cur,
216 sizeof(struct kinfo_cputime) * vmm_ncpus);
217 vmm_totprev = vmm_totcur;
218 getvmm();
221 void
222 labelvmm(void)
224 int i, n;
226 clear();
228 n = X_START + CPU_LABEL_W;
230 DRAW_ROW(n, TOT_START - 1, 6, "%*s", "timer");
231 DRAW_ROW(n, TOT_START - 1, 8, "%*s", "ipi");
232 DRAW_ROW(n, TOT_START - 1, 8, "%*s", "extint");
233 DRAW_ROW(n, TOT_START - 1, 6, "%*s", "user%");
234 DRAW_ROW(n, TOT_START - 1, 6, "%*s", "sys%");
235 DRAW_ROW(n, TOT_START - 1, 6, "%*s", "intr%");
236 DRAW_ROW(n, TOT_START - 1, 6, "%*s", "idle%");
237 DRAW_ROW(n, TOT_START - 1, 8, "%*s", "smpcol");
238 DRAW_ROW(n, TOT_START - 1, (WideMode ? 24 : 16), "%*s", "contention");
239 if (WideMode) {
240 DRAW_ROW(n, TOT_START - 1, 17, "%*s", "lockaddr");
242 if (WideMode && getuid() == 0) {
243 DRAW_ROW(n, TOT_START - 1, 30, "%*s", "sample_pc");
246 n = X_START + CPU_LABEL_W;
247 DRAW_ROW(n, TOT_START + 1, 6, "%*s", "-----");
248 DRAW_ROW(n, TOT_START + 1, 8, "%*s", "-------");
249 DRAW_ROW(n, TOT_START + 1, 8, "%*s", "-------");
250 DRAW_ROW(n, TOT_START + 1, 6, "%*s", "-----");
251 DRAW_ROW(n, TOT_START + 1, 6, "%*s", "-----");
252 DRAW_ROW(n, TOT_START + 1, 6, "%*s", "-----");
253 DRAW_ROW(n, TOT_START + 1, 6, "%*s", "-----");
254 DRAW_ROW(n, TOT_START + 1, 8, "%*s", "-------");
255 DRAW_ROW(n, TOT_START + 1, (WideMode ? 24 : 16),
256 "%*s",
257 (WideMode ? "-----------------------" : "---------------"));
258 if (WideMode)
259 DRAW_ROW(n, TOT_START + 1, 17, "%*s", "---------------");
260 if (WideMode && getuid() == 0) {
261 DRAW_ROW(n, TOT_START + 1, 30,
262 "%*s", "-----------------------------");
265 mvprintw(TOT_START, X_START, "total");
266 for (i = 0; i < vmm_ncpus; ++i)
267 mvprintw(CPU_START + i, X_START, "cpu%d", i);
269 #if 0
270 n = X_START + CPU_LABEL_W;
271 DRAW_ROW(n, TOT_STARTX - 1, 15, "%-*s", "contention");
272 DRAW_ROW(n, TOT_STARTX - 1, 35, "%-*s", "function");
274 for (i = 0; i < vmm_ncpus; ++i)
275 mvprintw(CPU_STARTX + i, X_START, "cpu%d", i);
276 #endif
279 WINDOW *
280 openvmm(void)
282 if (symbols_read == 0) {
283 symbols_read = 1;
284 read_symbols(NULL);
287 if (kinfo_get_cpus(&vmm_ncpus))
288 err(1, "kinfo_get_cpus");
290 vmm_cur = calloc(vmm_ncpus, sizeof(*vmm_cur));
291 if (vmm_cur == NULL)
292 err(1, "calloc vmm_cur");
294 vmm_prev = calloc(vmm_ncpus, sizeof(*vmm_prev));
295 if (vmm_prev == NULL)
296 err(1, "calloc vmm_prev");
298 vmm_cptime_cur = calloc(vmm_ncpus, sizeof(*vmm_cptime_cur));
299 if (vmm_cptime_cur == NULL)
300 err(1, "calloc vmm_cptime_cur");
302 vmm_cptime_prev = calloc(vmm_ncpus, sizeof(*vmm_cptime_prev));
303 if (vmm_cptime_prev == NULL)
304 err(1, "calloc vmm_cptime_prev");
306 getvmm();
308 return (stdscr);
311 void
312 closevmm(WINDOW *w)
314 if (vmm_cur != NULL)
315 free(vmm_cur);
316 if (vmm_prev != NULL)
317 free(vmm_prev);
319 if (vmm_cptime_cur != NULL)
320 free(vmm_cptime_cur);
321 if (vmm_cptime_prev != NULL)
322 free(vmm_cptime_prev);
324 vmm_fetched = 0;
326 if (w == NULL)
327 return;
328 wclear(w);
329 wrefresh(w);