1 #define _KERNEL_STRUCTURES
3 #include <sys/sysctl.h>
4 #include <sys/vmmeter.h>
21 #define CPU_STARTX (CPU_START + 1 + vmm_ncpus)
24 #define DRAW_ROW(n, y, w, fmt, args...) \
26 mvprintw(y, n, fmt, w - 1, args); \
30 #define DRAW_ROW2(n, y, w, fmt, args...) \
32 mvprintw(y, n, fmt, w - 1, w - 1, args);\
36 #define DRAW_ROWX(n, y, w, fmt, args...) \
38 mvprintw(y, n, fmt, args); \
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
;
56 vmm_totcur
.v_timer
= 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
];
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");
89 #define D(idx, field) \
90 (u_int)((vmm_cur[idx].field - vmm_prev[idx].field) / naptime)
92 #define CPUD(dif, idx, field) \
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; \
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)
117 struct kinfo_cputime dtot
;
118 uint64_t cp_total_all
= 0;
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
));
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
155 if (D(i
, v_lock_colls
) > 9999999)
156 DRAW_ROW(n
, CPU_START
+ i
, 8, "%*u", 9999999);
158 DRAW_ROW(n
, CPU_START
+ i
, 8, "%*u",
161 if (D(i
, v_lock_colls
) == 0) {
162 DRAW_ROW2(n
, CPU_START
+ i
, (WideMode
? 24 : 16),
165 DRAW_ROW2(n
, CPU_START
+ i
, 17, "%*.*s", "");
167 DRAW_ROW2(n
, CPU_START
+ i
, (WideMode
? 24 : 16),
169 vmm_cur
[i
].v_lock_name
);
171 DRAW_ROWX(n
, CPU_START
+ i
, 17,
173 (uintmax_t)(uintptr_t)
174 vmm_cur
[i
].v_lock_addr
);
178 if (WideMode
&& vmm_cptime_cur
[i
].cp_sample_pc
) {
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)
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 */
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);
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
;
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");
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),
257 (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
);
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
);
282 if (symbols_read
== 0) {
287 if (kinfo_get_cpus(&vmm_ncpus
))
288 err(1, "kinfo_get_cpus");
290 vmm_cur
= calloc(vmm_ncpus
, sizeof(*vmm_cur
));
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");
316 if (vmm_prev
!= NULL
)
319 if (vmm_cptime_cur
!= NULL
)
320 free(vmm_cptime_cur
);
321 if (vmm_cptime_prev
!= NULL
)
322 free(vmm_cptime_prev
);