xref: /original-bsd/usr.bin/vmstat/vmstat.c (revision 87a44d1b)
1 /*
2  * Copyright (c) 1980 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 char copyright[] =
20 "@(#) Copyright (c) 1980 The Regents of the University of California.\n\
21  All rights reserved.\n";
22 #endif /* not lint */
23 
24 #ifndef lint
25 static char sccsid[] = "@(#)vmstat.c	5.12 (Berkeley) 01/19/89";
26 #endif /* not lint */
27 
28 #include <stdio.h>
29 #include <ctype.h>
30 #include <nlist.h>
31 
32 #include <sys/param.h>
33 #include <sys/file.h>
34 #include <sys/vm.h>
35 #include <sys/dkstat.h>
36 #include <sys/buf.h>
37 #include <sys/dir.h>
38 #include <sys/inode.h>
39 #include <sys/namei.h>
40 #include <sys/text.h>
41 #include <sys/malloc.h>
42 
43 struct nlist nl[] = {
44 #define	X_CPTIME	0
45 	{ "_cp_time" },
46 #define	X_RATE		1
47 	{ "_rate" },
48 #define X_TOTAL		2
49 	{ "_total" },
50 #define	X_DEFICIT	3
51 	{ "_deficit" },
52 #define	X_FORKSTAT	4
53 	{ "_forkstat" },
54 #define X_SUM		5
55 	{ "_sum" },
56 #define	X_FIRSTFREE	6
57 	{ "_firstfree" },
58 #define	X_MAXFREE	7
59 	{ "_maxfree" },
60 #define	X_BOOTTIME	8
61 	{ "_boottime" },
62 #define	X_DKXFER	9
63 	{ "_dk_xfer" },
64 #define X_REC		10
65 	{ "_rectime" },
66 #define X_PGIN		11
67 	{ "_pgintime" },
68 #define X_HZ		12
69 	{ "_hz" },
70 #define X_PHZ		13
71 	{ "_phz" },
72 #define X_NCHSTATS	14
73 	{ "_nchstats" },
74 #define	X_INTRNAMES	15
75 	{ "_intrnames" },
76 #define	X_EINTRNAMES	16
77 	{ "_eintrnames" },
78 #define	X_INTRCNT	17
79 	{ "_intrcnt" },
80 #define	X_EINTRCNT	18
81 	{ "_eintrcnt" },
82 #define	X_DK_NDRIVE	19
83 	{ "_dk_ndrive" },
84 #define	X_XSTATS	20
85 	{ "_xstats" },
86 #define	X_KMEMSTAT	21
87 	{ "_kmemstats" },
88 #define	X_KMEMBUCKETS	22
89 	{ "_bucket" },
90 #ifdef vax
91 #define X_MBDINIT	(X_XSTATS+1)
92 	{ "_mbdinit" },
93 #define X_UBDINIT	(X_XSTATS+2)
94 	{ "_ubdinit" },
95 #endif
96 #ifdef tahoe
97 #define	X_VBDINIT	(X_XSTATS+1)
98 	{ "_vbdinit" },
99 #define	X_CKEYSTATS	(X_XSTATS+2)
100 	{ "_ckeystats" },
101 #define	X_DKEYSTATS	(X_XSTATS+3)
102 	{ "_dkeystats" },
103 #endif
104 	{ "" },
105 };
106 
107 char	**dr_name;
108 int	*dr_select;
109 int	dk_ndrive;
110 int	ndrives = 0;
111 #ifdef vax
112 char	*defdrives[] = { "hp0", "hp1", "hp2",  0 };
113 #else
114 char	*defdrives[] = { 0 };
115 #endif
116 double	stat1();
117 int	firstfree, maxfree;
118 int	hz;
119 int	phz;
120 int	HZ;
121 
122 struct {
123 	int	busy;
124 	long	time[CPUSTATES];
125 	long	*xfer;
126 	struct	vmmeter Rate;
127 	struct	vmtotal	Total;
128 	struct	vmmeter Sum;
129 	struct	forkstat Forkstat;
130 	unsigned rectime;
131 	unsigned pgintime;
132 } s, s1, z;
133 #define	rate		s.Rate
134 #define	total		s.Total
135 #define	sum		s.Sum
136 #define	forkstat	s.Forkstat
137 
138 struct	vmmeter osum;
139 int	deficit;
140 double	etime;
141 int 	mf;
142 time_t	now, boottime;
143 int	printhdr();
144 int	lines = 1;
145 
146 #define	INTS(x)	((x) - (hz + phz))
147 
148 main(argc, argv)
149 	int argc;
150 	char **argv;
151 {
152 	extern char *ctime();
153 	register i;
154 	int iter, nintv, iflag = 0;
155 	long t;
156 	char *arg, **cp, buf[BUFSIZ];
157 
158 	nlist("/vmunix", nl);
159 	if(nl[0].n_type == 0) {
160 		fprintf(stderr, "no /vmunix namelist\n");
161 		exit(1);
162 	}
163 	mf = open("/dev/kmem", 0);
164 	if(mf < 0) {
165 		fprintf(stderr, "cannot open /dev/kmem\n");
166 		exit(1);
167 	}
168 	iter = 0;
169 	argc--, argv++;
170 	while (argc>0 && argv[0][0]=='-') {
171 		char *cp = *argv++;
172 		argc--;
173 		while (*++cp) switch (*cp) {
174 
175 		case 't':
176 			dotimes();
177 			exit(0);
178 
179 		case 'z':
180 			close(mf);
181 			mf = open("/dev/kmem", 2);
182 			lseek(mf, (long)nl[X_SUM].n_value, L_SET);
183 			write(mf, &z.Sum, sizeof z.Sum);
184 			exit(0);
185 
186 		case 'f':
187 			doforkst();
188 			exit(0);
189 
190 		case 'm':
191 			domem();
192 			exit(0);
193 
194 		case 's':
195 			dosum();
196 			exit(0);
197 
198 		case 'i':
199 			iflag++;
200 			break;
201 
202 		default:
203 			fprintf(stderr,
204 			    "usage: vmstat [ -fsim ] [ interval ] [ count]\n");
205 			exit(1);
206 		}
207 	}
208 	lseek(mf, (long)nl[X_FIRSTFREE].n_value, L_SET);
209 	read(mf, &firstfree, sizeof firstfree);
210 	lseek(mf, (long)nl[X_MAXFREE].n_value, L_SET);
211 	read(mf, &maxfree, sizeof maxfree);
212 	lseek(mf, (long)nl[X_BOOTTIME].n_value, L_SET);
213 	read(mf, &boottime, sizeof boottime);
214 	lseek(mf, (long)nl[X_HZ].n_value, L_SET);
215 	read(mf, &hz, sizeof hz);
216 	if (nl[X_PHZ].n_value != 0) {
217 		lseek(mf, (long)nl[X_PHZ].n_value, L_SET);
218 		read(mf, &phz, sizeof phz);
219 	}
220 	HZ = phz ? phz : hz;
221 	if (nl[X_DK_NDRIVE].n_value == 0) {
222 		fprintf(stderr, "dk_ndrive undefined in system\n");
223 		exit(1);
224 	}
225 	lseek(mf, nl[X_DK_NDRIVE].n_value, L_SET);
226 	read(mf, &dk_ndrive, sizeof (dk_ndrive));
227 	if (dk_ndrive <= 0) {
228 		fprintf(stderr, "dk_ndrive %d\n", dk_ndrive);
229 		exit(1);
230 	}
231 	dr_select = (int *)calloc(dk_ndrive, sizeof (int));
232 	dr_name = (char **)calloc(dk_ndrive, sizeof (char *));
233 #define	allocate(e, t) \
234     s./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \
235     s1./**/e = (t *)calloc(dk_ndrive, sizeof (t));
236 	allocate(xfer, long);
237 	for (arg = buf, i = 0; i < dk_ndrive; i++) {
238 		dr_name[i] = arg;
239 		sprintf(dr_name[i], "dk%d", i);
240 		arg += strlen(dr_name[i]) + 1;
241 	}
242 	read_names();
243 	time(&now);
244 	nintv = now - boottime;
245 	if (nintv <= 0 || nintv > 60*60*24*365*10) {
246 		fprintf(stderr,
247 		    "Time makes no sense... namelist must be wrong.\n");
248 		exit(1);
249 	}
250 	if (iflag) {
251 		dointr(nintv);
252 		exit(0);
253 	}
254 	/*
255 	 * Choose drives to be displayed.  Priority
256 	 * goes to (in order) drives supplied as arguments,
257 	 * default drives.  If everything isn't filled
258 	 * in and there are drives not taken care of,
259 	 * display the first few that fit.
260 	 */
261 	ndrives = 0;
262 	while (argc > 0 && !isdigit(argv[0][0])) {
263 		for (i = 0; i < dk_ndrive; i++) {
264 			if (strcmp(dr_name[i], argv[0]))
265 				continue;
266 			dr_select[i] = 1;
267 			ndrives++;
268 		}
269 		argc--, argv++;
270 	}
271 	for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
272 		if (dr_select[i])
273 			continue;
274 		for (cp = defdrives; *cp; cp++)
275 			if (strcmp(dr_name[i], *cp) == 0) {
276 				dr_select[i] = 1;
277 				ndrives++;
278 				break;
279 			}
280 	}
281 	for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
282 		if (dr_select[i])
283 			continue;
284 		dr_select[i] = 1;
285 		ndrives++;
286 	}
287 	if (argc > 1)
288 		iter = atoi(argv[1]);
289 	signal(SIGCONT, printhdr);
290 loop:
291 	if (--lines == 0)
292 		printhdr();
293 	lseek(mf, (long)nl[X_CPTIME].n_value, L_SET);
294  	read(mf, s.time, sizeof s.time);
295 	lseek(mf, (long)nl[X_DKXFER].n_value, L_SET);
296 	read(mf, s.xfer, dk_ndrive * sizeof (long));
297 	if (nintv != 1)
298 		lseek(mf, (long)nl[X_SUM].n_value, L_SET);
299 	else
300 		lseek(mf, (long)nl[X_RATE].n_value, L_SET);
301 	read(mf, &rate, sizeof rate);
302 	lseek(mf, (long)nl[X_TOTAL].n_value, L_SET);
303 	read(mf, &total, sizeof total);
304 	osum = sum;
305 	lseek(mf, (long)nl[X_SUM].n_value, L_SET);
306 	read(mf, &sum, sizeof sum);
307 	lseek(mf, (long)nl[X_DEFICIT].n_value, L_SET);
308 	read(mf, &deficit, sizeof deficit);
309 	etime = 0;
310 	for (i=0; i < dk_ndrive; i++) {
311 		t = s.xfer[i];
312 		s.xfer[i] -= s1.xfer[i];
313 		s1.xfer[i] = t;
314 	}
315 	for (i=0; i < CPUSTATES; i++) {
316 		t = s.time[i];
317 		s.time[i] -= s1.time[i];
318 		s1.time[i] = t;
319 		etime += s.time[i];
320 	}
321 	if(etime == 0.)
322 		etime = 1.;
323 	printf("%2d%2d%2d", total.t_rq, total.t_dw+total.t_pw, total.t_sw);
324 #define pgtok(a) ((a)*NBPG/1024)
325 	printf("%6d%6d", pgtok(total.t_avm), pgtok(total.t_free));
326 	printf("%4d%3d", (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv,
327 	    (rate.v_xsfrec+rate.v_xifrec)/nintv);
328 	printf("%4d", pgtok(rate.v_pgpgin)/nintv);
329 	printf("%4d%4d%4d%4d", pgtok(rate.v_pgpgout)/nintv,
330 	    pgtok(rate.v_dfree)/nintv, pgtok(deficit), rate.v_scan/nintv);
331 	etime /= (float)HZ;
332 	for (i = 0; i < dk_ndrive; i++)
333 		if (dr_select[i])
334 			stats(i);
335 	printf("%4d%4d%4d", INTS(rate.v_intr/nintv), rate.v_syscall/nintv,
336 	    rate.v_swtch/nintv);
337 	for(i=0; i<CPUSTATES; i++) {
338 		float f = stat1(i);
339 		if (i == 0) {		/* US+NI */
340 			i++;
341 			f += stat1(i);
342 		}
343 		printf("%3.0f", f);
344 	}
345 	printf("\n");
346 	fflush(stdout);
347 	nintv = 1;
348 	if (--iter &&argc > 0) {
349 		sleep(atoi(argv[0]));
350 		goto loop;
351 	}
352 }
353 
354 printhdr()
355 {
356 	register int i, j;
357 
358 	printf(" procs     memory              page           ");
359 	i = (ndrives * 3 - 6) / 2;
360 	if (i < 0)
361 		i = 0;
362 	for (j = 0; j < i; j++)
363 		putchar(' ');
364 	printf("faults");
365 	i = ndrives * 3 - 6 - i;
366 	for (j = 0; j < i; j++)
367 		putchar(' ');
368 	printf("               cpu\n");
369 	printf(" r b w   avm   fre  re at  pi  po  fr  de  sr ");
370 	for (i = 0; i < dk_ndrive; i++)
371 		if (dr_select[i])
372 			printf("%c%c ", dr_name[i][0], dr_name[i][2]);
373 	printf(" in  sy  cs us sy id\n");
374 	lines = 19;
375 }
376 
377 dotimes()
378 {
379 
380 	lseek(mf, (long)nl[X_REC].n_value, L_SET);
381 	read(mf, &s.rectime, sizeof s.rectime);
382 	lseek(mf, (long)nl[X_PGIN].n_value, L_SET);
383 	read(mf, &s.pgintime, sizeof s.pgintime);
384 	lseek(mf, (long)nl[X_SUM].n_value, L_SET);
385 	read(mf, &sum, sizeof sum);
386 	printf("%d reclaims, %d total time (usec)\n", sum.v_pgrec, s.rectime);
387 	printf("average: %d usec / reclaim\n", s.rectime/sum.v_pgrec);
388 	printf("\n");
389 	printf("%d page ins, %d total time (msec)\n",sum.v_pgin, s.pgintime/10);
390 	printf("average: %8.1f msec / page in\n", s.pgintime/(sum.v_pgin*10.0));
391 }
392 
393 #if defined(tahoe)
394 #include <tahoe/cpu.h>
395 #endif
396 
397 dosum()
398 {
399 	struct nchstats nchstats;
400 	struct xstats xstats;
401 	long nchtotal;
402 #if defined(tahoe)
403 	struct keystats keystats;
404 #endif
405 
406 	lseek(mf, (long)nl[X_SUM].n_value, L_SET);
407 	read(mf, &sum, sizeof sum);
408 	printf("%9d swap ins\n", sum.v_swpin);
409 	printf("%9d swap outs\n", sum.v_swpout);
410 	printf("%9d pages swapped in\n", sum.v_pswpin / CLSIZE);
411 	printf("%9d pages swapped out\n", sum.v_pswpout / CLSIZE);
412 	printf("%9d total address trans. faults taken\n", sum.v_faults);
413 	printf("%9d page ins\n", sum.v_pgin);
414 	printf("%9d page outs\n", sum.v_pgout);
415 	printf("%9d pages paged in\n", sum.v_pgpgin);
416 	printf("%9d pages paged out\n", sum.v_pgpgout);
417 	printf("%9d sequential process pages freed\n", sum.v_seqfree);
418 	printf("%9d total reclaims (%d%% fast)\n", sum.v_pgrec,
419 	    pct(sum.v_fastpgrec, sum.v_pgrec));
420 	printf("%9d reclaims from free list\n", sum.v_pgfrec);
421 	printf("%9d intransit blocking page faults\n", sum.v_intrans);
422 	printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE);
423 	printf("%9d zero fill page faults\n", sum.v_zfod / CLSIZE);
424 	printf("%9d executable fill pages created\n", sum.v_nexfod / CLSIZE);
425 	printf("%9d executable fill page faults\n", sum.v_exfod / CLSIZE);
426 	printf("%9d swap text pages found in free list\n", sum.v_xsfrec);
427 	printf("%9d inode text pages found in free list\n", sum.v_xifrec);
428 	printf("%9d file fill pages created\n", sum.v_nvrfod / CLSIZE);
429 	printf("%9d file fill page faults\n", sum.v_vrfod / CLSIZE);
430 	printf("%9d pages examined by the clock daemon\n", sum.v_scan);
431 	printf("%9d revolutions of the clock hand\n", sum.v_rev);
432 	printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE);
433 	printf("%9d cpu context switches\n", sum.v_swtch);
434 	printf("%9d device interrupts\n", sum.v_intr);
435 	printf("%9d software interrupts\n", sum.v_soft);
436 #ifdef vax
437 	printf("%9d pseudo-dma dz interrupts\n", sum.v_pdma);
438 #endif
439 	printf("%9d traps\n", sum.v_trap);
440 	printf("%9d system calls\n", sum.v_syscall);
441 	lseek(mf, (long)nl[X_NCHSTATS].n_value, 0);
442 	read(mf, &nchstats, sizeof nchstats);
443 	nchtotal = nchstats.ncs_goodhits + nchstats.ncs_badhits +
444 	    nchstats.ncs_falsehits + nchstats.ncs_miss + nchstats.ncs_long;
445 	printf("%9d total name lookups", nchtotal);
446 	printf(" (cache hits %d%% system %d%% per-process)\n",
447 	    pct(nchstats.ncs_goodhits, nchtotal),
448 	    pct(nchstats.ncs_pass2, nchtotal));
449 	printf("%9s badhits %d, falsehits %d, toolong %d\n", "",
450 	    nchstats.ncs_badhits, nchstats.ncs_falsehits, nchstats.ncs_long);
451 	lseek(mf, (long)nl[X_XSTATS].n_value, 0);
452 	read(mf, &xstats, sizeof xstats);
453 	printf("%9d total calls to xalloc (cache hits %d%%)\n",
454 	    xstats.alloc, pct(xstats.alloc_cachehit, xstats.alloc));
455 	printf("%9s sticky %d flushed %d unused %d\n", "",
456 	    xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused);
457 	printf("%9d total calls to xfree", xstats.free);
458 	printf(" (sticky %d cached %d swapped %d)\n",
459 	    xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap);
460 #if defined(tahoe)
461 	lseek(mf, (long)nl[X_CKEYSTATS].n_value, 0);
462 	read(mf, &keystats, sizeof keystats);
463 	printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
464 	    keystats.ks_allocs, "code cache keys allocated",
465 	    pct(keystats.ks_allocfree, keystats.ks_allocs),
466 	    pct(keystats.ks_norefs, keystats.ks_allocs),
467 	    pct(keystats.ks_taken, keystats.ks_allocs),
468 	    pct(keystats.ks_shared, keystats.ks_allocs));
469 	lseek(mf, (long)nl[X_DKEYSTATS].n_value, 0);
470 	read(mf, &keystats, sizeof keystats);
471 	printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
472 	    keystats.ks_allocs, "data cache keys allocated",
473 	    pct(keystats.ks_allocfree, keystats.ks_allocs),
474 	    pct(keystats.ks_norefs, keystats.ks_allocs),
475 	    pct(keystats.ks_taken, keystats.ks_allocs),
476 	    pct(keystats.ks_shared, keystats.ks_allocs));
477 #endif
478 }
479 
480 doforkst()
481 {
482 
483 	lseek(mf, (long)nl[X_FORKSTAT].n_value, L_SET);
484 	read(mf, &forkstat, sizeof forkstat);
485 	printf("%d forks, %d pages, average=%.2f\n",
486 		forkstat.cntfork, forkstat.sizfork,
487 		(float) forkstat.sizfork / forkstat.cntfork);
488 	printf("%d vforks, %d pages, average=%.2f\n",
489 		forkstat.cntvfork, forkstat.sizvfork,
490 		(float)forkstat.sizvfork / forkstat.cntvfork);
491 }
492 
493 stats(dn)
494 {
495 
496 	if (dn >= dk_ndrive) {
497 		printf("  0");
498 		return;
499 	}
500 	printf("%3.0f", s.xfer[dn]/etime);
501 }
502 
503 double
504 stat1(row)
505 {
506 	double t;
507 	register i;
508 
509 	t = 0;
510 	for(i=0; i<CPUSTATES; i++)
511 		t += s.time[i];
512 	if(t == 0.)
513 		t = 1.;
514 	return(s.time[row]*100./t);
515 }
516 
517 pct(top, bot)
518 {
519 
520 	if (bot == 0)
521 		return (0);
522 	return ((top * 100) / bot);
523 }
524 
525 dointr(nintv)
526 {
527 	int nintr, inttotal;
528 	long *intrcnt;
529 	char *intrname, *malloc();
530 
531 	nintr = (nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value) / sizeof(long);
532 	intrcnt = (long *) malloc(nl[X_EINTRCNT].n_value -
533 		nl[X_INTRCNT].n_value);
534 	intrname = malloc(nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value);
535 	if (intrcnt == NULL || intrname == NULL) {
536 		fprintf(stderr, "vmstat: out of memory\n");
537 		exit(9);
538 	}
539 	lseek(mf, (long)nl[X_INTRCNT].n_value, L_SET);
540 	read(mf, intrcnt, nintr * sizeof (long));
541 	lseek(mf, (long)nl[X_INTRNAMES].n_value, L_SET);
542 	read(mf, intrname, nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value);
543 	printf("interrupt      total      rate\n");
544 	inttotal = 0;
545 	while (nintr--) {
546 		if (*intrcnt)
547 			printf("%-12s %8ld %8ld\n", intrname,
548 			    *intrcnt, *intrcnt / nintv);
549 		intrname += strlen(intrname) + 1;
550 		inttotal += *intrcnt++;
551 	}
552 	printf("Total        %8ld %8ld\n", inttotal, inttotal / nintv);
553 }
554 
555 /*
556  * These names must be kept in sync with
557  * the types defined in <sys/malloc.h>.
558  */
559 char *kmemnames[] = {
560 	"free",		/* 0 M_FREE */
561 	"mbuf",		/* 1 M_MBUF */
562 	"devbuf",	/* 2 M_DEVBUF */
563 	"socket",	/* 3 M_SOCKET */
564 	"pcb",		/* 4 M_PCB */
565 	"routetbl",	/* 5 M_RTABLE */
566 	"hosttbl",	/* 6 M_HTABLE */
567 	"fragtbl",	/* 7 M_FTABLE */
568 	"zombie",	/* 8 M_ZOMBIE */
569 	"ifaddr",	/* 9 M_IFADDR */
570 	"soopts",	/* 10 M_SOOPTS */
571 	"soname",	/* 11 M_SONAME */
572 	"namei",	/* 12 M_NAMEI */
573 	"gprof",	/* 13 M_GPROF */
574 	"ioctlops",	/* 14 M_IOCTLOPS */
575 	"superblk",	/* 15 M_SUPERBLK */
576 	"cred",		/* 16 M_CRED */
577 	"pgrp",		/* 17 M_PGRP */
578 	"session",	/* 18 M_SESSION */
579 	"iov",		/* 19 M_IOV */
580 	0, 0, 0, 0, 0,
581 	0, 0, 0, 0, 0,
582 	0, 0, 0, 0, 0,
583 	0, 0, 0, 0, 0,
584 	0, 0, 0, 0, 0,
585 	0, 0, 0, 0,
586 	"temp",		/* 49 M_TEMP */
587 };
588 
589 domem()
590 {
591 	struct kmemstats kmemstats[M_LAST];
592 	struct kmembuckets buckets[MINBUCKET + 16];
593 	register struct kmembuckets *kp;
594 	register struct kmemstats *ks;
595 	int i;
596 
597 	lseek(mf, (long)nl[X_KMEMBUCKETS].n_value, L_SET);
598 	read(mf, buckets, sizeof buckets);
599 	printf("Memory statistics by bucket size\n");
600 	printf("    Size   In Use   Free   Requests  HighWater  Couldfree\n");
601 	for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) {
602 		if (kp->kb_calls == 0)
603 			continue;
604 		printf("%8d%9d%7d%11d%8d%11d\n", 1 << i,
605 			kp->kb_total - kp->kb_totalfree,
606 			kp->kb_totalfree, kp->kb_calls,
607 			kp->kb_highwat, kp->kb_couldfree);
608 
609 	}
610 	lseek(mf, (long)nl[X_KMEMSTAT].n_value, L_SET);
611 	read(mf, kmemstats, sizeof kmemstats);
612 	printf("Memory statistics by type\n");
613 	printf("     Type   In Use  MemUse   HighUse  Limit  Requests %s\n",
614 		"TypeLimit KernLimit");
615 	for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
616 		if (ks->ks_calls == 0)
617 			continue;
618 		printf("%10s%7d%8dK%9dK%6dK%9d%7d%10d\n",
619 			kmemnames[i] ? kmemnames[i] : "undefined",
620 			ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
621 			(ks->ks_maxused + 1023) / 1024,
622 			(ks->ks_limit + 1023) / 1024, ks->ks_calls,
623 			ks->ks_limblocks, ks->ks_mapblocks);
624 	}
625 }
626 
627 #define steal(where, var) \
628 	lseek(mf, where, L_SET); read(mf, &var, sizeof var);
629 /*
630  * Read the drive names out of kmem.
631  */
632 #ifdef vax
633 #include <vaxuba/ubavar.h>
634 #include <vaxmba/mbavar.h>
635 
636 read_names()
637 {
638 	struct mba_device mdev;
639 	register struct mba_device *mp;
640 	struct mba_driver mdrv;
641 	short two_char;
642 	char *cp = (char *) &two_char;
643 	struct uba_device udev, *up;
644 	struct uba_driver udrv;
645 
646 	mp = (struct mba_device *) nl[X_MBDINIT].n_value;
647 	up = (struct uba_device *) nl[X_UBDINIT].n_value;
648 	if (up == 0) {
649 		fprintf(stderr, "vmstat: Disk init info not in namelist\n");
650 		exit(1);
651 	}
652 	if (mp) for (;;) {
653 		steal(mp++, mdev);
654 		if (mdev.mi_driver == 0)
655 			break;
656 		if (mdev.mi_dk < 0 || mdev.mi_alive == 0)
657 			continue;
658 		steal(mdev.mi_driver, mdrv);
659 		steal(mdrv.md_dname, two_char);
660 		sprintf(dr_name[mdev.mi_dk], "%c%c%d",
661 		    cp[0], cp[1], mdev.mi_unit);
662 	}
663 	for (;;) {
664 		steal(up++, udev);
665 		if (udev.ui_driver == 0)
666 			break;
667 		if (udev.ui_dk < 0 || udev.ui_alive == 0)
668 			continue;
669 		steal(udev.ui_driver, udrv);
670 		steal(udrv.ud_dname, two_char);
671 		sprintf(dr_name[udev.ui_dk], "%c%c%d",
672 		    cp[0], cp[1], udev.ui_unit);
673 	}
674 }
675 #endif
676 
677 #ifdef tahoe
678 #include <tahoevba/vbavar.h>
679 
680 /*
681  * Read the drive names out of kmem.
682  */
683 read_names()
684 {
685 	struct vba_device udev, *up;
686 	struct vba_driver udrv;
687 	short two_char;
688 	char *cp = (char *)&two_char;
689 
690 	up = (struct vba_device *) nl[X_VBDINIT].n_value;
691 	if (up == 0) {
692 		fprintf(stderr, "vmstat: Disk init info not in namelist\n");
693 		exit(1);
694 	}
695 	for (;;) {
696 		steal(up++, udev);
697 		if (udev.ui_driver == 0)
698 			break;
699 		if (udev.ui_dk < 0 || udev.ui_alive == 0)
700 			continue;
701 		steal(udev.ui_driver, udrv);
702 		steal(udrv.ud_dname, two_char);
703 		sprintf(dr_name[udev.ui_dk], "%c%c%d",
704 		     cp[0], cp[1], udev.ui_unit);
705 	}
706 }
707 #endif
708