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