vmstat.c revision 1.55 1 1.55 kleink /* $NetBSD: vmstat.c,v 1.55 1999/02/12 15:04:00 kleink Exp $ */
2 1.45 thorpej
3 1.45 thorpej /*-
4 1.45 thorpej * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 1.45 thorpej * All rights reserved.
6 1.45 thorpej *
7 1.45 thorpej * This code is derived from software contributed to The NetBSD Foundation
8 1.45 thorpej * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 1.45 thorpej * NASA Ames Research Center.
10 1.45 thorpej *
11 1.45 thorpej * Redistribution and use in source and binary forms, with or without
12 1.45 thorpej * modification, are permitted provided that the following conditions
13 1.45 thorpej * are met:
14 1.45 thorpej * 1. Redistributions of source code must retain the above copyright
15 1.45 thorpej * notice, this list of conditions and the following disclaimer.
16 1.45 thorpej * 2. Redistributions in binary form must reproduce the above copyright
17 1.45 thorpej * notice, this list of conditions and the following disclaimer in the
18 1.45 thorpej * documentation and/or other materials provided with the distribution.
19 1.45 thorpej * 3. All advertising materials mentioning features or use of this software
20 1.45 thorpej * must display the following acknowledgement:
21 1.45 thorpej * This product includes software developed by the NetBSD
22 1.45 thorpej * Foundation, Inc. and its contributors.
23 1.45 thorpej * 4. Neither the name of The NetBSD Foundation nor the names of its
24 1.45 thorpej * contributors may be used to endorse or promote products derived
25 1.45 thorpej * from this software without specific prior written permission.
26 1.45 thorpej *
27 1.45 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 1.45 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 1.45 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 1.45 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 1.45 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 1.45 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 1.45 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 1.45 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 1.45 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 1.45 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 1.45 thorpej * POSSIBILITY OF SUCH DAMAGE.
38 1.45 thorpej */
39 1.21 cgd
40 1.1 cgd /*
41 1.13 cgd * Copyright (c) 1980, 1986, 1991, 1993
42 1.13 cgd * The Regents of the University of California. All rights reserved.
43 1.1 cgd *
44 1.1 cgd * Redistribution and use in source and binary forms, with or without
45 1.1 cgd * modification, are permitted provided that the following conditions
46 1.1 cgd * are met:
47 1.1 cgd * 1. Redistributions of source code must retain the above copyright
48 1.1 cgd * notice, this list of conditions and the following disclaimer.
49 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
50 1.1 cgd * notice, this list of conditions and the following disclaimer in the
51 1.1 cgd * documentation and/or other materials provided with the distribution.
52 1.1 cgd * 3. All advertising materials mentioning features or use of this software
53 1.1 cgd * must display the following acknowledgement:
54 1.1 cgd * This product includes software developed by the University of
55 1.1 cgd * California, Berkeley and its contributors.
56 1.1 cgd * 4. Neither the name of the University nor the names of its contributors
57 1.1 cgd * may be used to endorse or promote products derived from this software
58 1.1 cgd * without specific prior written permission.
59 1.1 cgd *
60 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
61 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
62 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
63 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
64 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
66 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
67 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
69 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70 1.1 cgd * SUCH DAMAGE.
71 1.1 cgd */
72 1.1 cgd
73 1.38 mrg #include <sys/cdefs.h>
74 1.1 cgd #ifndef lint
75 1.38 mrg __COPYRIGHT("@(#) Copyright (c) 1980, 1986, 1991, 1993\n\
76 1.38 mrg The Regents of the University of California. All rights reserved.\n");
77 1.1 cgd #endif /* not lint */
78 1.1 cgd
79 1.1 cgd #ifndef lint
80 1.21 cgd #if 0
81 1.37 mrg static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 3/1/95";
82 1.21 cgd #else
83 1.55 kleink __RCSID("$NetBSD: vmstat.c,v 1.55 1999/02/12 15:04:00 kleink Exp $");
84 1.21 cgd #endif
85 1.1 cgd #endif /* not lint */
86 1.1 cgd
87 1.1 cgd #include <sys/param.h>
88 1.1 cgd #include <sys/time.h>
89 1.1 cgd #include <sys/proc.h>
90 1.1 cgd #include <sys/user.h>
91 1.1 cgd #include <sys/dkstat.h>
92 1.1 cgd #include <sys/buf.h>
93 1.1 cgd #include <sys/namei.h>
94 1.1 cgd #include <sys/malloc.h>
95 1.1 cgd #include <sys/ioctl.h>
96 1.13 cgd #include <sys/sysctl.h>
97 1.18 pk #include <sys/device.h>
98 1.51 pk #include <sys/pool.h>
99 1.13 cgd #include <vm/vm.h>
100 1.45 thorpej #include <err.h>
101 1.55 kleink #include <fcntl.h>
102 1.1 cgd #include <time.h>
103 1.1 cgd #include <nlist.h>
104 1.1 cgd #include <kvm.h>
105 1.1 cgd #include <errno.h>
106 1.1 cgd #include <unistd.h>
107 1.22 jtc #include <signal.h>
108 1.1 cgd #include <stdio.h>
109 1.1 cgd #include <ctype.h>
110 1.1 cgd #include <stdlib.h>
111 1.1 cgd #include <string.h>
112 1.1 cgd #include <paths.h>
113 1.13 cgd #include <limits.h>
114 1.29 thorpej #include "dkstats.h"
115 1.1 cgd
116 1.45 thorpej #if defined(UVM)
117 1.45 thorpej #include <uvm/uvm_stat.h>
118 1.45 thorpej #endif
119 1.45 thorpej
120 1.13 cgd struct nlist namelist[] = {
121 1.1 cgd #define X_CPTIME 0
122 1.1 cgd { "_cp_time" },
123 1.41 mrg #define X_BOOTTIME 1
124 1.1 cgd { "_boottime" },
125 1.41 mrg #define X_HZ 2
126 1.1 cgd { "_hz" },
127 1.41 mrg #define X_STATHZ 3
128 1.13 cgd { "_stathz" },
129 1.41 mrg #define X_NCHSTATS 4
130 1.1 cgd { "_nchstats" },
131 1.41 mrg #define X_INTRNAMES 5
132 1.1 cgd { "_intrnames" },
133 1.41 mrg #define X_EINTRNAMES 6
134 1.1 cgd { "_eintrnames" },
135 1.41 mrg #define X_INTRCNT 7
136 1.1 cgd { "_intrcnt" },
137 1.41 mrg #define X_EINTRCNT 8
138 1.1 cgd { "_eintrcnt" },
139 1.41 mrg #define X_KMEMSTAT 9
140 1.1 cgd { "_kmemstats" },
141 1.41 mrg #define X_KMEMBUCKETS 10
142 1.1 cgd { "_bucket" },
143 1.41 mrg #define X_ALLEVENTS 11
144 1.18 pk { "_allevents" },
145 1.51 pk #define X_POOLHEAD 12
146 1.51 pk { "_pool_head" },
147 1.41 mrg #if defined(UVM)
148 1.51 pk #define X_END 13
149 1.1 cgd #else
150 1.51 pk #define X_SUM 13
151 1.41 mrg { "_cnt" },
152 1.51 pk #define X_END 14
153 1.1 cgd #endif
154 1.23 phil #if defined(pc532)
155 1.23 phil #define X_IVT (X_END)
156 1.23 phil { "_ivt" },
157 1.23 phil #endif
158 1.1 cgd { "" },
159 1.1 cgd };
160 1.1 cgd
161 1.29 thorpej /* Objects defined in dkstats.c */
162 1.29 thorpej extern struct _disk cur;
163 1.29 thorpej extern char **dr_name;
164 1.29 thorpej extern int *dk_select, dk_ndrive;
165 1.1 cgd
166 1.41 mrg #if defined(UVM)
167 1.41 mrg struct uvmexp uvmexp, ouvmexp;
168 1.41 mrg #else
169 1.13 cgd struct vmmeter sum, osum;
170 1.41 mrg #endif
171 1.29 thorpej int ndrives;
172 1.1 cgd
173 1.1 cgd int winlines = 20;
174 1.1 cgd
175 1.13 cgd kvm_t *kd;
176 1.13 cgd
177 1.1 cgd #define FORKSTAT 0x01
178 1.1 cgd #define INTRSTAT 0x02
179 1.1 cgd #define MEMSTAT 0x04
180 1.1 cgd #define SUMSTAT 0x08
181 1.1 cgd #define VMSTAT 0x20
182 1.45 thorpej #if defined(UVM)
183 1.45 thorpej #define HISTLIST 0x40
184 1.45 thorpej #define HISTDUMP 0x80
185 1.45 thorpej #endif
186 1.1 cgd
187 1.29 thorpej void cpustats __P((void));
188 1.29 thorpej void dkstats __P((void));
189 1.29 thorpej void dointr __P((void));
190 1.29 thorpej void domem __P((void));
191 1.51 pk void dopool __P((void));
192 1.29 thorpej void dosum __P((void));
193 1.29 thorpej void dovmstat __P((u_int, int));
194 1.29 thorpej void kread __P((int, void *, size_t));
195 1.38 mrg void needhdr __P((int));
196 1.38 mrg long getuptime __P((void));
197 1.38 mrg void printhdr __P((void));
198 1.38 mrg long pct __P((long, long));
199 1.29 thorpej void usage __P((void));
200 1.40 thorpej void doforkst __P((void));
201 1.1 cgd
202 1.45 thorpej #if defined(UVM)
203 1.45 thorpej void hist_traverse __P((int, const char *));
204 1.45 thorpej void hist_dodump __P((struct uvm_history *));
205 1.45 thorpej #endif
206 1.45 thorpej
207 1.38 mrg int main __P((int, char **));
208 1.29 thorpej char **choosedrives __P((char **));
209 1.29 thorpej
210 1.49 drochner extern int dkinit __P((int, gid_t));
211 1.38 mrg extern void dkreadstats __P((void));
212 1.38 mrg extern void dkswap __P((void));
213 1.38 mrg
214 1.29 thorpej /* Namelist and memory file names. */
215 1.29 thorpej char *nlistf, *memf;
216 1.29 thorpej
217 1.47 mrg /* allow old usage [vmstat 1] */
218 1.47 mrg #define BACKWARD_COMPATIBILITY
219 1.47 mrg
220 1.38 mrg int
221 1.1 cgd main(argc, argv)
222 1.38 mrg int argc;
223 1.38 mrg char **argv;
224 1.1 cgd {
225 1.1 cgd extern int optind;
226 1.1 cgd extern char *optarg;
227 1.38 mrg int c, todo;
228 1.1 cgd u_int interval;
229 1.1 cgd int reps;
230 1.13 cgd char errbuf[_POSIX2_LINE_MAX];
231 1.48 mrg gid_t egid = getegid();
232 1.45 thorpej #if defined(UVM)
233 1.45 thorpej const char *histname = NULL;
234 1.45 thorpej #endif
235 1.1 cgd
236 1.48 mrg (void)setegid(getgid());
237 1.13 cgd memf = nlistf = NULL;
238 1.1 cgd interval = reps = todo = 0;
239 1.45 thorpej #if defined(UVM)
240 1.54 thorpej while ((c = getopt(argc, argv, "c:fh:HilM:mN:sw:")) != -1) {
241 1.45 thorpej #else
242 1.54 thorpej while ((c = getopt(argc, argv, "c:fiM:mN:sw:")) != -1) {
243 1.45 thorpej #endif
244 1.1 cgd switch (c) {
245 1.1 cgd case 'c':
246 1.1 cgd reps = atoi(optarg);
247 1.1 cgd break;
248 1.1 cgd case 'f':
249 1.1 cgd todo |= FORKSTAT;
250 1.1 cgd break;
251 1.45 thorpej #if defined(UVM)
252 1.45 thorpej case 'h':
253 1.45 thorpej histname = optarg;
254 1.45 thorpej /* FALLTHROUGH */
255 1.45 thorpej case 'H':
256 1.45 thorpej todo |= HISTDUMP;
257 1.45 thorpej break;
258 1.45 thorpej #endif
259 1.1 cgd case 'i':
260 1.1 cgd todo |= INTRSTAT;
261 1.1 cgd break;
262 1.45 thorpej #if defined(UVM)
263 1.45 thorpej case 'l':
264 1.45 thorpej todo |= HISTLIST;
265 1.45 thorpej break;
266 1.45 thorpej #endif
267 1.1 cgd case 'M':
268 1.13 cgd memf = optarg;
269 1.1 cgd break;
270 1.1 cgd case 'm':
271 1.1 cgd todo |= MEMSTAT;
272 1.1 cgd break;
273 1.1 cgd case 'N':
274 1.13 cgd nlistf = optarg;
275 1.1 cgd break;
276 1.1 cgd case 's':
277 1.1 cgd todo |= SUMSTAT;
278 1.1 cgd break;
279 1.1 cgd case 'w':
280 1.1 cgd interval = atoi(optarg);
281 1.1 cgd break;
282 1.1 cgd case '?':
283 1.1 cgd default:
284 1.1 cgd usage();
285 1.1 cgd }
286 1.1 cgd }
287 1.1 cgd argc -= optind;
288 1.1 cgd argv += optind;
289 1.1 cgd
290 1.1 cgd if (todo == 0)
291 1.1 cgd todo = VMSTAT;
292 1.1 cgd
293 1.13 cgd /*
294 1.48 mrg * Discard setgid privileges. If not the running kernel, we toss
295 1.48 mrg * them away totally so that bad guys can't print interesting stuff
296 1.48 mrg * from kernel memory, otherwise switch back to kmem for the
297 1.48 mrg * duration of the kvm_openfiles() call.
298 1.13 cgd */
299 1.13 cgd if (nlistf != NULL || memf != NULL)
300 1.48 mrg (void)setgid(getgid());
301 1.48 mrg else
302 1.48 mrg (void)setegid(egid);
303 1.13 cgd
304 1.13 cgd kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
305 1.48 mrg if (kd == 0)
306 1.48 mrg errx(1, "kvm_openfiles: %s\n", errbuf);
307 1.48 mrg
308 1.48 mrg if (nlistf == NULL && memf == NULL) {
309 1.48 mrg if (todo & VMSTAT)
310 1.48 mrg (void)setegid(getgid()); /* XXX: dkinit */
311 1.48 mrg else
312 1.48 mrg (void)setgid(getgid());
313 1.1 cgd }
314 1.1 cgd
315 1.13 cgd if ((c = kvm_nlist(kd, namelist)) != 0) {
316 1.1 cgd if (c > 0) {
317 1.1 cgd (void)fprintf(stderr,
318 1.13 cgd "vmstat: undefined symbols:");
319 1.13 cgd for (c = 0;
320 1.13 cgd c < sizeof(namelist)/sizeof(namelist[0]); c++)
321 1.13 cgd if (namelist[c].n_type == 0)
322 1.13 cgd fprintf(stderr, " %s",
323 1.13 cgd namelist[c].n_name);
324 1.1 cgd (void)fputc('\n', stderr);
325 1.1 cgd } else
326 1.1 cgd (void)fprintf(stderr, "vmstat: kvm_nlist: %s\n",
327 1.13 cgd kvm_geterr(kd));
328 1.1 cgd exit(1);
329 1.1 cgd }
330 1.1 cgd
331 1.1 cgd if (todo & VMSTAT) {
332 1.1 cgd struct winsize winsize;
333 1.1 cgd
334 1.49 drochner dkinit(0, egid); /* Initialize disk stats, no disks selected. */
335 1.49 drochner
336 1.49 drochner (void)setgid(getgid()); /* don't need privs anymore */
337 1.49 drochner
338 1.29 thorpej argv = choosedrives(argv); /* Select disks. */
339 1.1 cgd winsize.ws_row = 0;
340 1.47 mrg (void)ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize);
341 1.1 cgd if (winsize.ws_row > 0)
342 1.1 cgd winlines = winsize.ws_row;
343 1.1 cgd
344 1.1 cgd }
345 1.1 cgd
346 1.1 cgd #ifdef BACKWARD_COMPATIBILITY
347 1.1 cgd if (*argv) {
348 1.1 cgd interval = atoi(*argv);
349 1.1 cgd if (*++argv)
350 1.1 cgd reps = atoi(*argv);
351 1.1 cgd }
352 1.1 cgd #endif
353 1.1 cgd
354 1.1 cgd if (interval) {
355 1.1 cgd if (!reps)
356 1.1 cgd reps = -1;
357 1.1 cgd } else if (reps)
358 1.1 cgd interval = 1;
359 1.1 cgd
360 1.45 thorpej #if defined(UVM)
361 1.45 thorpej if (todo & (HISTLIST|HISTDUMP)) {
362 1.45 thorpej if ((todo & (HISTLIST|HISTDUMP)) == (HISTLIST|HISTDUMP))
363 1.45 thorpej errx(1, "you may list or dump, but not both!");
364 1.45 thorpej hist_traverse(todo, histname);
365 1.45 thorpej }
366 1.45 thorpej #endif
367 1.1 cgd if (todo & FORKSTAT)
368 1.1 cgd doforkst();
369 1.51 pk if (todo & MEMSTAT) {
370 1.1 cgd domem();
371 1.51 pk dopool();
372 1.51 pk }
373 1.1 cgd if (todo & SUMSTAT)
374 1.13 cgd dosum();
375 1.1 cgd if (todo & INTRSTAT)
376 1.1 cgd dointr();
377 1.1 cgd if (todo & VMSTAT)
378 1.1 cgd dovmstat(interval, reps);
379 1.1 cgd exit(0);
380 1.1 cgd }
381 1.1 cgd
382 1.1 cgd char **
383 1.29 thorpej choosedrives(argv)
384 1.1 cgd char **argv;
385 1.1 cgd {
386 1.38 mrg int i;
387 1.1 cgd
388 1.1 cgd /*
389 1.1 cgd * Choose drives to be displayed. Priority goes to (in order) drives
390 1.1 cgd * supplied as arguments, default drives. If everything isn't filled
391 1.1 cgd * in and there are drives not taken care of, display the first few
392 1.1 cgd * that fit.
393 1.1 cgd */
394 1.1 cgd #define BACKWARD_COMPATIBILITY
395 1.1 cgd for (ndrives = 0; *argv; ++argv) {
396 1.1 cgd #ifdef BACKWARD_COMPATIBILITY
397 1.1 cgd if (isdigit(**argv))
398 1.1 cgd break;
399 1.1 cgd #endif
400 1.1 cgd for (i = 0; i < dk_ndrive; i++) {
401 1.1 cgd if (strcmp(dr_name[i], *argv))
402 1.1 cgd continue;
403 1.29 thorpej dk_select[i] = 1;
404 1.1 cgd ++ndrives;
405 1.1 cgd break;
406 1.1 cgd }
407 1.1 cgd }
408 1.1 cgd for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
409 1.29 thorpej if (dk_select[i])
410 1.1 cgd continue;
411 1.29 thorpej dk_select[i] = 1;
412 1.1 cgd ++ndrives;
413 1.1 cgd }
414 1.1 cgd return(argv);
415 1.1 cgd }
416 1.1 cgd
417 1.1 cgd long
418 1.1 cgd getuptime()
419 1.1 cgd {
420 1.30 cgd static time_t now;
421 1.30 cgd static struct timeval boottime;
422 1.1 cgd time_t uptime;
423 1.1 cgd
424 1.30 cgd if (boottime.tv_sec == 0)
425 1.1 cgd kread(X_BOOTTIME, &boottime, sizeof(boottime));
426 1.1 cgd (void)time(&now);
427 1.30 cgd uptime = now - boottime.tv_sec;
428 1.1 cgd if (uptime <= 0 || uptime > 60*60*24*365*10) {
429 1.1 cgd (void)fprintf(stderr,
430 1.1 cgd "vmstat: time makes no sense; namelist must be wrong.\n");
431 1.1 cgd exit(1);
432 1.1 cgd }
433 1.1 cgd return(uptime);
434 1.1 cgd }
435 1.1 cgd
436 1.1 cgd int hz, hdrcnt;
437 1.1 cgd
438 1.1 cgd void
439 1.1 cgd dovmstat(interval, reps)
440 1.1 cgd u_int interval;
441 1.1 cgd int reps;
442 1.1 cgd {
443 1.1 cgd struct vmtotal total;
444 1.1 cgd time_t uptime, halfuptime;
445 1.17 cgd int mib[2];
446 1.17 cgd size_t size;
447 1.41 mrg int pagesize = getpagesize();
448 1.1 cgd
449 1.1 cgd uptime = getuptime();
450 1.1 cgd halfuptime = uptime / 2;
451 1.1 cgd (void)signal(SIGCONT, needhdr);
452 1.1 cgd
453 1.13 cgd if (namelist[X_STATHZ].n_type != 0 && namelist[X_STATHZ].n_value != 0)
454 1.13 cgd kread(X_STATHZ, &hz, sizeof(hz));
455 1.1 cgd if (!hz)
456 1.1 cgd kread(X_HZ, &hz, sizeof(hz));
457 1.1 cgd
458 1.1 cgd for (hdrcnt = 1;;) {
459 1.1 cgd if (!--hdrcnt)
460 1.1 cgd printhdr();
461 1.29 thorpej /* Read new disk statistics */
462 1.29 thorpej dkreadstats();
463 1.41 mrg #if defined(UVM)
464 1.41 mrg size = sizeof(uvmexp);
465 1.41 mrg mib[0] = CTL_VM;
466 1.41 mrg mib[1] = VM_UVMEXP;
467 1.41 mrg if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0) {
468 1.41 mrg printf("can't get uvmexp: %s\n", strerror(errno));
469 1.53 perry memset(&uvmexp, 0, sizeof(uvmexp));
470 1.41 mrg }
471 1.41 mrg #else
472 1.13 cgd kread(X_SUM, &sum, sizeof(sum));
473 1.41 mrg #endif
474 1.13 cgd size = sizeof(total);
475 1.13 cgd mib[0] = CTL_VM;
476 1.13 cgd mib[1] = VM_METER;
477 1.13 cgd if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) {
478 1.13 cgd printf("Can't get kerninfo: %s\n", strerror(errno));
479 1.53 perry memset(&total, 0, sizeof(total));
480 1.13 cgd }
481 1.13 cgd (void)printf("%2d%2d%2d",
482 1.13 cgd total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw);
483 1.41 mrg #define pgtok(a) (long)((a) * (pagesize >> 10))
484 1.38 mrg #define rate(x) (u_long)(((x) + halfuptime) / uptime) /* round */
485 1.13 cgd (void)printf("%6ld%6ld ",
486 1.1 cgd pgtok(total.t_avm), pgtok(total.t_free));
487 1.41 mrg #if defined(UVM)
488 1.42 mrg (void)printf("%4lu ", rate(uvmexp.faults - ouvmexp.faults));
489 1.42 mrg (void)printf("%3lu ", rate(uvmexp.pdreact - ouvmexp.pdreact));
490 1.46 mrg (void)printf("%3lu ", rate(uvmexp.pageins - ouvmexp.pageins));
491 1.44 mrg (void)printf("%4lu ",
492 1.44 mrg rate(uvmexp.pgswapout - ouvmexp.pgswapout));
493 1.44 mrg (void)printf("%4lu ", rate(uvmexp.pdfreed - ouvmexp.pdfreed));
494 1.44 mrg (void)printf("%4lu ", rate(uvmexp.pdscans - ouvmexp.pdscans));
495 1.42 mrg dkstats();
496 1.42 mrg (void)printf("%4lu %4lu %3lu ",
497 1.42 mrg rate(uvmexp.intrs - ouvmexp.intrs),
498 1.42 mrg rate(uvmexp.syscalls - ouvmexp.syscalls),
499 1.42 mrg rate(uvmexp.swtch - ouvmexp.swtch));
500 1.42 mrg cpustats();
501 1.42 mrg (void)printf("\n");
502 1.42 mrg (void)fflush(stdout);
503 1.42 mrg if (reps >= 0 && --reps <= 0)
504 1.42 mrg break;
505 1.42 mrg ouvmexp = uvmexp;
506 1.41 mrg #else
507 1.13 cgd (void)printf("%4lu ", rate(sum.v_faults - osum.v_faults));
508 1.1 cgd (void)printf("%3lu ",
509 1.13 cgd rate(sum.v_reactivated - osum.v_reactivated));
510 1.13 cgd (void)printf("%3lu ", rate(sum.v_pageins - osum.v_pageins));
511 1.1 cgd (void)printf("%3lu %3lu ",
512 1.38 mrg rate(sum.v_pageouts - osum.v_pageouts), (u_long)0);
513 1.13 cgd (void)printf("%3lu ", rate(sum.v_scan - osum.v_scan));
514 1.1 cgd dkstats();
515 1.1 cgd (void)printf("%4lu %4lu %3lu ",
516 1.13 cgd rate(sum.v_intr - osum.v_intr),
517 1.13 cgd rate(sum.v_syscall - osum.v_syscall),
518 1.13 cgd rate(sum.v_swtch - osum.v_swtch));
519 1.1 cgd cpustats();
520 1.1 cgd (void)printf("\n");
521 1.1 cgd (void)fflush(stdout);
522 1.1 cgd if (reps >= 0 && --reps <= 0)
523 1.1 cgd break;
524 1.13 cgd osum = sum;
525 1.41 mrg #endif
526 1.1 cgd uptime = interval;
527 1.1 cgd /*
528 1.1 cgd * We round upward to avoid losing low-frequency events
529 1.1 cgd * (i.e., >= 1 per interval but < 1 per second).
530 1.1 cgd */
531 1.33 thorpej halfuptime = uptime == 1 ? 0 : (uptime + 1) / 2;
532 1.1 cgd (void)sleep(interval);
533 1.1 cgd }
534 1.1 cgd }
535 1.1 cgd
536 1.38 mrg void
537 1.1 cgd printhdr()
538 1.1 cgd {
539 1.38 mrg int i;
540 1.1 cgd
541 1.44 mrg #if defined(UVM)
542 1.44 mrg (void)printf(" procs memory page%*s", 23, "");
543 1.44 mrg #else
544 1.1 cgd (void)printf(" procs memory page%*s", 20, "");
545 1.44 mrg #endif
546 1.29 thorpej if (ndrives > 0)
547 1.29 thorpej (void)printf("%s %*sfaults cpu\n",
548 1.29 thorpej ((ndrives > 1) ? "disks" : "disk"),
549 1.29 thorpej ((ndrives > 1) ? ndrives * 3 - 4 : 0), "");
550 1.1 cgd else
551 1.29 thorpej (void)printf("%*s faults cpu\n",
552 1.29 thorpej ndrives * 3, "");
553 1.29 thorpej
554 1.44 mrg #if defined(UVM)
555 1.44 mrg (void)printf(" r b w avm fre flt re pi po fr sr ");
556 1.44 mrg #else
557 1.1 cgd (void)printf(" r b w avm fre flt re pi po fr sr ");
558 1.44 mrg #endif
559 1.1 cgd for (i = 0; i < dk_ndrive; i++)
560 1.29 thorpej if (dk_select[i])
561 1.1 cgd (void)printf("%c%c ", dr_name[i][0],
562 1.1 cgd dr_name[i][strlen(dr_name[i]) - 1]);
563 1.1 cgd (void)printf(" in sy cs us sy id\n");
564 1.1 cgd hdrcnt = winlines - 2;
565 1.1 cgd }
566 1.1 cgd
567 1.1 cgd /*
568 1.1 cgd * Force a header to be prepended to the next output.
569 1.1 cgd */
570 1.1 cgd void
571 1.38 mrg needhdr(dummy)
572 1.38 mrg int dummy;
573 1.1 cgd {
574 1.1 cgd
575 1.1 cgd hdrcnt = 1;
576 1.1 cgd }
577 1.1 cgd
578 1.38 mrg long
579 1.1 cgd pct(top, bot)
580 1.1 cgd long top, bot;
581 1.1 cgd {
582 1.13 cgd long ans;
583 1.13 cgd
584 1.1 cgd if (bot == 0)
585 1.1 cgd return(0);
586 1.13 cgd ans = (quad_t)top * 100 / bot;
587 1.13 cgd return (ans);
588 1.1 cgd }
589 1.1 cgd
590 1.38 mrg #define PCT(top, bot) (int)pct((long)(top), (long)(bot))
591 1.1 cgd
592 1.1 cgd void
593 1.13 cgd dosum()
594 1.1 cgd {
595 1.1 cgd struct nchstats nchstats;
596 1.1 cgd long nchtotal;
597 1.1 cgd
598 1.41 mrg #if defined(UVM)
599 1.41 mrg int mib[2];
600 1.41 mrg size_t size;
601 1.41 mrg
602 1.41 mrg size = sizeof(uvmexp);
603 1.41 mrg mib[0] = CTL_VM;
604 1.41 mrg mib[1] = VM_UVMEXP;
605 1.41 mrg if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0) {
606 1.41 mrg printf("can't get uvmexp: %s\n", strerror(errno));
607 1.53 perry memset(&uvmexp, 0, sizeof(uvmexp));
608 1.41 mrg }
609 1.41 mrg
610 1.44 mrg (void)printf("%9u bytes per page\n", uvmexp.pagesize);
611 1.44 mrg
612 1.44 mrg (void)printf("%9u pages managed\n", uvmexp.npages);
613 1.44 mrg (void)printf("%9u pages free\n", uvmexp.free);
614 1.44 mrg (void)printf("%9u pages active\n", uvmexp.active);
615 1.44 mrg (void)printf("%9u pages inactive\n", uvmexp.inactive);
616 1.44 mrg (void)printf("%9u pages paging\n", uvmexp.paging);
617 1.44 mrg (void)printf("%9u pages wired\n", uvmexp.wired);
618 1.44 mrg (void)printf("%9u reserve pagedaemon pages\n",
619 1.44 mrg uvmexp.reserve_pagedaemon);
620 1.44 mrg (void)printf("%9u reserve kernel pages\n", uvmexp.reserve_kernel);
621 1.44 mrg
622 1.44 mrg (void)printf("%9u minimum free pages\n", uvmexp.freemin);
623 1.44 mrg (void)printf("%9u target free pages\n", uvmexp.freetarg);
624 1.44 mrg (void)printf("%9u target inactive pages\n", uvmexp.inactarg);
625 1.44 mrg (void)printf("%9u maximum wired pages\n", uvmexp.wiredmax);
626 1.44 mrg
627 1.44 mrg (void)printf("%9u swap devices\n", uvmexp.nswapdev);
628 1.44 mrg (void)printf("%9u swap pages\n", uvmexp.swpages);
629 1.44 mrg (void)printf("%9u swap pages in use\n", uvmexp.swpginuse);
630 1.44 mrg (void)printf("%9u swap allocations\n", uvmexp.nswget);
631 1.44 mrg (void)printf("%9u anons\n", uvmexp.nanon);
632 1.44 mrg (void)printf("%9u free anons\n", uvmexp.nfreeanon);
633 1.44 mrg
634 1.43 mrg (void)printf("%9u total faults taken\n", uvmexp.faults);
635 1.43 mrg (void)printf("%9u traps\n", uvmexp.traps);
636 1.43 mrg (void)printf("%9u device interrupts\n", uvmexp.intrs);
637 1.43 mrg (void)printf("%9u cpu context switches\n", uvmexp.swtch);
638 1.43 mrg (void)printf("%9u software interrupts\n", uvmexp.softs);
639 1.43 mrg (void)printf("%9u system calls\n", uvmexp.syscalls);
640 1.44 mrg (void)printf("%9u pagein requests\n", uvmexp.pageins / CLSIZE);
641 1.44 mrg (void)printf("%9u pageout requests\n", uvmexp.pdpageouts / CLSIZE);
642 1.43 mrg (void)printf("%9u swap ins\n", uvmexp.swapins);
643 1.43 mrg (void)printf("%9u swap outs\n", uvmexp.swapouts);
644 1.44 mrg (void)printf("%9u pages swapped in\n", uvmexp.pgswapin / CLSIZE);
645 1.44 mrg (void)printf("%9u pages swapped out\n", uvmexp.pgswapout / CLSIZE);
646 1.43 mrg (void)printf("%9u forks total\n", uvmexp.forks);
647 1.43 mrg (void)printf("%9u forks blocked parent\n", uvmexp.forks_ppwait);
648 1.43 mrg (void)printf("%9u forks shared address space with parent\n",
649 1.43 mrg uvmexp.forks_sharevm);
650 1.44 mrg
651 1.44 mrg (void)printf("%9u faults with no memory\n", uvmexp.fltnoram);
652 1.44 mrg (void)printf("%9u faults with no anons\n", uvmexp.fltnoanon);
653 1.43 mrg (void)printf("%9u faults had to wait on pages\n", uvmexp.fltpgwait);
654 1.43 mrg (void)printf("%9u faults found released page\n", uvmexp.fltpgrele);
655 1.43 mrg (void)printf("%9u faults relock (%u ok)\n", uvmexp.fltrelck,
656 1.43 mrg uvmexp.fltrelckok);
657 1.43 mrg (void)printf("%9u anon page faults\n", uvmexp.fltanget);
658 1.43 mrg (void)printf("%9u anon retry faults\n", uvmexp.fltanretry);
659 1.43 mrg (void)printf("%9u amap copy faults\n", uvmexp.fltamcopy);
660 1.43 mrg (void)printf("%9u neighbour anon page faults\n", uvmexp.fltnamap);
661 1.43 mrg (void)printf("%9u neighbour object page faults\n", uvmexp.fltnomap);
662 1.43 mrg (void)printf("%9u locked pager get faults\n", uvmexp.fltlget);
663 1.43 mrg (void)printf("%9u unlocked pager get faults\n", uvmexp.fltget);
664 1.43 mrg (void)printf("%9u anon faults\n", uvmexp.flt_anon);
665 1.43 mrg (void)printf("%9u anon copy on write faults\n", uvmexp.flt_acow);
666 1.43 mrg (void)printf("%9u object faults\n", uvmexp.flt_obj);
667 1.43 mrg (void)printf("%9u promote copy faults\n", uvmexp.flt_prcopy);
668 1.43 mrg (void)printf("%9u promote zero fill faults\n", uvmexp.flt_przero);
669 1.44 mrg
670 1.44 mrg (void)printf("%9u times daemon wokeup\n",uvmexp.pdwoke);
671 1.44 mrg (void)printf("%9u revolutions of the clock hand\n", uvmexp.pdrevs);
672 1.44 mrg (void)printf("%9u times daemon attempted swapout\n", uvmexp.pdswout);
673 1.44 mrg (void)printf("%9u pages freed by daemon\n", uvmexp.pdfreed);
674 1.44 mrg (void)printf("%9u pages scanned by daemon\n", uvmexp.pdscans);
675 1.44 mrg (void)printf("%9u anonymous pages scanned by daemon\n", uvmexp.pdanscan);
676 1.44 mrg (void)printf("%9u object pages scanned by daemon\n", uvmexp.pdobscan);
677 1.44 mrg (void)printf("%9u pages reactivated\n", uvmexp.pdreact);
678 1.44 mrg (void)printf("%9u pages found busy by daemon\n", uvmexp.pdbusy);
679 1.44 mrg (void)printf("%9u total pending pageouts\n", uvmexp.pdpending);
680 1.44 mrg (void)printf("%9u pages deactivated\n", uvmexp.pddeact);
681 1.41 mrg #else
682 1.13 cgd kread(X_SUM, &sum, sizeof(sum));
683 1.13 cgd (void)printf("%9u cpu context switches\n", sum.v_swtch);
684 1.13 cgd (void)printf("%9u device interrupts\n", sum.v_intr);
685 1.13 cgd (void)printf("%9u software interrupts\n", sum.v_soft);
686 1.13 cgd (void)printf("%9u traps\n", sum.v_trap);
687 1.13 cgd (void)printf("%9u system calls\n", sum.v_syscall);
688 1.13 cgd (void)printf("%9u total faults taken\n", sum.v_faults);
689 1.13 cgd (void)printf("%9u swap ins\n", sum.v_swpin);
690 1.13 cgd (void)printf("%9u swap outs\n", sum.v_swpout);
691 1.13 cgd (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE);
692 1.13 cgd (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE);
693 1.13 cgd (void)printf("%9u page ins\n", sum.v_pageins);
694 1.13 cgd (void)printf("%9u page outs\n", sum.v_pageouts);
695 1.13 cgd (void)printf("%9u pages paged in\n", sum.v_pgpgin);
696 1.13 cgd (void)printf("%9u pages paged out\n", sum.v_pgpgout);
697 1.13 cgd (void)printf("%9u pages reactivated\n", sum.v_reactivated);
698 1.13 cgd (void)printf("%9u intransit blocking page faults\n", sum.v_intrans);
699 1.13 cgd (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE);
700 1.13 cgd (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE);
701 1.13 cgd (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan);
702 1.13 cgd (void)printf("%9u revolutions of the clock hand\n", sum.v_rev);
703 1.13 cgd (void)printf("%9u VM object cache lookups\n", sum.v_lookups);
704 1.13 cgd (void)printf("%9u VM object hits\n", sum.v_hits);
705 1.13 cgd (void)printf("%9u total VM faults taken\n", sum.v_vm_faults);
706 1.13 cgd (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults);
707 1.13 cgd (void)printf("%9u pages freed by daemon\n", sum.v_dfree);
708 1.13 cgd (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree);
709 1.13 cgd (void)printf("%9u pages free\n", sum.v_free_count);
710 1.13 cgd (void)printf("%9u pages wired down\n", sum.v_wire_count);
711 1.13 cgd (void)printf("%9u pages active\n", sum.v_active_count);
712 1.13 cgd (void)printf("%9u pages inactive\n", sum.v_inactive_count);
713 1.13 cgd (void)printf("%9u bytes per page\n", sum.v_page_size);
714 1.37 mrg (void)printf("%9u target inactive pages\n", sum.v_inactive_target);
715 1.37 mrg (void)printf("%9u target free pages\n", sum.v_free_target);
716 1.37 mrg (void)printf("%9u minimum free pages\n", sum.v_free_min);
717 1.1 cgd #endif
718 1.1 cgd kread(X_NCHSTATS, &nchstats, sizeof(nchstats));
719 1.1 cgd nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits +
720 1.1 cgd nchstats.ncs_badhits + nchstats.ncs_falsehits +
721 1.1 cgd nchstats.ncs_miss + nchstats.ncs_long;
722 1.1 cgd (void)printf("%9ld total name lookups\n", nchtotal);
723 1.1 cgd (void)printf(
724 1.1 cgd "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n",
725 1.1 cgd "", PCT(nchstats.ncs_goodhits, nchtotal),
726 1.1 cgd PCT(nchstats.ncs_neghits, nchtotal),
727 1.1 cgd PCT(nchstats.ncs_pass2, nchtotal));
728 1.1 cgd (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "",
729 1.1 cgd PCT(nchstats.ncs_badhits, nchtotal),
730 1.1 cgd PCT(nchstats.ncs_falsehits, nchtotal),
731 1.1 cgd PCT(nchstats.ncs_long, nchtotal));
732 1.1 cgd }
733 1.1 cgd
734 1.1 cgd void
735 1.1 cgd doforkst()
736 1.1 cgd {
737 1.41 mrg #if defined(UVM)
738 1.41 mrg int mib[2];
739 1.41 mrg size_t size;
740 1.41 mrg
741 1.41 mrg size = sizeof(uvmexp);
742 1.41 mrg mib[0] = CTL_VM;
743 1.41 mrg mib[1] = VM_UVMEXP;
744 1.41 mrg if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0) {
745 1.41 mrg printf("can't get uvmexp: %s\n", strerror(errno));
746 1.53 perry memset(&uvmexp, 0, sizeof(uvmexp));
747 1.41 mrg }
748 1.41 mrg (void)printf("%u forks total\n", uvmexp.forks);
749 1.41 mrg (void)printf("%u forks blocked parent\n", uvmexp.forks_ppwait);
750 1.41 mrg (void)printf("%u forks shared address space with parent\n",
751 1.41 mrg uvmexp.forks_sharevm);
752 1.41 mrg #else
753 1.1 cgd
754 1.40 thorpej kread(X_SUM, &sum, sizeof(sum));
755 1.40 thorpej (void)printf("%u forks total\n", sum.v_forks);
756 1.40 thorpej (void)printf("%u forks blocked parent\n", sum.v_forks_ppwait);
757 1.40 thorpej (void)printf("%u forks shared address space with parent\n",
758 1.40 thorpej sum.v_forks_sharevm);
759 1.41 mrg #endif
760 1.1 cgd }
761 1.1 cgd
762 1.1 cgd void
763 1.1 cgd dkstats()
764 1.1 cgd {
765 1.38 mrg int dn, state;
766 1.1 cgd double etime;
767 1.1 cgd
768 1.29 thorpej /* Calculate disk stat deltas. */
769 1.29 thorpej dkswap();
770 1.1 cgd etime = 0;
771 1.1 cgd for (state = 0; state < CPUSTATES; ++state) {
772 1.29 thorpej etime += cur.cp_time[state];
773 1.1 cgd }
774 1.1 cgd if (etime == 0)
775 1.1 cgd etime = 1;
776 1.1 cgd etime /= hz;
777 1.1 cgd for (dn = 0; dn < dk_ndrive; ++dn) {
778 1.29 thorpej if (!dk_select[dn])
779 1.1 cgd continue;
780 1.29 thorpej (void)printf("%2.0f ", cur.dk_xfer[dn] / etime);
781 1.1 cgd }
782 1.1 cgd }
783 1.1 cgd
784 1.1 cgd void
785 1.1 cgd cpustats()
786 1.1 cgd {
787 1.38 mrg int state;
788 1.1 cgd double pct, total;
789 1.1 cgd
790 1.1 cgd total = 0;
791 1.1 cgd for (state = 0; state < CPUSTATES; ++state)
792 1.29 thorpej total += cur.cp_time[state];
793 1.1 cgd if (total)
794 1.1 cgd pct = 100 / total;
795 1.1 cgd else
796 1.1 cgd pct = 0;
797 1.29 thorpej (void)printf("%2.0f ", (cur.cp_time[CP_USER] + cur.cp_time[CP_NICE]) * pct);
798 1.29 thorpej (void)printf("%2.0f ", (cur.cp_time[CP_SYS] + cur.cp_time[CP_INTR]) * pct);
799 1.29 thorpej (void)printf("%2.0f", cur.cp_time[CP_IDLE] * pct);
800 1.1 cgd }
801 1.1 cgd
802 1.23 phil #if defined(pc532)
803 1.24 phil /* To get struct iv ...*/
804 1.24 phil #define _KERNEL
805 1.23 phil #include <machine/psl.h>
806 1.24 phil #undef _KERNEL
807 1.23 phil void
808 1.23 phil dointr()
809 1.23 phil {
810 1.38 mrg long i, j, inttotal, uptime;
811 1.23 phil static char iname[64];
812 1.23 phil struct iv ivt[32], *ivp = ivt;
813 1.23 phil
814 1.23 phil iname[63] = '\0';
815 1.23 phil uptime = getuptime();
816 1.23 phil kread(X_IVT, ivp, sizeof(ivt));
817 1.23 phil
818 1.23 phil for (i = 0; i < 2; i++) {
819 1.23 phil (void)printf("%sware interrupts:\n", i ? "\nsoft" : "hard");
820 1.23 phil (void)printf("interrupt total rate\n");
821 1.23 phil inttotal = 0;
822 1.23 phil for (j = 0; j < 16; j++, ivp++) {
823 1.23 phil if (ivp->iv_vec && ivp->iv_use && ivp->iv_cnt) {
824 1.23 phil if (kvm_read(kd, (u_long)ivp->iv_use, iname, 63) != 63) {
825 1.23 phil (void)fprintf(stderr, "vmstat: iv_use: %s\n",
826 1.23 phil kvm_geterr(kd));
827 1.23 phil exit(1);
828 1.23 phil }
829 1.23 phil (void)printf("%-12s %8ld %8ld\n", iname,
830 1.23 phil ivp->iv_cnt, ivp->iv_cnt / uptime);
831 1.23 phil inttotal += ivp->iv_cnt;
832 1.23 phil }
833 1.23 phil }
834 1.23 phil (void)printf("Total %8ld %8ld\n",
835 1.23 phil inttotal, inttotal / uptime);
836 1.23 phil }
837 1.23 phil }
838 1.23 phil #else
839 1.1 cgd void
840 1.1 cgd dointr()
841 1.1 cgd {
842 1.38 mrg long *intrcnt, inttotal, uptime;
843 1.38 mrg int nintr, inamlen;
844 1.38 mrg char *intrname;
845 1.28 cgd struct evcntlist allevents;
846 1.28 cgd struct evcnt evcnt, *evptr;
847 1.18 pk struct device dev;
848 1.1 cgd
849 1.1 cgd uptime = getuptime();
850 1.13 cgd nintr = namelist[X_EINTRCNT].n_value - namelist[X_INTRCNT].n_value;
851 1.13 cgd inamlen =
852 1.13 cgd namelist[X_EINTRNAMES].n_value - namelist[X_INTRNAMES].n_value;
853 1.1 cgd intrcnt = malloc((size_t)nintr);
854 1.1 cgd intrname = malloc((size_t)inamlen);
855 1.1 cgd if (intrcnt == NULL || intrname == NULL) {
856 1.1 cgd (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno));
857 1.1 cgd exit(1);
858 1.1 cgd }
859 1.1 cgd kread(X_INTRCNT, intrcnt, (size_t)nintr);
860 1.1 cgd kread(X_INTRNAMES, intrname, (size_t)inamlen);
861 1.27 cgd (void)printf("interrupt total rate\n");
862 1.1 cgd inttotal = 0;
863 1.1 cgd nintr /= sizeof(long);
864 1.1 cgd while (--nintr >= 0) {
865 1.1 cgd if (*intrcnt)
866 1.27 cgd (void)printf("%-14s %8ld %8ld\n", intrname,
867 1.1 cgd *intrcnt, *intrcnt / uptime);
868 1.1 cgd intrname += strlen(intrname) + 1;
869 1.1 cgd inttotal += *intrcnt++;
870 1.1 cgd }
871 1.18 pk kread(X_ALLEVENTS, &allevents, sizeof allevents);
872 1.28 cgd evptr = allevents.tqh_first;
873 1.28 cgd while (evptr) {
874 1.28 cgd if (kvm_read(kd, (long)evptr, (void *)&evcnt,
875 1.18 pk sizeof evcnt) != sizeof evcnt) {
876 1.38 mrg (void)fprintf(stderr, "vmstat: event chain trashed: %s\n",
877 1.18 pk kvm_geterr(kd));
878 1.18 pk exit(1);
879 1.18 pk }
880 1.32 cgd if (kvm_read(kd, (long)evcnt.ev_dev, (void *)&dev,
881 1.32 cgd sizeof dev) != sizeof dev) {
882 1.38 mrg (void)fprintf(stderr, "vmstat: event chain trashed: %s\n",
883 1.32 cgd kvm_geterr(kd));
884 1.32 cgd exit(1);
885 1.18 pk }
886 1.32 cgd if (evcnt.ev_count)
887 1.32 cgd (void)printf("%-14s %8ld %8ld\n", dev.dv_xname,
888 1.38 mrg (long)evcnt.ev_count, evcnt.ev_count / uptime);
889 1.32 cgd inttotal += evcnt.ev_count++;
890 1.32 cgd
891 1.28 cgd evptr = evcnt.ev_list.tqe_next;
892 1.18 pk }
893 1.27 cgd (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime);
894 1.1 cgd }
895 1.23 phil #endif
896 1.1 cgd
897 1.1 cgd /*
898 1.1 cgd * These names are defined in <sys/malloc.h>.
899 1.1 cgd */
900 1.1 cgd char *kmemnames[] = INITKMEMNAMES;
901 1.1 cgd
902 1.1 cgd void
903 1.1 cgd domem()
904 1.1 cgd {
905 1.38 mrg struct kmembuckets *kp;
906 1.38 mrg struct kmemstats *ks;
907 1.38 mrg int i, j;
908 1.13 cgd int len, size, first;
909 1.13 cgd long totuse = 0, totfree = 0, totreq = 0;
910 1.13 cgd char *name;
911 1.13 cgd struct kmemstats kmemstats[M_LAST];
912 1.1 cgd struct kmembuckets buckets[MINBUCKET + 16];
913 1.1 cgd
914 1.1 cgd kread(X_KMEMBUCKETS, buckets, sizeof(buckets));
915 1.34 thorpej for (first = 1, i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16;
916 1.34 thorpej i++, kp++) {
917 1.1 cgd if (kp->kb_calls == 0)
918 1.1 cgd continue;
919 1.34 thorpej if (first) {
920 1.34 thorpej (void)printf("Memory statistics by bucket size\n");
921 1.34 thorpej (void)printf(
922 1.34 thorpej " Size In Use Free Requests HighWater Couldfree\n");
923 1.34 thorpej first = 0;
924 1.34 thorpej }
925 1.1 cgd size = 1 << i;
926 1.1 cgd (void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size,
927 1.1 cgd kp->kb_total - kp->kb_totalfree,
928 1.1 cgd kp->kb_totalfree, kp->kb_calls,
929 1.1 cgd kp->kb_highwat, kp->kb_couldfree);
930 1.1 cgd totfree += size * kp->kb_totalfree;
931 1.34 thorpej }
932 1.34 thorpej
933 1.34 thorpej /*
934 1.34 thorpej * If kmem statistics are not being gathered by the kernel,
935 1.34 thorpej * first will still be 1.
936 1.34 thorpej */
937 1.34 thorpej if (first) {
938 1.34 thorpej printf(
939 1.34 thorpej "Kmem statistics are not being gathered by the kernel.\n");
940 1.34 thorpej return;
941 1.1 cgd }
942 1.1 cgd
943 1.1 cgd kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats));
944 1.13 cgd (void)printf("\nMemory usage type by bucket size\n");
945 1.13 cgd (void)printf(" Size Type(s)\n");
946 1.13 cgd kp = &buckets[MINBUCKET];
947 1.13 cgd for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1, kp++) {
948 1.13 cgd if (kp->kb_calls == 0)
949 1.13 cgd continue;
950 1.13 cgd first = 1;
951 1.13 cgd len = 8;
952 1.13 cgd for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
953 1.13 cgd if (ks->ks_calls == 0)
954 1.13 cgd continue;
955 1.13 cgd if ((ks->ks_size & j) == 0)
956 1.13 cgd continue;
957 1.35 is if (kmemnames[i] == 0) {
958 1.35 is kmemnames[i] = malloc(10);
959 1.35 is /* strlen("undef/")+3+1);*/
960 1.35 is snprintf(kmemnames[i], 10, "undef/%d", i);
961 1.35 is /* same 10 as above!!! */
962 1.35 is }
963 1.35 is name = kmemnames[i];
964 1.13 cgd len += 2 + strlen(name);
965 1.13 cgd if (first)
966 1.13 cgd printf("%8d %s", j, name);
967 1.13 cgd else
968 1.13 cgd printf(",");
969 1.13 cgd if (len >= 80) {
970 1.13 cgd printf("\n\t ");
971 1.13 cgd len = 10 + strlen(name);
972 1.13 cgd }
973 1.13 cgd if (!first)
974 1.13 cgd printf(" %s", name);
975 1.13 cgd first = 0;
976 1.13 cgd }
977 1.13 cgd printf("\n");
978 1.13 cgd }
979 1.13 cgd
980 1.1 cgd (void)printf(
981 1.13 cgd "\nMemory statistics by type Type Kern\n");
982 1.13 cgd (void)printf(
983 1.36 is " Type InUse MemUse HighUse Limit Requests Limit Limit Size(s)\n");
984 1.13 cgd for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
985 1.1 cgd if (ks->ks_calls == 0)
986 1.1 cgd continue;
987 1.36 is (void)printf("%14s%6ld%6ldK%7ldK%6ldK%9ld%5u%6u",
988 1.1 cgd kmemnames[i] ? kmemnames[i] : "undefined",
989 1.1 cgd ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
990 1.1 cgd (ks->ks_maxused + 1023) / 1024,
991 1.1 cgd (ks->ks_limit + 1023) / 1024, ks->ks_calls,
992 1.1 cgd ks->ks_limblocks, ks->ks_mapblocks);
993 1.13 cgd first = 1;
994 1.13 cgd for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
995 1.13 cgd if ((ks->ks_size & j) == 0)
996 1.13 cgd continue;
997 1.13 cgd if (first)
998 1.13 cgd printf(" %d", j);
999 1.13 cgd else
1000 1.13 cgd printf(",%d", j);
1001 1.13 cgd first = 0;
1002 1.13 cgd }
1003 1.13 cgd printf("\n");
1004 1.1 cgd totuse += ks->ks_memuse;
1005 1.1 cgd totreq += ks->ks_calls;
1006 1.1 cgd }
1007 1.13 cgd (void)printf("\nMemory Totals: In Use Free Requests\n");
1008 1.13 cgd (void)printf(" %7ldK %6ldK %8ld\n",
1009 1.13 cgd (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq);
1010 1.51 pk }
1011 1.51 pk
1012 1.51 pk void
1013 1.51 pk dopool()
1014 1.51 pk {
1015 1.51 pk int first;
1016 1.51 pk long addr;
1017 1.51 pk long total = 0, inuse = 0;
1018 1.51 pk TAILQ_HEAD(,pool) pool_head;
1019 1.51 pk struct pool pool, *pp = &pool;
1020 1.51 pk
1021 1.51 pk kread(X_POOLHEAD, &pool_head, sizeof(pool_head));
1022 1.51 pk addr = (long)TAILQ_FIRST(&pool_head);
1023 1.51 pk
1024 1.51 pk for (first = 1; addr != 0; ) {
1025 1.51 pk char name[32], maxp[32];
1026 1.51 pk if (kvm_read(kd, addr, (void *)pp, sizeof *pp) != sizeof *pp) {
1027 1.51 pk (void)fprintf(stderr, "vmstat: pool chain trashed: %s\n",
1028 1.51 pk kvm_geterr(kd));
1029 1.51 pk exit(1);
1030 1.51 pk }
1031 1.51 pk if (kvm_read(kd, (long)pp->pr_wchan, name, sizeof name) < 0) {
1032 1.51 pk (void)fprintf(stderr, "vmstat: pool name trashed: %s\n",
1033 1.51 pk kvm_geterr(kd));
1034 1.51 pk exit(1);
1035 1.51 pk }
1036 1.51 pk name[31]='\0';
1037 1.51 pk
1038 1.51 pk if (first) {
1039 1.51 pk (void)printf("Memory resource pool statistics\n");
1040 1.51 pk (void)printf(
1041 1.52 thorpej "%16s %6s %8s %8s %8s %7s %7s %6s %6s %6s %6s %6s\n",
1042 1.51 pk "Name",
1043 1.51 pk "Size",
1044 1.51 pk "Requests",
1045 1.51 pk "Failed",
1046 1.51 pk "Releases",
1047 1.51 pk "Pagereq",
1048 1.51 pk "Pagerel",
1049 1.51 pk "Npage",
1050 1.51 pk "Hiwat",
1051 1.51 pk "Minpage",
1052 1.52 thorpej "Maxpage",
1053 1.52 thorpej "Idle");
1054 1.51 pk first = 0;
1055 1.51 pk }
1056 1.51 pk if (pp->pr_maxpages == UINT_MAX)
1057 1.51 pk sprintf(maxp, "inf");
1058 1.51 pk else
1059 1.51 pk sprintf(maxp, "%6u", pp->pr_maxpages);
1060 1.51 pk (void)printf(
1061 1.52 thorpej "%16s %6u %8lu %8lu %8lu %7lu %7lu %6u %6u %6u %6s %6lu\n",
1062 1.51 pk name,
1063 1.51 pk pp->pr_size,
1064 1.51 pk pp->pr_nget,
1065 1.51 pk pp->pr_nfail,
1066 1.51 pk pp->pr_nput,
1067 1.51 pk pp->pr_npagealloc,
1068 1.51 pk pp->pr_npagefree,
1069 1.51 pk pp->pr_npages,
1070 1.51 pk pp->pr_hiwat,
1071 1.51 pk pp->pr_minpages,
1072 1.52 thorpej maxp,
1073 1.52 thorpej pp->pr_nidle);
1074 1.51 pk
1075 1.51 pk inuse += (pp->pr_nget - pp->pr_nput) * pp->pr_size;
1076 1.51 pk total += pp->pr_npages * pp->pr_pagesz;
1077 1.51 pk addr = (long)TAILQ_NEXT(pp, pr_poollist);
1078 1.51 pk }
1079 1.51 pk
1080 1.51 pk printf("\nIn use %ldK, total allocated %ldK; utilization %.1f%%\n",
1081 1.51 pk inuse/1024, total/1024, (double)(100 * inuse) / total);
1082 1.51 pk
1083 1.1 cgd }
1084 1.1 cgd
1085 1.1 cgd /*
1086 1.1 cgd * kread reads something from the kernel, given its nlist index.
1087 1.1 cgd */
1088 1.1 cgd void
1089 1.1 cgd kread(nlx, addr, size)
1090 1.1 cgd int nlx;
1091 1.1 cgd void *addr;
1092 1.1 cgd size_t size;
1093 1.1 cgd {
1094 1.50 mycroft const char *sym;
1095 1.1 cgd
1096 1.13 cgd if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) {
1097 1.13 cgd sym = namelist[nlx].n_name;
1098 1.1 cgd if (*sym == '_')
1099 1.1 cgd ++sym;
1100 1.1 cgd (void)fprintf(stderr,
1101 1.13 cgd "vmstat: symbol %s not defined\n", sym);
1102 1.1 cgd exit(1);
1103 1.1 cgd }
1104 1.13 cgd if (kvm_read(kd, namelist[nlx].n_value, addr, size) != size) {
1105 1.13 cgd sym = namelist[nlx].n_name;
1106 1.1 cgd if (*sym == '_')
1107 1.1 cgd ++sym;
1108 1.13 cgd (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr(kd));
1109 1.1 cgd exit(1);
1110 1.1 cgd }
1111 1.1 cgd }
1112 1.1 cgd
1113 1.45 thorpej #if defined(UVM)
1114 1.45 thorpej struct nlist histnl[] = {
1115 1.45 thorpej { "_uvm_histories" },
1116 1.45 thorpej #define X_UVM_HISTORIES 0
1117 1.45 thorpej { NULL },
1118 1.45 thorpej };
1119 1.45 thorpej
1120 1.45 thorpej /*
1121 1.45 thorpej * Traverse the UVM history buffers, performing the requested action.
1122 1.45 thorpej *
1123 1.45 thorpej * Note, we assume that if we're not listing, we're dumping.
1124 1.45 thorpej */
1125 1.45 thorpej void
1126 1.45 thorpej hist_traverse(todo, histname)
1127 1.45 thorpej int todo;
1128 1.45 thorpej const char *histname;
1129 1.45 thorpej {
1130 1.45 thorpej struct uvm_history_head histhead;
1131 1.45 thorpej struct uvm_history hist, *histkva;
1132 1.45 thorpej char *name = NULL;
1133 1.45 thorpej size_t namelen = 0;
1134 1.45 thorpej
1135 1.45 thorpej if (kvm_nlist(kd, histnl) != 0) {
1136 1.45 thorpej printf("UVM history is not compiled into the kernel.\n");
1137 1.45 thorpej return;
1138 1.45 thorpej }
1139 1.45 thorpej
1140 1.45 thorpej if (kvm_read(kd, histnl[X_UVM_HISTORIES].n_value, &histhead,
1141 1.45 thorpej sizeof(histhead)) != sizeof(histhead)) {
1142 1.45 thorpej warnx("unable to read %s: %s",
1143 1.45 thorpej histnl[X_UVM_HISTORIES].n_name, kvm_geterr(kd));
1144 1.45 thorpej return;
1145 1.45 thorpej }
1146 1.45 thorpej
1147 1.45 thorpej if (histhead.lh_first == NULL) {
1148 1.45 thorpej printf("No active UVM history logs.\n");
1149 1.45 thorpej return;
1150 1.45 thorpej }
1151 1.45 thorpej
1152 1.45 thorpej if (todo & HISTLIST)
1153 1.45 thorpej printf("Active UVM histories:");
1154 1.45 thorpej
1155 1.45 thorpej for (histkva = histhead.lh_first; histkva != NULL;
1156 1.45 thorpej histkva = hist.list.le_next) {
1157 1.45 thorpej if (kvm_read(kd, (u_long)histkva, &hist, sizeof(hist)) !=
1158 1.45 thorpej sizeof(hist)) {
1159 1.45 thorpej warnx("unable to read history at %p: %s",
1160 1.45 thorpej histkva, kvm_geterr(kd));
1161 1.45 thorpej goto out;
1162 1.45 thorpej }
1163 1.45 thorpej
1164 1.45 thorpej if (hist.namelen > namelen) {
1165 1.45 thorpej if (name != NULL)
1166 1.45 thorpej free(name);
1167 1.45 thorpej namelen = hist.namelen;
1168 1.45 thorpej if ((name = malloc(namelen + 1)) == NULL)
1169 1.45 thorpej err(1, "malloc history name");
1170 1.45 thorpej }
1171 1.45 thorpej
1172 1.45 thorpej if (kvm_read(kd, (u_long)hist.name, name, namelen) !=
1173 1.45 thorpej namelen) {
1174 1.45 thorpej warnx("unable to read history name at %p: %s",
1175 1.45 thorpej hist.name, kvm_geterr(kd));
1176 1.45 thorpej goto out;
1177 1.45 thorpej }
1178 1.45 thorpej name[namelen] = '\0';
1179 1.45 thorpej if (todo & HISTLIST)
1180 1.45 thorpej printf(" %s", name);
1181 1.45 thorpej else {
1182 1.45 thorpej /*
1183 1.45 thorpej * If we're dumping all histories, do it, else
1184 1.45 thorpej * check to see if this is the one we want.
1185 1.45 thorpej */
1186 1.45 thorpej if (histname == NULL || strcmp(histname, name) == 0) {
1187 1.45 thorpej if (histname == NULL)
1188 1.45 thorpej printf("\nUVM history `%s':\n", name);
1189 1.45 thorpej hist_dodump(&hist);
1190 1.45 thorpej }
1191 1.45 thorpej }
1192 1.45 thorpej }
1193 1.45 thorpej
1194 1.45 thorpej if (todo & HISTLIST)
1195 1.45 thorpej printf("\n");
1196 1.45 thorpej
1197 1.45 thorpej out:
1198 1.45 thorpej if (name != NULL)
1199 1.45 thorpej free(name);
1200 1.45 thorpej }
1201 1.45 thorpej
1202 1.45 thorpej /*
1203 1.45 thorpej * Actually dump the history buffer at the specified KVA.
1204 1.45 thorpej */
1205 1.45 thorpej void
1206 1.45 thorpej hist_dodump(histp)
1207 1.45 thorpej struct uvm_history *histp;
1208 1.45 thorpej {
1209 1.45 thorpej struct uvm_history_ent *histents, *e;
1210 1.45 thorpej size_t histsize;
1211 1.45 thorpej char *fmt = NULL, *fn = NULL;
1212 1.45 thorpej size_t fmtlen = 0, fnlen = 0;
1213 1.45 thorpej int i;
1214 1.45 thorpej
1215 1.45 thorpej histsize = sizeof(struct uvm_history_ent) * histp->n;
1216 1.45 thorpej
1217 1.45 thorpej if ((histents = malloc(histsize)) == NULL)
1218 1.45 thorpej err(1, "malloc history entries");
1219 1.45 thorpej
1220 1.45 thorpej memset(histents, 0, histsize);
1221 1.45 thorpej
1222 1.45 thorpej if (kvm_read(kd, (u_long)histp->e, histents, histsize) != histsize) {
1223 1.45 thorpej warnx("unable to read history entries at %p: %s",
1224 1.45 thorpej histp->e, kvm_geterr(kd));
1225 1.45 thorpej goto out;
1226 1.45 thorpej }
1227 1.45 thorpej
1228 1.45 thorpej i = histp->f;
1229 1.45 thorpej do {
1230 1.45 thorpej e = &histents[i];
1231 1.45 thorpej if (e->fmt != NULL) {
1232 1.45 thorpej if (e->fmtlen > fmtlen) {
1233 1.45 thorpej if (fmt != NULL)
1234 1.45 thorpej free(fmt);
1235 1.45 thorpej fmtlen = e->fmtlen;
1236 1.45 thorpej if ((fmt = malloc(fmtlen + 1)) == NULL)
1237 1.45 thorpej err(1, "malloc printf format");
1238 1.45 thorpej }
1239 1.45 thorpej if (e->fnlen > fnlen) {
1240 1.45 thorpej if (fn != NULL)
1241 1.45 thorpej free(fn);
1242 1.45 thorpej fnlen = e->fnlen;
1243 1.45 thorpej if ((fn = malloc(fnlen + 1)) == NULL)
1244 1.45 thorpej err(1, "malloc function name");
1245 1.45 thorpej }
1246 1.45 thorpej
1247 1.45 thorpej if (kvm_read(kd, (u_long)e->fmt, fmt, fmtlen)
1248 1.45 thorpej != fmtlen) {
1249 1.45 thorpej warnx("unable to read printf format "
1250 1.45 thorpej "at %p: %s", e->fmt, kvm_geterr(kd));
1251 1.45 thorpej goto out;
1252 1.45 thorpej }
1253 1.45 thorpej fmt[fmtlen] = '\0';
1254 1.45 thorpej
1255 1.45 thorpej if (kvm_read(kd, (u_long)e->fn, fn, fnlen) != fnlen) {
1256 1.45 thorpej warnx("unable to read function name "
1257 1.45 thorpej "at %p: %s", e->fn, kvm_geterr(kd));
1258 1.45 thorpej goto out;
1259 1.45 thorpej }
1260 1.45 thorpej fn[fnlen] = '\0';
1261 1.45 thorpej
1262 1.45 thorpej printf("%06ld.%06ld ", e->tv.tv_sec, e->tv.tv_usec);
1263 1.45 thorpej printf("%s#%ld: ", fn, e->call);
1264 1.45 thorpej printf(fmt, e->v[0], e->v[1], e->v[2], e->v[3]);
1265 1.45 thorpej printf("\n");
1266 1.45 thorpej }
1267 1.45 thorpej i = (i + 1) % histp->n;
1268 1.45 thorpej } while (i != histp->f);
1269 1.45 thorpej
1270 1.45 thorpej out:
1271 1.45 thorpej free(histents);
1272 1.45 thorpej if (fmt != NULL)
1273 1.45 thorpej free(fmt);
1274 1.45 thorpej if (fn != NULL)
1275 1.45 thorpej free(fn);
1276 1.45 thorpej }
1277 1.45 thorpej #endif /* UVM */
1278 1.45 thorpej
1279 1.1 cgd void
1280 1.1 cgd usage()
1281 1.1 cgd {
1282 1.47 mrg
1283 1.45 thorpej #if defined(UVM)
1284 1.1 cgd (void)fprintf(stderr,
1285 1.45 thorpej "usage: vmstat [-fHilms] [-h histname] [-c count] [-M core] \
1286 1.1 cgd [-N system] [-w wait] [disks]\n");
1287 1.45 thorpej #else
1288 1.45 thorpej (void)fprintf(stderr,
1289 1.45 thorpej "usage: vmstat [-fims] [-c count] [-M core] \
1290 1.45 thorpej [-N system] [-w wait] [disks]\n");
1291 1.45 thorpej #endif /* UVM */
1292 1.1 cgd exit(1);
1293 1.1 cgd }
1294