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