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