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