Commit | Line | Data |
---|---|---|
f42904bc | 1 | /* |
946db102 KB |
2 | * Copyright (c) 1980, 1986, 1991, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
01c8685d | 4 | * |
32ce521f | 5 | * %sccs.include.redist.c% |
f42904bc DF |
6 | */ |
7 | ||
8 | #ifndef lint | |
946db102 KB |
9 | static char copyright[] = |
10 | "@(#) Copyright (c) 1980, 1986, 1991, 1993\n\ | |
11 | The Regents of the University of California. All rights reserved.\n"; | |
01c8685d | 12 | #endif /* not lint */ |
f42904bc | 13 | |
338c4a5d | 14 | #ifndef lint |
586f1ff2 | 15 | static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) %G%"; |
01c8685d | 16 | #endif /* not lint */ |
338c4a5d | 17 | |
7f02df2f | 18 | #include <sys/param.h> |
6f7a6346 MK |
19 | #include <sys/time.h> |
20 | #include <sys/proc.h> | |
5ff3748f | 21 | #include <sys/user.h> |
920a4346 | 22 | #include <sys/dkstat.h> |
61d7d2b3 | 23 | #include <sys/buf.h> |
4b894a2c | 24 | #include <sys/namei.h> |
0c429495 | 25 | #include <sys/malloc.h> |
6f7a6346 MK |
26 | #include <sys/signal.h> |
27 | #include <sys/fcntl.h> | |
28 | #include <sys/ioctl.h> | |
038ba33c | 29 | #include <sys/sysctl.h> |
686c76a1 | 30 | #include <vm/vm.h> |
dd6bac83 | 31 | #include <time.h> |
f5506e0f | 32 | #include <nlist.h> |
dd6bac83 KB |
33 | #include <kvm.h> |
34 | #include <errno.h> | |
35 | #include <unistd.h> | |
0ef721f3 | 36 | #include <stdio.h> |
dd6bac83 | 37 | #include <ctype.h> |
0ef721f3 KB |
38 | #include <stdlib.h> |
39 | #include <string.h> | |
f5506e0f | 40 | #include <paths.h> |
4e39f603 | 41 | #include <limits.h> |
7f02df2f | 42 | |
686c76a1 | 43 | #define NEWVM /* XXX till old has been updated or purged */ |
357113aa | 44 | struct nlist namelist[] = { |
682f1dcb BJ |
45 | #define X_CPTIME 0 |
46 | { "_cp_time" }, | |
8fe01cde KM |
47 | #define X_DK_NDRIVE 1 |
48 | { "_dk_ndrive" }, | |
ecc9fa0b | 49 | #define X_SUM 2 |
8fe01cde | 50 | { "_cnt" }, |
ecc9fa0b | 51 | #define X_BOOTTIME 3 |
a43be079 | 52 | { "_boottime" }, |
ecc9fa0b | 53 | #define X_DKXFER 4 |
682f1dcb | 54 | { "_dk_xfer" }, |
ecc9fa0b | 55 | #define X_HZ 5 |
61d7d2b3 | 56 | { "_hz" }, |
4e39f603 SM |
57 | #define X_STATHZ 6 |
58 | { "_stathz" }, | |
ecc9fa0b | 59 | #define X_NCHSTATS 7 |
dfdfb4c8 | 60 | { "_nchstats" }, |
ecc9fa0b | 61 | #define X_INTRNAMES 8 |
4b894a2c | 62 | { "_intrnames" }, |
ecc9fa0b | 63 | #define X_EINTRNAMES 9 |
4b894a2c | 64 | { "_eintrnames" }, |
ecc9fa0b | 65 | #define X_INTRCNT 10 |
4b894a2c | 66 | { "_intrcnt" }, |
ecc9fa0b | 67 | #define X_EINTRCNT 11 |
4b894a2c | 68 | { "_eintrcnt" }, |
8fe01cde | 69 | #define X_KMEMSTAT 12 |
0c429495 | 70 | { "_kmemstats" }, |
8fe01cde | 71 | #define X_KMEMBUCKETS 13 |
0c429495 | 72 | { "_bucket" }, |
686c76a1 | 73 | #ifdef notdef |
8fe01cde | 74 | #define X_DEFICIT 14 |
6f7a6346 | 75 | { "_deficit" }, |
8fe01cde | 76 | #define X_FORKSTAT 15 |
6f7a6346 | 77 | { "_forkstat" }, |
8fe01cde | 78 | #define X_REC 16 |
6f7a6346 | 79 | { "_rectime" }, |
8fe01cde | 80 | #define X_PGIN 17 |
6f7a6346 | 81 | { "_pgintime" }, |
8fe01cde | 82 | #define X_XSTATS 18 |
6f7a6346 | 83 | { "_xstats" }, |
8fe01cde | 84 | #define X_END 18 |
686c76a1 | 85 | #else |
8fe01cde | 86 | #define X_END 14 |
6f7a6346 | 87 | #endif |
413f7539 | 88 | #if defined(hp300) || defined(luna68k) |
8fe01cde | 89 | #define X_HPDINIT (X_END) |
dd6bac83 | 90 | { "_hp_dinit" }, |
242684ee | 91 | #endif |
3b8aefc4 RC |
92 | #ifdef mips |
93 | #define X_SCSI_DINIT (X_END) | |
94 | { "_scsi_dinit" }, | |
95 | #endif | |
242684ee | 96 | #ifdef tahoe |
8fe01cde | 97 | #define X_VBDINIT (X_END) |
242684ee | 98 | { "_vbdinit" }, |
8fe01cde | 99 | #define X_CKEYSTATS (X_END+1) |
7aa7d88f | 100 | { "_ckeystats" }, |
8fe01cde | 101 | #define X_DKEYSTATS (X_END+2) |
7aa7d88f | 102 | { "_dkeystats" }, |
468dd322 | 103 | #endif |
dd6bac83 | 104 | #ifdef vax |
8fe01cde | 105 | #define X_MBDINIT (X_END) |
dd6bac83 | 106 | { "_mbdinit" }, |
8fe01cde | 107 | #define X_UBDINIT (X_END+1) |
dd6bac83 | 108 | { "_ubdinit" }, |
338c4a5d SL |
109 | #endif |
110 | { "" }, | |
7f02df2f BJ |
111 | }; |
112 | ||
dd6bac83 KB |
113 | struct _disk { |
114 | long time[CPUSTATES]; | |
115 | long *xfer; | |
116 | } cur, last; | |
7f02df2f | 117 | |
ecc9fa0b | 118 | struct vmmeter sum, osum; |
6f7a6346 MK |
119 | char **dr_name; |
120 | int *dr_select, dk_ndrive, ndrives; | |
121 | ||
122 | int winlines = 20; | |
920a4346 | 123 | |
4e39f603 SM |
124 | kvm_t *kd; |
125 | ||
0ef721f3 KB |
126 | #define FORKSTAT 0x01 |
127 | #define INTRSTAT 0x02 | |
128 | #define MEMSTAT 0x04 | |
129 | #define SUMSTAT 0x08 | |
130 | #define TIMESTAT 0x10 | |
131 | #define VMSTAT 0x20 | |
0ef721f3 | 132 | |
dd6bac83 KB |
133 | #include "names.c" /* disk names -- machine dependent */ |
134 | ||
6f7a6346 | 135 | void cpustats(), dkstats(), dointr(), domem(), dosum(); |
686c76a1 MK |
136 | void dovmstat(), kread(), usage(); |
137 | #ifdef notdef | |
6f7a6346 MK |
138 | void dotimes(), doforkst(); |
139 | #endif | |
dd6bac83 | 140 | |
7f02df2f | 141 | main(argc, argv) |
0ef721f3 KB |
142 | register int argc; |
143 | register char **argv; | |
7f02df2f | 144 | { |
0ef721f3 KB |
145 | extern int optind; |
146 | extern char *optarg; | |
dd6bac83 KB |
147 | register int c, todo; |
148 | u_int interval; | |
149 | int reps; | |
ad07e3a9 | 150 | char *memf, *nlistf; |
4e39f603 | 151 | char errbuf[_POSIX2_LINE_MAX]; |
dd6bac83 | 152 | |
ad07e3a9 | 153 | memf = nlistf = NULL; |
dd6bac83 | 154 | interval = reps = todo = 0; |
686c76a1 | 155 | while ((c = getopt(argc, argv, "c:fiM:mN:stw:")) != EOF) { |
0ef721f3 | 156 | switch (c) { |
dd6bac83 KB |
157 | case 'c': |
158 | reps = atoi(optarg); | |
159 | break; | |
686c76a1 | 160 | #ifndef notdef |
7f02df2f | 161 | case 'f': |
0ef721f3 KB |
162 | todo |= FORKSTAT; |
163 | break; | |
6f7a6346 | 164 | #endif |
0ef721f3 KB |
165 | case 'i': |
166 | todo |= INTRSTAT; | |
167 | break; | |
dd6bac83 | 168 | case 'M': |
ad07e3a9 | 169 | memf = optarg; |
0ef721f3 | 170 | break; |
0c429495 | 171 | case 'm': |
0ef721f3 KB |
172 | todo |= MEMSTAT; |
173 | break; | |
dd6bac83 | 174 | case 'N': |
ad07e3a9 | 175 | nlistf = optarg; |
dd6bac83 | 176 | break; |
7f02df2f | 177 | case 's': |
0ef721f3 | 178 | todo |= SUMSTAT; |
4b894a2c | 179 | break; |
686c76a1 | 180 | #ifndef notdef |
0ef721f3 KB |
181 | case 't': |
182 | todo |= TIMESTAT; | |
183 | break; | |
6f7a6346 | 184 | #endif |
dd6bac83 KB |
185 | case 'w': |
186 | interval = atoi(optarg); | |
0ef721f3 | 187 | break; |
0ef721f3 | 188 | case '?': |
7f02df2f | 189 | default: |
dd6bac83 | 190 | usage(); |
7f02df2f BJ |
191 | } |
192 | } | |
dd6bac83 KB |
193 | argc -= optind; |
194 | argv += optind; | |
0ef721f3 | 195 | |
0ef721f3 KB |
196 | if (todo == 0) |
197 | todo = VMSTAT; | |
198 | ||
ad07e3a9 KB |
199 | /* |
200 | * Discard setgid privileges if not the running kernel so that bad | |
201 | * guys can't print interesting stuff from kernel memory. | |
202 | */ | |
203 | if (nlistf != NULL || memf != NULL) | |
204 | setgid(getgid()); | |
205 | ||
4e39f603 SM |
206 | kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); |
207 | if (kd == 0) { | |
dd6bac83 | 208 | (void)fprintf(stderr, |
4e39f603 | 209 | "vmstat: kvm_openfiles: %s\n", errbuf); |
a448353a SL |
210 | exit(1); |
211 | } | |
0ef721f3 | 212 | |
357113aa | 213 | if ((c = kvm_nlist(kd, namelist)) != 0) { |
6f7a6346 MK |
214 | if (c > 0) { |
215 | (void)fprintf(stderr, | |
3b8aefc4 | 216 | "vmstat: undefined symbols:"); |
357113aa KB |
217 | for (c = 0; |
218 | c < sizeof(namelist)/sizeof(namelist[0]); c++) | |
219 | if (namelist[c].n_type == 0) | |
3b8aefc4 RC |
220 | fprintf(stderr, " %s", |
221 | namelist[c].n_name); | |
6f7a6346 MK |
222 | (void)fputc('\n', stderr); |
223 | } else | |
224 | (void)fprintf(stderr, "vmstat: kvm_nlist: %s\n", | |
4e39f603 | 225 | kvm_geterr(kd)); |
a448353a SL |
226 | exit(1); |
227 | } | |
0ef721f3 | 228 | |
dd6bac83 KB |
229 | if (todo & VMSTAT) { |
230 | char **getdrivedata(); | |
6f7a6346 | 231 | struct winsize winsize; |
dd6bac83 KB |
232 | |
233 | argv = getdrivedata(argv); | |
6f7a6346 MK |
234 | winsize.ws_row = 0; |
235 | (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize); | |
236 | if (winsize.ws_row > 0) | |
237 | winlines = winsize.ws_row; | |
238 | ||
dd6bac83 KB |
239 | } |
240 | ||
241 | #define BACKWARD_COMPATIBILITY | |
242 | #ifdef BACKWARD_COMPATIBILITY | |
243 | if (*argv) { | |
244 | interval = atoi(*argv); | |
245 | if (*++argv) | |
246 | reps = atoi(*argv); | |
247 | } | |
248 | #endif | |
249 | ||
5a168b67 KB |
250 | if (interval) { |
251 | if (!reps) | |
252 | reps = -1; | |
686c76a1 MK |
253 | } else if (reps) |
254 | interval = 1; | |
5a168b67 | 255 | |
686c76a1 | 256 | #ifdef notdef |
0ef721f3 KB |
257 | if (todo & FORKSTAT) |
258 | doforkst(); | |
6f7a6346 | 259 | #endif |
0ef721f3 KB |
260 | if (todo & MEMSTAT) |
261 | domem(); | |
262 | if (todo & SUMSTAT) | |
263 | dosum(); | |
686c76a1 | 264 | #ifdef notdef |
0ef721f3 KB |
265 | if (todo & TIMESTAT) |
266 | dotimes(); | |
6f7a6346 | 267 | #endif |
0ef721f3 KB |
268 | if (todo & INTRSTAT) |
269 | dointr(); | |
dd6bac83 KB |
270 | if (todo & VMSTAT) |
271 | dovmstat(interval, reps); | |
0ef721f3 KB |
272 | exit(0); |
273 | } | |
274 | ||
dd6bac83 KB |
275 | char ** |
276 | getdrivedata(argv) | |
0ef721f3 KB |
277 | char **argv; |
278 | { | |
279 | register int i; | |
280 | register char **cp; | |
0ef721f3 KB |
281 | char buf[30]; |
282 | ||
dd6bac83 | 283 | kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive)); |
0ef721f3 | 284 | if (dk_ndrive <= 0) { |
dd6bac83 | 285 | (void)fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive); |
0ef721f3 | 286 | exit(1); |
4b894a2c | 287 | } |
dd6bac83 KB |
288 | dr_select = calloc((size_t)dk_ndrive, sizeof(int)); |
289 | dr_name = calloc((size_t)dk_ndrive, sizeof(char *)); | |
0ef721f3 KB |
290 | for (i = 0; i < dk_ndrive; i++) |
291 | dr_name[i] = NULL; | |
dd6bac83 KB |
292 | cur.xfer = calloc((size_t)dk_ndrive, sizeof(long)); |
293 | last.xfer = calloc((size_t)dk_ndrive, sizeof(long)); | |
74a17228 KB |
294 | if (!read_names()) |
295 | exit (1); | |
dd6bac83 | 296 | for (i = 0; i < dk_ndrive; i++) |
0ef721f3 | 297 | if (dr_name[i] == NULL) { |
dd6bac83 | 298 | (void)sprintf(buf, "??%d", i); |
0ef721f3 KB |
299 | dr_name[i] = strdup(buf); |
300 | } | |
0ef721f3 | 301 | |
a448353a | 302 | /* |
dd6bac83 KB |
303 | * Choose drives to be displayed. Priority goes to (in order) drives |
304 | * supplied as arguments, default drives. If everything isn't filled | |
305 | * in and there are drives not taken care of, display the first few | |
306 | * that fit. | |
a448353a | 307 | */ |
dd6bac83 KB |
308 | #define BACKWARD_COMPATIBILITY |
309 | for (ndrives = 0; *argv; ++argv) { | |
310 | #ifdef BACKWARD_COMPATIBILITY | |
311 | if (isdigit(**argv)) | |
312 | break; | |
313 | #endif | |
a448353a | 314 | for (i = 0; i < dk_ndrive; i++) { |
dd6bac83 | 315 | if (strcmp(dr_name[i], *argv)) |
a448353a SL |
316 | continue; |
317 | dr_select[i] = 1; | |
dd6bac83 | 318 | ++ndrives; |
0ef721f3 | 319 | break; |
a448353a | 320 | } |
a448353a SL |
321 | } |
322 | for (i = 0; i < dk_ndrive && ndrives < 4; i++) { | |
323 | if (dr_select[i]) | |
324 | continue; | |
325 | for (cp = defdrives; *cp; cp++) | |
326 | if (strcmp(dr_name[i], *cp) == 0) { | |
327 | dr_select[i] = 1; | |
dd6bac83 | 328 | ++ndrives; |
a448353a SL |
329 | break; |
330 | } | |
331 | } | |
332 | for (i = 0; i < dk_ndrive && ndrives < 4; i++) { | |
333 | if (dr_select[i]) | |
334 | continue; | |
335 | dr_select[i] = 1; | |
dd6bac83 | 336 | ++ndrives; |
a448353a | 337 | } |
dd6bac83 | 338 | return(argv); |
0ef721f3 KB |
339 | } |
340 | ||
341 | long | |
342 | getuptime() | |
343 | { | |
dd6bac83 KB |
344 | static time_t now, boottime; |
345 | time_t uptime; | |
0ef721f3 KB |
346 | |
347 | if (boottime == 0) | |
dd6bac83 KB |
348 | kread(X_BOOTTIME, &boottime, sizeof(boottime)); |
349 | (void)time(&now); | |
0ef721f3 KB |
350 | uptime = now - boottime; |
351 | if (uptime <= 0 || uptime > 60*60*24*365*10) { | |
dd6bac83 | 352 | (void)fprintf(stderr, |
0ef721f3 KB |
353 | "vmstat: time makes no sense; namelist must be wrong.\n"); |
354 | exit(1); | |
355 | } | |
dd6bac83 | 356 | return(uptime); |
0ef721f3 KB |
357 | } |
358 | ||
ecc9fa0b | 359 | int hz, hdrcnt; |
5a168b67 | 360 | |
dd6bac83 KB |
361 | void |
362 | dovmstat(interval, reps) | |
363 | u_int interval; | |
364 | int reps; | |
0ef721f3 | 365 | { |
dd6bac83 | 366 | struct vmtotal total; |
686c76a1 | 367 | time_t uptime, halfuptime; |
6f7a6346 | 368 | void needhdr(); |
038ba33c | 369 | int mib[2], size; |
dd6bac83 KB |
370 | |
371 | uptime = getuptime(); | |
686c76a1 | 372 | halfuptime = uptime / 2; |
6f7a6346 | 373 | (void)signal(SIGCONT, needhdr); |
dd6bac83 | 374 | |
357113aa | 375 | if (namelist[X_STATHZ].n_type != 0 && namelist[X_STATHZ].n_value != 0) |
4e39f603 | 376 | kread(X_STATHZ, &hz, sizeof(hz)); |
5a168b67 KB |
377 | if (!hz) |
378 | kread(X_HZ, &hz, sizeof(hz)); | |
dd6bac83 KB |
379 | |
380 | for (hdrcnt = 1;;) { | |
6f7a6346 | 381 | if (!--hdrcnt) |
dd6bac83 | 382 | printhdr(); |
dd6bac83 | 383 | kread(X_CPTIME, cur.time, sizeof(cur.time)); |
db651481 | 384 | kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer) * dk_ndrive); |
dd6bac83 | 385 | kread(X_SUM, &sum, sizeof(sum)); |
8fe01cde | 386 | size = sizeof(total); |
038ba33c KM |
387 | mib[0] = CTL_VM; |
388 | mib[1] = VM_METER; | |
389 | if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) { | |
8fe01cde KM |
390 | printf("Can't get kerninfo: %s\n", strerror(errno)); |
391 | bzero(&total, sizeof(total)); | |
392 | } | |
393 | (void)printf("%2d%2d%2d", | |
cf2d3fce | 394 | total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw); |
8fe01cde | 395 | #define pgtok(a) ((a) * sum.v_page_size >> 10) |
686c76a1 | 396 | #define rate(x) (((x) + halfuptime) / uptime) /* round */ |
8fe01cde | 397 | (void)printf("%6ld%6ld ", |
dd6bac83 | 398 | pgtok(total.t_avm), pgtok(total.t_free)); |
ecc9fa0b | 399 | #ifdef NEWVM |
8fe01cde | 400 | (void)printf("%4lu ", rate(sum.v_faults - osum.v_faults)); |
ecc9fa0b | 401 | (void)printf("%3lu ", |
8fe01cde KM |
402 | rate(sum.v_reactivated - osum.v_reactivated)); |
403 | (void)printf("%3lu ", rate(sum.v_pageins - osum.v_pageins)); | |
ecc9fa0b | 404 | (void)printf("%3lu %3lu ", |
8fe01cde | 405 | rate(sum.v_pageouts - osum.v_pageouts), 0); |
ecc9fa0b MK |
406 | #else |
407 | (void)printf("%3lu %2lu ", | |
686c76a1 MK |
408 | rate(sum.v_pgrec - (sum.v_xsfrec+sum.v_xifrec) - |
409 | (osum.v_pgrec - (osum.v_xsfrec+osum.v_xifrec))), | |
410 | rate(sum.v_xsfrec + sum.v_xifrec - | |
411 | osum.v_xsfrec - osum.v_xifrec)); | |
ecc9fa0b | 412 | (void)printf("%3lu ", |
686c76a1 | 413 | rate(pgtok(sum.v_pgpgin - osum.v_pgpgin))); |
ecc9fa0b | 414 | (void)printf("%3lu %3lu ", |
686c76a1 MK |
415 | rate(pgtok(sum.v_pgpgout - osum.v_pgpgout)), |
416 | rate(pgtok(sum.v_dfree - osum.v_dfree))); | |
ecc9fa0b MK |
417 | (void)printf("%3d ", pgtok(deficit)); |
418 | #endif | |
686c76a1 | 419 | (void)printf("%3lu ", rate(sum.v_scan - osum.v_scan)); |
5a168b67 | 420 | dkstats(); |
ecc9fa0b | 421 | (void)printf("%4lu %4lu %3lu ", |
686c76a1 MK |
422 | rate(sum.v_intr - osum.v_intr), |
423 | rate(sum.v_syscall - osum.v_syscall), | |
424 | rate(sum.v_swtch - osum.v_swtch)); | |
5a168b67 | 425 | cpustats(); |
dd6bac83 KB |
426 | (void)printf("\n"); |
427 | (void)fflush(stdout); | |
5a168b67 | 428 | if (reps >= 0 && --reps <= 0) |
dd6bac83 | 429 | break; |
ecc9fa0b | 430 | osum = sum; |
686c76a1 MK |
431 | uptime = interval; |
432 | /* | |
433 | * We round upward to avoid losing low-frequency events | |
434 | * (i.e., >= 1 per interval but < 1 per second). | |
435 | */ | |
436 | halfuptime = (uptime + 1) / 2; | |
5a168b67 | 437 | (void)sleep(interval); |
7f02df2f BJ |
438 | } |
439 | } | |
440 | ||
4b894a2c KM |
441 | printhdr() |
442 | { | |
dd6bac83 KB |
443 | register int i; |
444 | ||
ecc9fa0b | 445 | (void)printf(" procs memory page%*s", 20, ""); |
dd6bac83 | 446 | if (ndrives > 1) |
ecc9fa0b | 447 | (void)printf("disks %*s faults cpu\n", |
dd6bac83 KB |
448 | ndrives * 3 - 6, ""); |
449 | else | |
ecc9fa0b MK |
450 | (void)printf("%*s faults cpu\n", ndrives * 3, ""); |
451 | #ifndef NEWVM | |
dd6bac83 | 452 | (void)printf(" r b w avm fre re at pi po fr de sr "); |
ecc9fa0b MK |
453 | #else |
454 | (void)printf(" r b w avm fre flt re pi po fr sr "); | |
455 | #endif | |
a448353a SL |
456 | for (i = 0; i < dk_ndrive; i++) |
457 | if (dr_select[i]) | |
dd6bac83 | 458 | (void)printf("%c%c ", dr_name[i][0], |
0ef721f3 | 459 | dr_name[i][strlen(dr_name[i]) - 1]); |
ecc9fa0b | 460 | (void)printf(" in sy cs us sy id\n"); |
6f7a6346 | 461 | hdrcnt = winlines - 2; |
4b894a2c KM |
462 | } |
463 | ||
6f7a6346 MK |
464 | /* |
465 | * Force a header to be prepended to the next output. | |
466 | */ | |
467 | void | |
468 | needhdr() | |
469 | { | |
470 | ||
471 | hdrcnt = 1; | |
472 | } | |
473 | ||
686c76a1 | 474 | #ifdef notdef |
dd6bac83 | 475 | void |
7f02df2f BJ |
476 | dotimes() |
477 | { | |
dd6bac83 KB |
478 | u_int pgintime, rectime; |
479 | ||
480 | kread(X_REC, &rectime, sizeof(rectime)); | |
481 | kread(X_PGIN, &pgintime, sizeof(pgintime)); | |
482 | kread(X_SUM, &sum, sizeof(sum)); | |
483 | (void)printf("%u reclaims, %u total time (usec)\n", | |
484 | sum.v_pgrec, rectime); | |
485 | (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec); | |
486 | (void)printf("\n"); | |
487 | (void)printf("%u page ins, %u total time (msec)\n", | |
488 | sum.v_pgin, pgintime / 10); | |
489 | (void)printf("average: %8.1f msec / page in\n", | |
490 | pgintime / (sum.v_pgin * 10.0)); | |
0ef721f3 | 491 | } |
6f7a6346 | 492 | #endif |
0ef721f3 KB |
493 | |
494 | pct(top, bot) | |
495 | long top, bot; | |
496 | { | |
0fa6b0ba KM |
497 | long ans; |
498 | ||
0ef721f3 | 499 | if (bot == 0) |
dd6bac83 | 500 | return(0); |
0fa6b0ba KM |
501 | ans = (quad_t)top * 100 / bot; |
502 | return (ans); | |
7f02df2f | 503 | } |
7f02df2f | 504 | |
0ef721f3 KB |
505 | #define PCT(top, bot) pct((long)(top), (long)(bot)) |
506 | ||
70b78b6e | 507 | #if defined(tahoe) |
0ef721f3 | 508 | #include <machine/cpu.h> |
70b78b6e SL |
509 | #endif |
510 | ||
dd6bac83 | 511 | void |
7f02df2f BJ |
512 | dosum() |
513 | { | |
a448353a | 514 | struct nchstats nchstats; |
6f7a6346 | 515 | #ifndef NEWVM |
7aa7d88f | 516 | struct xstats xstats; |
6f7a6346 | 517 | #endif |
dfdfb4c8 | 518 | long nchtotal; |
7aa7d88f SL |
519 | #if defined(tahoe) |
520 | struct keystats keystats; | |
521 | #endif | |
7f02df2f | 522 | |
dd6bac83 | 523 | kread(X_SUM, &sum, sizeof(sum)); |
8fe01cde KM |
524 | (void)printf("%9u cpu context switches\n", sum.v_swtch); |
525 | (void)printf("%9u device interrupts\n", sum.v_intr); | |
526 | (void)printf("%9u software interrupts\n", sum.v_soft); | |
527 | #ifdef vax | |
528 | (void)printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma); | |
529 | #endif | |
530 | (void)printf("%9u traps\n", sum.v_trap); | |
531 | (void)printf("%9u system calls\n", sum.v_syscall); | |
532 | (void)printf("%9u total faults taken\n", sum.v_faults); | |
dd6bac83 KB |
533 | (void)printf("%9u swap ins\n", sum.v_swpin); |
534 | (void)printf("%9u swap outs\n", sum.v_swpout); | |
535 | (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE); | |
536 | (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE); | |
8fe01cde KM |
537 | (void)printf("%9u page ins\n", sum.v_pageins); |
538 | (void)printf("%9u page outs\n", sum.v_pageouts); | |
dd6bac83 KB |
539 | (void)printf("%9u pages paged in\n", sum.v_pgpgin); |
540 | (void)printf("%9u pages paged out\n", sum.v_pgpgout); | |
8fe01cde KM |
541 | (void)printf("%9u pages reactivated\n", sum.v_reactivated); |
542 | (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); | |
543 | (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE); | |
544 | (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE); | |
545 | (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan); | |
546 | (void)printf("%9u revolutions of the clock hand\n", sum.v_rev); | |
547 | #ifdef NEWVM | |
548 | (void)printf("%9u VM object cache lookups\n", sum.v_lookups); | |
549 | (void)printf("%9u VM object hits\n", sum.v_hits); | |
550 | (void)printf("%9u total VM faults taken\n", sum.v_vm_faults); | |
551 | (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults); | |
552 | (void)printf("%9u pages freed by daemon\n", sum.v_dfree); | |
553 | (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree); | |
554 | (void)printf("%9u pages free\n", sum.v_free_count); | |
555 | (void)printf("%9u pages wired down\n", sum.v_wire_count); | |
556 | (void)printf("%9u pages active\n", sum.v_active_count); | |
557 | (void)printf("%9u pages inactive\n", sum.v_inactive_count); | |
558 | (void)printf("%9u bytes per page\n", sum.v_page_size); | |
586f1ff2 KM |
559 | (void)printf("%9u target inactive pages\n", sum.v_inactive_target); |
560 | (void)printf("%9u target free pages\n", sum.v_free_target); | |
561 | (void)printf("%9u minimum free pages\n", sum.v_free_min); | |
8fe01cde | 562 | #else |
dd6bac83 KB |
563 | (void)printf("%9u sequential process pages freed\n", sum.v_seqfree); |
564 | (void)printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec, | |
0ef721f3 | 565 | PCT(sum.v_fastpgrec, sum.v_pgrec)); |
dd6bac83 | 566 | (void)printf("%9u reclaims from free list\n", sum.v_pgfrec); |
dd6bac83 | 567 | (void)printf("%9u executable fill pages created\n", |
0ef721f3 | 568 | sum.v_nexfod / CLSIZE); |
dd6bac83 | 569 | (void)printf("%9u executable fill page faults\n", |
0ef721f3 | 570 | sum.v_exfod / CLSIZE); |
dd6bac83 | 571 | (void)printf("%9u swap text pages found in free list\n", |
0ef721f3 | 572 | sum.v_xsfrec); |
dd6bac83 | 573 | (void)printf("%9u inode text pages found in free list\n", |
0ef721f3 | 574 | sum.v_xifrec); |
dd6bac83 KB |
575 | (void)printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE); |
576 | (void)printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE); | |
dd6bac83 | 577 | (void)printf("%9u pages freed by the clock daemon\n", |
0ef721f3 | 578 | sum.v_dfree / CLSIZE); |
ecc9fa0b | 579 | #endif |
dd6bac83 | 580 | kread(X_NCHSTATS, &nchstats, sizeof(nchstats)); |
3aea8979 KM |
581 | nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits + |
582 | nchstats.ncs_badhits + nchstats.ncs_falsehits + | |
583 | nchstats.ncs_miss + nchstats.ncs_long; | |
dd6bac83 KB |
584 | (void)printf("%9ld total name lookups\n", nchtotal); |
585 | (void)printf( | |
0ef721f3 KB |
586 | "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n", |
587 | "", PCT(nchstats.ncs_goodhits, nchtotal), | |
588 | PCT(nchstats.ncs_neghits, nchtotal), | |
589 | PCT(nchstats.ncs_pass2, nchtotal)); | |
dd6bac83 | 590 | (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "", |
0ef721f3 KB |
591 | PCT(nchstats.ncs_badhits, nchtotal), |
592 | PCT(nchstats.ncs_falsehits, nchtotal), | |
593 | PCT(nchstats.ncs_long, nchtotal)); | |
6f7a6346 | 594 | #ifndef NEWVM |
dd6bac83 KB |
595 | kread(X_XSTATS, &xstats, sizeof(xstats)); |
596 | (void)printf("%9lu total calls to xalloc (cache hits %d%%)\n", | |
0ef721f3 | 597 | xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc)); |
dd6bac83 | 598 | (void)printf("%9s sticky %lu flushed %lu unused %lu\n", "", |
b6b10463 | 599 | xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused); |
dd6bac83 KB |
600 | (void)printf("%9lu total calls to xfree", xstats.free); |
601 | (void)printf(" (sticky %lu cached %lu swapped %lu)\n", | |
b6b10463 | 602 | xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap); |
6f7a6346 | 603 | #endif |
7aa7d88f | 604 | #if defined(tahoe) |
dd6bac83 KB |
605 | kread(X_CKEYSTATS, &keystats, sizeof(keystats)); |
606 | (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", | |
7aa7d88f | 607 | keystats.ks_allocs, "code cache keys allocated", |
0ef721f3 KB |
608 | PCT(keystats.ks_allocfree, keystats.ks_allocs), |
609 | PCT(keystats.ks_norefs, keystats.ks_allocs), | |
610 | PCT(keystats.ks_taken, keystats.ks_allocs), | |
611 | PCT(keystats.ks_shared, keystats.ks_allocs)); | |
dd6bac83 KB |
612 | kread(X_DKEYSTATS, &keystats, sizeof(keystats)); |
613 | (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", | |
7aa7d88f | 614 | keystats.ks_allocs, "data cache keys allocated", |
0ef721f3 KB |
615 | PCT(keystats.ks_allocfree, keystats.ks_allocs), |
616 | PCT(keystats.ks_norefs, keystats.ks_allocs), | |
617 | PCT(keystats.ks_taken, keystats.ks_allocs), | |
618 | PCT(keystats.ks_shared, keystats.ks_allocs)); | |
7aa7d88f | 619 | #endif |
7f02df2f BJ |
620 | } |
621 | ||
686c76a1 | 622 | #ifdef notdef |
dd6bac83 | 623 | void |
7f02df2f BJ |
624 | doforkst() |
625 | { | |
dd6bac83 | 626 | struct forkstat fks; |
7f02df2f | 627 | |
dd6bac83 KB |
628 | kread(X_FORKSTAT, &fks, sizeof(struct forkstat)); |
629 | (void)printf("%d forks, %d pages, average %.2f\n", | |
630 | fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork); | |
631 | (void)printf("%d vforks, %d pages, average %.2f\n", | |
632 | fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork); | |
7f02df2f | 633 | } |
6f7a6346 | 634 | #endif |
7f02df2f | 635 | |
dd6bac83 | 636 | void |
5a168b67 | 637 | dkstats() |
7f02df2f | 638 | { |
5a168b67 KB |
639 | register int dn, state; |
640 | double etime; | |
641 | long tmp; | |
642 | ||
643 | for (dn = 0; dn < dk_ndrive; ++dn) { | |
644 | tmp = cur.xfer[dn]; | |
645 | cur.xfer[dn] -= last.xfer[dn]; | |
646 | last.xfer[dn] = tmp; | |
647 | } | |
648 | etime = 0; | |
649 | for (state = 0; state < CPUSTATES; ++state) { | |
650 | tmp = cur.time[state]; | |
651 | cur.time[state] -= last.time[state]; | |
652 | last.time[state] = tmp; | |
653 | etime += cur.time[state]; | |
654 | } | |
655 | if (etime == 0) | |
656 | etime = 1; | |
657 | etime /= hz; | |
658 | for (dn = 0; dn < dk_ndrive; ++dn) { | |
659 | if (!dr_select[dn]) | |
660 | continue; | |
ecc9fa0b | 661 | (void)printf("%2.0f ", cur.xfer[dn] / etime); |
5a168b67 | 662 | } |
7f02df2f BJ |
663 | } |
664 | ||
5a168b67 KB |
665 | void |
666 | cpustats() | |
7f02df2f | 667 | { |
5a168b67 KB |
668 | register int state; |
669 | double pct, total; | |
670 | ||
671 | total = 0; | |
672 | for (state = 0; state < CPUSTATES; ++state) | |
673 | total += cur.time[state]; | |
674 | if (total) | |
675 | pct = 100 / total; | |
676 | else | |
677 | pct = 0; | |
7ca7ab96 RC |
678 | (void)printf("%2.0f ", (cur.time[CP_USER] + cur.time[CP_NICE]) * pct); |
679 | (void)printf("%2.0f ", (cur.time[CP_SYS] + cur.time[CP_INTR]) * pct); | |
680 | (void)printf("%2.0f", cur.time[CP_IDLE] * pct); | |
7f02df2f BJ |
681 | } |
682 | ||
dd6bac83 | 683 | void |
0ef721f3 | 684 | dointr() |
4b894a2c | 685 | { |
dd6bac83 | 686 | register long *intrcnt, inttotal, uptime; |
0ef721f3 | 687 | register int nintr, inamlen; |
0ef721f3 KB |
688 | register char *intrname; |
689 | ||
dd6bac83 | 690 | uptime = getuptime(); |
357113aa KB |
691 | nintr = namelist[X_EINTRCNT].n_value - namelist[X_INTRCNT].n_value; |
692 | inamlen = | |
693 | namelist[X_EINTRNAMES].n_value - namelist[X_INTRNAMES].n_value; | |
dd6bac83 | 694 | intrcnt = malloc((size_t)nintr); |
0ef721f3 | 695 | intrname = malloc((size_t)inamlen); |
4b894a2c | 696 | if (intrcnt == NULL || intrname == NULL) { |
dd6bac83 KB |
697 | (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno)); |
698 | exit(1); | |
4b894a2c | 699 | } |
dd6bac83 | 700 | kread(X_INTRCNT, intrcnt, (size_t)nintr); |
0ef721f3 | 701 | kread(X_INTRNAMES, intrname, (size_t)inamlen); |
dd6bac83 | 702 | (void)printf("interrupt total rate\n"); |
4b894a2c | 703 | inttotal = 0; |
0ef721f3 KB |
704 | nintr /= sizeof(long); |
705 | while (--nintr >= 0) { | |
4b894a2c | 706 | if (*intrcnt) |
dd6bac83 | 707 | (void)printf("%-12s %8ld %8ld\n", intrname, |
0ef721f3 | 708 | *intrcnt, *intrcnt / uptime); |
4b894a2c KM |
709 | intrname += strlen(intrname) + 1; |
710 | inttotal += *intrcnt++; | |
711 | } | |
dd6bac83 | 712 | (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime); |
4b894a2c KM |
713 | } |
714 | ||
0c429495 | 715 | /* |
b004c5f6 | 716 | * These names are defined in <sys/malloc.h>. |
0c429495 | 717 | */ |
b004c5f6 | 718 | char *kmemnames[] = INITKMEMNAMES; |
0c429495 | 719 | |
dd6bac83 | 720 | void |
0c429495 KM |
721 | domem() |
722 | { | |
0c429495 KM |
723 | register struct kmembuckets *kp; |
724 | register struct kmemstats *ks; | |
52fdec69 KM |
725 | register int i, j; |
726 | int len, size, first; | |
6f7a6346 | 727 | long totuse = 0, totfree = 0, totreq = 0; |
52fdec69 | 728 | char *name; |
0ef721f3 KB |
729 | struct kmemstats kmemstats[M_LAST]; |
730 | struct kmembuckets buckets[MINBUCKET + 16]; | |
0c429495 | 731 | |
dd6bac83 KB |
732 | kread(X_KMEMBUCKETS, buckets, sizeof(buckets)); |
733 | (void)printf("Memory statistics by bucket size\n"); | |
734 | (void)printf( | |
0ef721f3 | 735 | " Size In Use Free Requests HighWater Couldfree\n"); |
0c429495 KM |
736 | for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) { |
737 | if (kp->kb_calls == 0) | |
738 | continue; | |
6f7a6346 | 739 | size = 1 << i; |
ecc9fa0b | 740 | (void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size, |
0c429495 KM |
741 | kp->kb_total - kp->kb_totalfree, |
742 | kp->kb_totalfree, kp->kb_calls, | |
743 | kp->kb_highwat, kp->kb_couldfree); | |
6f7a6346 | 744 | totfree += size * kp->kb_totalfree; |
0c429495 | 745 | } |
6f7a6346 | 746 | |
dd6bac83 | 747 | kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats)); |
52fdec69 KM |
748 | (void)printf("\nMemory usage type by bucket size\n"); |
749 | (void)printf(" Size Type(s)\n"); | |
750 | kp = &buckets[MINBUCKET]; | |
751 | for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1, kp++) { | |
752 | if (kp->kb_calls == 0) | |
753 | continue; | |
754 | first = 1; | |
755 | len = 8; | |
756 | for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) { | |
757 | if (ks->ks_calls == 0) | |
758 | continue; | |
759 | if ((ks->ks_size & j) == 0) | |
760 | continue; | |
761 | name = kmemnames[i] ? kmemnames[i] : "undefined"; | |
762 | len += 2 + strlen(name); | |
763 | if (first) | |
764 | printf("%8d %s", j, name); | |
765 | else | |
766 | printf(","); | |
767 | if (len >= 80) { | |
768 | printf("\n\t "); | |
769 | len = 10 + strlen(name); | |
770 | } | |
771 | if (!first) | |
772 | printf(" %s", name); | |
773 | first = 0; | |
774 | } | |
775 | printf("\n"); | |
776 | } | |
777 | ||
dd6bac83 | 778 | (void)printf( |
52fdec69 KM |
779 | "\nMemory statistics by type Type Kern\n"); |
780 | (void)printf( | |
781 | " Type InUse MemUse HighUse Limit Requests Limit Limit Size(s)\n"); | |
0c429495 KM |
782 | for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) { |
783 | if (ks->ks_calls == 0) | |
784 | continue; | |
52fdec69 | 785 | (void)printf("%11s%6ld%6ldK%7ldK%6ldK%9ld%5u%6u", |
dd6bac83 KB |
786 | kmemnames[i] ? kmemnames[i] : "undefined", |
787 | ks->ks_inuse, (ks->ks_memuse + 1023) / 1024, | |
788 | (ks->ks_maxused + 1023) / 1024, | |
789 | (ks->ks_limit + 1023) / 1024, ks->ks_calls, | |
790 | ks->ks_limblocks, ks->ks_mapblocks); | |
52fdec69 KM |
791 | first = 1; |
792 | for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) { | |
793 | if ((ks->ks_size & j) == 0) | |
794 | continue; | |
795 | if (first) | |
796 | printf(" %d", j); | |
797 | else | |
798 | printf(",%d", j); | |
799 | first = 0; | |
800 | } | |
801 | printf("\n"); | |
6f7a6346 MK |
802 | totuse += ks->ks_memuse; |
803 | totreq += ks->ks_calls; | |
0c429495 | 804 | } |
6f7a6346 MK |
805 | (void)printf("\nMemory Totals: In Use Free Requests\n"); |
806 | (void)printf(" %7ldK %6ldK %8ld\n", | |
807 | (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq); | |
0c429495 KM |
808 | } |
809 | ||
242684ee | 810 | /* |
dd6bac83 | 811 | * kread reads something from the kernel, given its nlist index. |
242684ee | 812 | */ |
dd6bac83 KB |
813 | void |
814 | kread(nlx, addr, size) | |
815 | int nlx; | |
816 | void *addr; | |
817 | size_t size; | |
242684ee | 818 | { |
dd6bac83 KB |
819 | char *sym; |
820 | ||
357113aa KB |
821 | if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) { |
822 | sym = namelist[nlx].n_name; | |
dd6bac83 KB |
823 | if (*sym == '_') |
824 | ++sym; | |
825 | (void)fprintf(stderr, | |
ad07e3a9 | 826 | "vmstat: symbol %s not defined\n", sym); |
242684ee SL |
827 | exit(1); |
828 | } | |
357113aa KB |
829 | if (kvm_read(kd, namelist[nlx].n_value, addr, size) != size) { |
830 | sym = namelist[nlx].n_name; | |
dd6bac83 KB |
831 | if (*sym == '_') |
832 | ++sym; | |
4e39f603 | 833 | (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr(kd)); |
dd6bac83 | 834 | exit(1); |
242684ee SL |
835 | } |
836 | } | |
468dd322 | 837 | |
dd6bac83 KB |
838 | void |
839 | usage() | |
468dd322 | 840 | { |
dd6bac83 | 841 | (void)fprintf(stderr, |
6f7a6346 | 842 | #ifndef NEWVM |
dd6bac83 | 843 | "usage: vmstat [-fimst] [-c count] [-M core] \ |
686c76a1 | 844 | [-N system] [-w wait] [disks]\n"); |
6f7a6346 MK |
845 | #else |
846 | "usage: vmstat [-ims] [-c count] [-M core] \ | |
686c76a1 | 847 | [-N system] [-w wait] [disks]\n"); |
6f7a6346 | 848 | #endif |
dd6bac83 | 849 | exit(1); |
468dd322 | 850 | } |