1 #define _KERNEL_STRUCTURES
3 #include <sys/sysctl.h>
4 #include <sys/vmmeter.h>
21 #define CPU_STARTX (3 + 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); \
37 static int vmm_fetched
;
38 static struct vmmeter vmm_totcur
, vmm_totprev
;
39 static struct vmmeter
*vmm_cur
, *vmm_prev
;
40 static struct kinfo_cputime
*vmm_cptime_cur
, *vmm_cptime_prev
;
41 static struct save_ctx symctx
;
42 static int symbols_read
;
51 vmm_totcur
.v_intr
= 0;
52 vmm_totcur
.v_lock_colls
= 0;
54 for (i
= 0; i
< vmm_ncpus
; ++i
) {
55 struct vmmeter
*vmm
= &vmm_cur
[i
];
59 snprintf(buf
, sizeof(buf
), "vm.cpu%d.vmmeter", i
);
60 if (sysctlbyname(buf
, vmm
, &sz
, NULL
, 0))
61 err(1, "sysctlbyname(cpu%d)", i
);
63 vmm
->v_intr
-= (vmm
->v_timer
+ vmm
->v_ipi
);
65 vmm_totcur
.v_ipi
+= vmm
->v_ipi
;
66 vmm_totcur
.v_intr
+= vmm
->v_intr
;
67 vmm_totcur
.v_lock_colls
+= vmm
->v_lock_colls
;
70 sz
= vmm_ncpus
* sizeof(struct kinfo_cputime
);
71 if (sysctlbyname("kern.cputime", vmm_cptime_cur
, &sz
, NULL
, 0))
72 err(1, "kern.cputime");
89 n
= X_START
+ CPU_LABEL_W
;
92 (u_int)((vmm_totcur.field - vmm_totprev.field) / naptime)
94 DRAW_ROW(n
, TOT_START
, 6, "%*s", ""); /* timer */
95 DRAW_ROW(n
, TOT_START
, 8, "%*u", DTOT(v_ipi
));
96 DRAW_ROW(n
, TOT_START
, 8, "%*u", DTOT(v_intr
));
98 DRAW_ROW(n
, TOT_START
, 6, "%*s", ""); /* user */
99 /* DRAW_ROW(n, TOT_START, 6, "%*s", ""); nice */
100 DRAW_ROW(n
, TOT_START
, 6, "%*s", ""); /* sys */
101 DRAW_ROW(n
, TOT_START
, 6, "%*s", ""); /* intr */
102 DRAW_ROW(n
, TOT_START
, 6, "%*s", ""); /* idle */
103 if (DTOT(v_lock_colls
) > 9999999)
104 DRAW_ROW(n
, TOT_START
, 8, "%*u", 9999999);
106 DRAW_ROW(n
, TOT_START
, 8, "%*u", DTOT( v_lock_colls
));
107 DRAW_ROW2(n
, TOT_START
, 18, "%*.*s", ""); /* label */
109 DRAW_ROW2(n
, TOT_START
, 30, "%*.*s", ""); /* sample_pc */
111 DRAW_ROW2(n
, TOT_START
, 20, "%*.*s", ""); /* sample_sp */
117 for (i
= 0; i
< vmm_ncpus
; ++i
) {
118 struct kinfo_cputime d
;
119 uint64_t cp_total
= 0;
121 n
= X_START
+ CPU_LABEL_W
;
123 #define D(idx, field) \
124 (u_int)((vmm_cur[idx].field - vmm_prev[idx].field) / naptime)
126 DRAW_ROW(n
, CPU_START
+ i
, 6, "%*u", D(i
, v_timer
));
127 DRAW_ROW(n
, CPU_START
+ i
, 8, "%*u", D(i
, v_ipi
));
128 DRAW_ROW(n
, CPU_START
+ i
, 8, "%*u", D(i
, v_intr
));
130 #define CPUD(dif, idx, field) \
132 dif.cp_##field = vmm_cptime_cur[idx].cp_##field - \
133 vmm_cptime_prev[idx].cp_##field; \
134 cp_total += dif.cp_##field; \
137 #define CPUV(dif, field) \
138 (dif.cp_##field * 100.0) / cp_total
149 DRAW_ROW(n
, CPU_START
+ i
, 6, "%*.1f",
150 CPUV(d
, user
) + CPUV(d
, nice
));
151 /* DRAW_ROW(n, CPU_START + i, 6, "%*.1f", CPUV(d, nice));*/
152 DRAW_ROW(n
, CPU_START
+ i
, 6, "%*.1f", CPUV(d
, sys
));
153 DRAW_ROW(n
, CPU_START
+ i
, 6, "%*.1f", CPUV(d
, intr
));
154 DRAW_ROW(n
, CPU_START
+ i
, 6, "%*.1f", CPUV(d
, idle
));
157 * Display token collision count and the last-colliding
160 if (D(i
, v_lock_colls
) > 9999999)
161 DRAW_ROW(n
, CPU_START
+ i
, 8, "%*u", 9999999);
163 DRAW_ROW(n
, CPU_START
+ i
, 8, "%*u",
166 if (D(i
, v_lock_colls
) == 0) {
167 DRAW_ROW2(n
, CPU_START
+ i
, 18, "%*.*s", "");
169 DRAW_ROW2(n
, CPU_START
+ i
, 18, "%*.*s",
170 vmm_cur
[i
].v_lock_name
);
177 #define CPUC(idx, field) vmm_cptime_cur[idx].cp_##field
179 if (vmm_cptime_cur
[i
].cp_sample_pc
) {
182 rip
= (void *)(intptr_t)CPUC(i
, sample_pc
);
183 DRAW_ROW2(n
, CPU_START
+ i
, 30, "%*.*s",
184 address_to_symbol(rip
, &symctx
));
186 DRAW_ROW(n
, CPU_START
+ i
, 19, " %016jx",
199 memcpy(vmm_prev
, vmm_cur
, sizeof(struct vmmeter
) * vmm_ncpus
);
200 memcpy(vmm_cptime_prev
, vmm_cptime_cur
,
201 sizeof(struct kinfo_cputime
) * vmm_ncpus
);
202 vmm_totprev
= vmm_totcur
;
213 n
= X_START
+ CPU_LABEL_W
;
215 DRAW_ROW(n
, TOT_START
- 1, 6, "%*s", "timer");
216 DRAW_ROW(n
, TOT_START
- 1, 8, "%*s", "ipi");
217 DRAW_ROW(n
, TOT_START
- 1, 8, "%*s", "extint");
218 DRAW_ROW(n
, TOT_START
- 1, 6, "%*s", "user%");
219 /* DRAW_ROW(n, TOT_START - 1, 6, "%*s", "nice%");*/
220 DRAW_ROW(n
, TOT_START
- 1, 6, "%*s", "sys%");
221 DRAW_ROW(n
, TOT_START
- 1, 6, "%*s", "intr%");
222 DRAW_ROW(n
, TOT_START
- 1, 6, "%*s", "idle%");
223 DRAW_ROW(n
, TOT_START
- 1, 8, "%*s", "smpcol");
224 DRAW_ROW(n
, TOT_START
- 1, 18, "%*s", "label");
226 DRAW_ROW(n
, TOT_START
- 1, 30, "%*s", "sample_pc");
228 DRAW_ROW(n
, TOT_START
- 1, 18, "%*s", "sample_sp");
232 mvprintw(TOT_START
, X_START
, "total");
233 for (i
= 0; i
< vmm_ncpus
; ++i
)
234 mvprintw(CPU_START
+ i
, X_START
, "cpu%d", i
);
237 n
= X_START
+ CPU_LABEL_W
;
238 DRAW_ROW(n
, TOT_STARTX
- 1, 15, "%-*s", "contention");
239 DRAW_ROW(n
, TOT_STARTX
- 1, 35, "%-*s", "function");
241 for (i
= 0; i
< vmm_ncpus
; ++i
)
242 mvprintw(CPU_STARTX
+ i
, X_START
, "cpu%d", i
);
249 if (symbols_read
== 0) {
254 if (kinfo_get_cpus(&vmm_ncpus
))
255 err(1, "kinfo_get_cpus");
257 vmm_cur
= calloc(vmm_ncpus
, sizeof(*vmm_cur
));
259 err(1, "calloc vmm_cur");
261 vmm_prev
= calloc(vmm_ncpus
, sizeof(*vmm_prev
));
262 if (vmm_prev
== NULL
)
263 err(1, "calloc vmm_prev");
265 vmm_cptime_cur
= calloc(vmm_ncpus
, sizeof(*vmm_cptime_cur
));
266 if (vmm_cptime_cur
== NULL
)
267 err(1, "calloc vmm_cptime_cur");
269 vmm_cptime_prev
= calloc(vmm_ncpus
, sizeof(*vmm_cptime_prev
));
270 if (vmm_cptime_prev
== NULL
)
271 err(1, "calloc vmm_cptime_prev");
283 if (vmm_prev
!= NULL
)
286 if (vmm_cptime_cur
!= NULL
)
287 free(vmm_cptime_cur
);
288 if (vmm_cptime_prev
!= NULL
)
289 free(vmm_cptime_prev
);