Blob


1 #include <u.h>
2 #include <kvm.h>
3 #include <nlist.h>
4 #include <sys/types.h>
5 #include <sys/protosw.h>
6 #include <sys/socket.h>
7 #include <sys/sysctl.h>
8 #include <sys/time.h>
9 #include <sys/dkstat.h>
10 #include <net/if.h>
11 #include <net/if_var.h>
12 #include <net/if_dl.h>
13 #include <net/if_types.h>
14 #if __FreeBSD_version < 600000
15 #include <machine/apm_bios.h>
16 #endif
17 #include <sys/ioctl.h>
18 #include <limits.h>
19 #include <libc.h>
20 #include <bio.h>
21 #include "dat.h"
23 /* XXX: #if __FreeBSD_version */
25 void xapm(int);
26 void xloadavg(int);
27 void xcpu(int);
28 void xswap(int);
29 void xsysctl(int);
30 void xnet(int);
31 void xkvm(int);
33 void (*statfn[])(int) =
34 {
35 xkvm,
36 xapm,
37 xloadavg,
38 xswap,
39 xcpu,
40 xsysctl,
41 xnet,
42 0
43 };
45 static kvm_t *kvm;
47 static struct nlist nl[] = {
48 { "_ifnet" },
49 { "_cp_time" },
50 { "" }
51 };
53 void
54 kvminit(void)
55 {
56 char buf[_POSIX2_LINE_MAX];
58 if(kvm)
59 return;
60 kvm = kvm_openfiles(nil, nil, nil, OREAD, buf);
61 if(kvm == nil)
62 return;
63 if(kvm_nlist(kvm, nl) < 0 || nl[0].n_type == 0){
64 kvm = nil;
65 return;
66 }
67 }
69 void
70 xkvm(int first)
71 {
72 if(first)
73 kvminit();
74 }
76 int
77 kread(ulong addr, char *buf, int size)
78 {
79 if(kvm_read(kvm, addr, buf, size) != size){
80 memset(buf, 0, size);
81 return -1;
82 }
83 return size;
84 }
86 void
87 xnet(int first)
88 {
89 ulong out, in, outb, inb, err;
90 static ulong ifnetaddr;
91 ulong addr;
92 struct ifnet ifnet;
93 struct ifnethead ifnethead;
94 char name[16];
96 if(first)
97 return;
99 if(ifnetaddr == 0){
100 ifnetaddr = nl[0].n_value;
101 if(ifnetaddr == 0)
102 return;
105 if(kread(ifnetaddr, (char*)&ifnethead, sizeof ifnethead) < 0)
106 return;
108 out = in = outb = inb = err = 0;
109 addr = (ulong)TAILQ_FIRST(&ifnethead);
110 while(addr){
111 #if __FreeBSD_version < 500000
112 if(kread(addr, (char*)&ifnet, sizeof ifnet) < 0
113 || kread((ulong)ifnet.if_name, name, 16) < 0)
114 return;
115 #else
116 if(kread(addr, (char*)&ifnet, sizeof ifnet) < 0
117 || kread((ulong)ifnet.if_dname, name, 16) < 0)
118 return;
119 #endif
120 name[15] = 0;
121 addr = (ulong)TAILQ_NEXT(&ifnet, if_link);
122 out += ifnet.if_opackets;
123 in += ifnet.if_ipackets;
124 outb += ifnet.if_obytes;
125 inb += ifnet.if_ibytes;
126 err += ifnet.if_oerrors+ifnet.if_ierrors;
128 Bprint(&bout, "etherin %lud 1000\n", in);
129 Bprint(&bout, "etherout %lud 1000\n", out);
130 Bprint(&bout, "etherinb %lud 1000000\n", inb);
131 Bprint(&bout, "etheroutb %lud 1000000\n", outb);
132 Bprint(&bout, "ethererr %lud 1000\n", err);
133 Bprint(&bout, "ether %lud 1000\n", in+out);
134 Bprint(&bout, "etherb %lud 1000000\n", inb+outb);
137 #if __FreeBSD_version >= 500000
138 int
139 xacpi(int first)
141 int rv;
142 int val;
143 size_t len;
145 len = sizeof(val);
146 rv = sysctlbyname("hw.acpi.battery.life", &val, &len, nil, 0);
147 if(rv != 0)
148 return -1;
149 Bprint(&bout, "battery =%d 100\n", val);
150 return 0;
152 #else
153 int
154 xacpi(int first)
156 return -1;
158 #endif
160 #if __FreeBSD_version < 600000
161 void
162 xapm(int first)
164 static int fd;
165 struct apm_info ai;
167 if(first){
168 xacpi(first);
169 fd = open("/dev/apm", OREAD);
170 return;
173 if(xacpi(0) >= 0)
174 return;
176 if(ioctl(fd, APMIO_GETINFO, &ai) < 0)
177 return;
179 if(ai.ai_batt_life <= 100)
180 Bprint(&bout, "battery =%d 100\n", ai.ai_batt_life);
182 #else
183 void
184 xapm(int first)
186 xacpi(first);
188 #endif
190 int
191 rsys(char *name, char *buf, int len)
193 size_t l;
195 l = len;
196 if(sysctlbyname(name, buf, &l, nil, 0) < 0)
197 return -1;
198 buf[l] = 0;
199 return l;
202 vlong
203 isys(char *name)
205 ulong u;
206 size_t l;
208 l = sizeof u;
209 if(sysctlbyname(name, &u, &l, nil, 0) < 0)
210 return -1;
211 return u;
214 void
215 xsysctl(int first)
217 static int pgsize;
219 if(first){
220 pgsize = isys("vm.stats.vm.v_page_size");
221 if(pgsize == 0)
222 pgsize = 4096;
225 Bprint(&bout, "mem =%lld %lld\n",
226 isys("vm.stats.vm.v_active_count")*pgsize,
227 isys("vm.stats.vm.v_page_count")*pgsize);
228 Bprint(&bout, "context %lld 1000\n", isys("vm.stats.sys.v_swtch"));
229 Bprint(&bout, "syscall %lld 1000\n", isys("vm.stats.sys.v_syscall"));
230 Bprint(&bout, "intr %lld 1000\n", isys("vm.stats.sys.v_intr")+isys("vm.stats.sys.v_trap"));
231 Bprint(&bout, "fault %lld 1000\n", isys("vm.stats.vm.v_vm_faults"));
232 Bprint(&bout, "fork %lld 1000\n", isys("vm.stats.vm.v_forks")
233 +isys("vm.stats.vm.v_rforks")
234 +isys("vm.stats.vm.v_vforks"));
237 void
238 xcpu(int first)
240 static int stathz;
241 ulong x[20];
242 struct clockinfo *ci;
243 int n;
245 if(first){
246 if(rsys("kern.clockrate", (char*)&x, sizeof x) < sizeof ci)
247 stathz = 128;
248 else{
249 ci = (struct clockinfo*)x;
250 stathz = ci->stathz;
252 return;
255 if((n=rsys("kern.cp_time", (char*)x, sizeof x)) < 5*sizeof(ulong))
256 return;
258 Bprint(&bout, "user %lud %d\n", x[CP_USER]+x[CP_NICE], stathz);
259 Bprint(&bout, "sys %lud %d\n", x[CP_SYS], stathz);
260 Bprint(&bout, "cpu %lud %d\n", x[CP_USER]+x[CP_NICE]+x[CP_SYS], stathz);
261 Bprint(&bout, "idle %lud %d\n", x[CP_IDLE], stathz);
264 void
265 xloadavg(int first)
267 double l[3];
269 if(first)
270 return;
272 if(getloadavg(l, 3) < 0)
273 return;
274 Bprint(&bout, "load =%d 1000\n", (int)(l[0]*1000.0));
277 void
278 xswap(int first)
280 static struct kvm_swap s;
281 static ulong pgin, pgout;
282 int i, o;
283 static int pgsize;
285 if(first){
286 pgsize = getpagesize();
287 if(pgsize == 0)
288 pgsize = 4096;
289 return;
292 if(kvm == nil)
293 return;
295 i = isys("vm.stats.vm.v_swappgsin");
296 o = isys("vm.stats.vm.v_swappgsout");
297 if(i != pgin || o != pgout){
298 pgin = i;
299 pgout = o;
300 kvm_getswapinfo(kvm, &s, 1, 0);
304 Bprint(&bout, "swap =%lld %lld\n", s.ksw_used*(vlong)pgsize, s.ksw_total*(vlong)pgsize);