xref: /dragonfly/usr.bin/systat/vmmeter.c (revision fb151170)
1 #define _KERNEL_STRUCTURES
2 #include <sys/param.h>
3 #include <sys/sysctl.h>
4 #include <sys/vmmeter.h>
5 #include "symbols.h"
6 
7 #include <err.h>
8 #include <kinfo.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <devstat.h>
13 
14 #include "systat.h"
15 #include "extern.h"
16 
17 #define X_START		1
18 #define CPU_START	1
19 #define CPU_STARTX	(3 + vmm_ncpus)
20 #define CPU_LABEL_W	7
21 
22 #define DRAW_ROW(n, y, w, fmt, args...) \
23 do { \
24 	mvprintw(y, n, fmt, w, args); \
25 	n += w; \
26 } while (0)
27 
28 static int vmm_ncpus;
29 static int vmm_fetched;
30 static struct vmmeter *vmm_cur, *vmm_prev;
31 static struct kinfo_cputime *vmm_cptime_cur, *vmm_cptime_prev;
32 #if 0
33 static struct save_ctx symctx;
34 #endif
35 static int symbols_read;
36 
37 static void
38 getvmm(void)
39 {
40 	size_t sz;
41 	int i;
42 
43 	for (i = 0; i < vmm_ncpus; ++i) {
44 		struct vmmeter *vmm = &vmm_cur[i];
45 		char buf[64];
46 
47 		sz = sizeof(*vmm);
48 		snprintf(buf, sizeof(buf), "vm.cpu%d.vmmeter", i);
49 		if (sysctlbyname(buf, vmm, &sz, NULL, 0))
50 			err(1, "sysctlbyname(cpu%d)", i);
51 
52 		vmm->v_intr -= (vmm->v_timer + vmm->v_ipi);
53 	}
54 
55 	sz = vmm_ncpus * sizeof(struct kinfo_cputime);
56 	if (sysctlbyname("kern.cputime", vmm_cptime_cur, &sz, NULL, 0))
57 		err(1, "kern.cputime");
58 }
59 
60 int
61 initvmm(void)
62 {
63 	return 1;
64 }
65 
66 void
67 showvmm(void)
68 {
69 	int i, n;
70 
71 	if (!vmm_fetched)
72 		return;
73 
74 	for (i = 0; i < vmm_ncpus; ++i) {
75 		struct kinfo_cputime d;
76 		uint64_t cp_total = 0;
77 
78 		n = X_START + CPU_LABEL_W;
79 
80 #define D(idx, field) \
81 	(vmm_cur[idx].field - vmm_prev[idx].field) / (u_int)naptime
82 
83 		DRAW_ROW(n, CPU_START + i, 6, "%*u", D(i, v_timer));
84 		DRAW_ROW(n, CPU_START + i, 8, "%*u", D(i, v_ipi));
85 		DRAW_ROW(n, CPU_START + i, 8, "%*u", D(i, v_intr));
86 
87 #undef D
88 
89 #define CPUD(dif, idx, field) \
90 do { \
91 	dif.cp_##field = vmm_cptime_cur[idx].cp_##field - \
92 			 vmm_cptime_prev[idx].cp_##field; \
93 	cp_total += dif.cp_##field; \
94 } while (0)
95 
96 #define CPUV(dif, field) \
97 	(dif.cp_##field * 100.0) / cp_total
98 
99 		CPUD(d, i, user);
100 		CPUD(d, i, idle);
101 		CPUD(d, i, intr);
102 		CPUD(d, i, nice);
103 		CPUD(d, i, sys);
104 
105 		if (cp_total == 0)
106 			cp_total = 1;
107 
108 		DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, user));
109 		DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, nice));
110 		DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, sys));
111 		DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, intr));
112 		DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, idle));
113 
114 #undef CPUV
115 #undef CPUD
116 #define CPUC(idx, field) vmm_cptime_cur[idx].cp_##field
117 
118 #if 0
119 		n = X_START + CPU_LABEL_W;
120 
121 		DRAW_ROW(n, CPU_STARTX + i, 15, "%-*s", CPUC(i, msg));
122 		DRAW_ROW(n, CPU_STARTX + i, 35, "%-*s",
123 			address_to_symbol((void *)(intptr_t)CPUC(i, stallpc),
124 					  &symctx));
125 #endif
126 #undef CPUC
127 	}
128 }
129 
130 void
131 fetchvmm(void)
132 {
133 	vmm_fetched = 1;
134 
135 	memcpy(vmm_prev, vmm_cur, sizeof(struct vmmeter) * vmm_ncpus);
136 	memcpy(vmm_cptime_prev, vmm_cptime_cur,
137 	       sizeof(struct kinfo_cputime) * vmm_ncpus);
138 	getvmm();
139 }
140 
141 void
142 labelvmm(void)
143 {
144 	int i, n;
145 
146 	clear();
147 
148 	n = X_START + CPU_LABEL_W;
149 
150 	DRAW_ROW(n, CPU_START - 1, 6, "%*s", "timer");
151 	DRAW_ROW(n, CPU_START - 1, 8, "%*s", "ipi");
152 	DRAW_ROW(n, CPU_START - 1, 8, "%*s", "extint");
153 	DRAW_ROW(n, CPU_START - 1, 7, "%*s", "user%");
154 	DRAW_ROW(n, CPU_START - 1, 7, "%*s", "nice%");
155 	DRAW_ROW(n, CPU_START - 1, 7, "%*s", "sys%");
156 	DRAW_ROW(n, CPU_START - 1, 7, "%*s", "intr%");
157 	DRAW_ROW(n, CPU_START - 1, 7, "%*s", "idle%");
158 
159 	for (i = 0; i < vmm_ncpus; ++i)
160 		mvprintw(CPU_START + i, X_START, "cpu%d", i);
161 
162 #if 0
163 	n = X_START + CPU_LABEL_W;
164 	DRAW_ROW(n, CPU_STARTX - 1, 15, "%-*s", "contention");
165 	DRAW_ROW(n, CPU_STARTX - 1, 35, "%-*s", "function");
166 
167 	for (i = 0; i < vmm_ncpus; ++i)
168 		mvprintw(CPU_STARTX + i, X_START, "cpu%d", i);
169 #endif
170 }
171 
172 WINDOW *
173 openvmm(void)
174 {
175 	if (symbols_read == 0) {
176 		symbols_read = 1;
177 		read_symbols(NULL);
178 	}
179 
180 	if (kinfo_get_cpus(&vmm_ncpus))
181 		err(1, "kinfo_get_cpus");
182 
183 	vmm_cur = calloc(vmm_ncpus, sizeof(*vmm_cur));
184 	if (vmm_cur == NULL)
185 		err(1, "calloc vmm_cur");
186 
187 	vmm_prev = calloc(vmm_ncpus, sizeof(*vmm_prev));
188 	if (vmm_prev == NULL)
189 		err(1, "calloc vmm_prev");
190 
191 	vmm_cptime_cur = calloc(vmm_ncpus, sizeof(*vmm_cptime_cur));
192 	if (vmm_cptime_cur == NULL)
193 		err(1, "calloc vmm_cptime_cur");
194 
195 	vmm_cptime_prev = calloc(vmm_ncpus, sizeof(*vmm_cptime_prev));
196 	if (vmm_cptime_prev == NULL)
197 		err(1, "calloc vmm_cptime_prev");
198 
199 	getvmm();
200 
201 	return (stdscr);
202 }
203 
204 void
205 closevmm(WINDOW *w)
206 {
207 	if (vmm_cur != NULL)
208 		free(vmm_cur);
209 	if (vmm_prev != NULL)
210 		free(vmm_prev);
211 
212 	if (vmm_cptime_cur != NULL)
213 		free(vmm_cptime_cur);
214 	if (vmm_cptime_prev != NULL)
215 		free(vmm_cptime_prev);
216 
217 	vmm_fetched = 0;
218 
219 	if (w == NULL)
220 		return;
221 	wclear(w);
222 	wrefresh(w);
223 }
224