Merge branch 'master' of /home/aggelos/devel/dfly/dfly.git/
[dragonfly.git] / usr.bin / systat / vmmeter.c
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 }