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