File: | src/usr.bin/vmstat/vmstat.c |
Warning: | line 182, column 2 Value stored to 'argc' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $NetBSD: vmstat.c,v 1.29.4.1 1996/06/05 00:21:05 cgd Exp $ */ |
2 | /* $OpenBSD: vmstat.c,v 1.151 2021/07/12 15:09:20 beck Exp $ */ |
3 | |
4 | /* |
5 | * Copyright (c) 1980, 1986, 1991, 1993 |
6 | * The Regents of the University of California. All rights reserved. |
7 | * |
8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions |
10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. |
16 | * 3. Neither the name of the University nor the names of its contributors |
17 | * may be used to endorse or promote products derived from this software |
18 | * without specific prior written permission. |
19 | * |
20 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
30 | * SUCH DAMAGE. |
31 | */ |
32 | |
33 | #include <sys/param.h> /* MAXCOMLEN */ |
34 | #include <sys/time.h> |
35 | #include <sys/proc.h> |
36 | #include <sys/namei.h> |
37 | #include <sys/malloc.h> |
38 | #include <sys/ioctl.h> |
39 | #include <sys/sysctl.h> |
40 | #include <sys/device.h> |
41 | #include <sys/pool.h> |
42 | #include <sys/sched.h> |
43 | #include <sys/vmmeter.h> |
44 | |
45 | #include <ctype.h> |
46 | #include <err.h> |
47 | #include <errno(*__errno()).h> |
48 | #include <fcntl.h> |
49 | #include <kvm.h> |
50 | #include <limits.h> |
51 | #include <nlist.h> |
52 | #include <paths.h> |
53 | #include <signal.h> |
54 | #include <stdio.h> |
55 | #include <stdlib.h> |
56 | #include <string.h> |
57 | #include <time.h> |
58 | #include <unistd.h> |
59 | |
60 | #include "dkstats.h" |
61 | |
62 | struct nlist namelist[] = { |
63 | #define X_UVMEXP0 0 /* sysctl */ |
64 | { "_uvmexp" }, |
65 | #define X_TIME_UPTIME1 1 |
66 | { "_time_uptime" }, |
67 | #define X_NCHSTATS2 2 /* sysctl */ |
68 | { "_nchstats" }, |
69 | #define X_KMEMSTAT3 3 /* sysctl */ |
70 | { "_kmemstats" }, |
71 | #define X_KMEMBUCKETS4 4 /* sysctl */ |
72 | { "_bucket" }, |
73 | #define X_FORKSTAT5 5 /* sysctl */ |
74 | { "_forkstat" }, |
75 | #define X_NSELCOLL6 6 /* sysctl */ |
76 | { "_nselcoll" }, |
77 | #define X_POOLHEAD7 7 /* sysctl */ |
78 | { "_pool_head" }, |
79 | #define X_NAPTIME8 8 |
80 | { "_naptime" }, |
81 | { "" }, |
82 | }; |
83 | |
84 | /* Objects defined in dkstats.c */ |
85 | extern struct _disk cur, last; |
86 | extern char **dr_name; |
87 | extern int *dk_select, dk_ndrive; |
88 | |
89 | struct uvmexp uvmexp, ouvmexp; |
90 | int ndrives; |
91 | |
92 | int winlines = 20; |
93 | |
94 | kvm_t *kd; |
95 | |
96 | #define FORKSTAT0x01 0x01 |
97 | #define INTRSTAT0x02 0x02 |
98 | #define MEMSTAT0x04 0x04 |
99 | #define SUMSTAT0x08 0x08 |
100 | #define TIMESTAT0x10 0x10 |
101 | #define VMSTAT0x20 0x20 |
102 | |
103 | void cpustats(void); |
104 | time_t getuptime(void); |
105 | void dkstats(void); |
106 | void dointr(void); |
107 | void domem(void); |
108 | void dopool(void); |
109 | void dosum(void); |
110 | void dovmstat(u_int, int); |
111 | void kread(int, void *, size_t); |
112 | void usage(void); |
113 | void dotimes(void); |
114 | void doforkst(void); |
115 | void needhdr(int); |
116 | int pct(int64_t, int64_t); |
117 | void printhdr(void); |
118 | |
119 | char **choosedrives(char **); |
120 | |
121 | /* Namelist and memory file names. */ |
122 | char *nlistf, *memf; |
123 | |
124 | extern char *__progname; |
125 | |
126 | int verbose = 0; |
127 | int zflag = 0; |
128 | |
129 | int |
130 | main(int argc, char *argv[]) |
131 | { |
132 | char errbuf[_POSIX2_LINE_MAX2048]; |
133 | int c, todo = 0, reps = 0; |
134 | struct winsize winsize; |
135 | const char *errstr; |
136 | u_int interval = 0; |
137 | |
138 | while ((c = getopt(argc, argv, "c:fiM:mN:stw:vz")) != -1) { |
139 | switch (c) { |
140 | case 'c': |
141 | reps = strtonum(optarg, 0, INT_MAX2147483647, &errstr); |
142 | if (errstr) |
143 | errx(1, "-c %s: %s", optarg, errstr); |
144 | break; |
145 | case 'f': |
146 | todo |= FORKSTAT0x01; |
147 | break; |
148 | case 'i': |
149 | todo |= INTRSTAT0x02; |
150 | break; |
151 | case 'M': |
152 | memf = optarg; |
153 | break; |
154 | case 'm': |
155 | todo |= MEMSTAT0x04; |
156 | break; |
157 | case 'N': |
158 | nlistf = optarg; |
159 | break; |
160 | case 's': |
161 | todo |= SUMSTAT0x08; |
162 | break; |
163 | case 't': |
164 | todo |= TIMESTAT0x10; |
165 | break; |
166 | case 'w': |
167 | interval = (u_int)strtonum(optarg, 0, 1000, &errstr); |
168 | if (errstr) |
169 | errx(1, "-w %s: %s", optarg, errstr); |
170 | break; |
171 | case 'v': |
172 | verbose = 1; |
173 | break; |
174 | case 'z': |
175 | zflag = 1; |
176 | break; |
177 | case '?': |
178 | default: |
179 | usage(); |
180 | } |
181 | } |
182 | argc -= optind; |
Value stored to 'argc' is never read | |
183 | argv += optind; |
184 | |
185 | if (todo == 0) |
186 | todo = VMSTAT0x20; |
187 | |
188 | if (nlistf != NULL((void *)0) || memf != NULL((void *)0)) { |
189 | kd = kvm_openfiles(nlistf, memf, NULL((void *)0), O_RDONLY0x0000, errbuf); |
190 | if (kd == 0) |
191 | errx(1, "kvm_openfiles: %s", errbuf); |
192 | |
193 | if ((c = kvm_nlist(kd, namelist)) != 0) { |
194 | if (c > 0) { |
195 | (void)fprintf(stderr(&__sF[2]), |
196 | "%s: undefined symbols:", __progname); |
197 | for (c = 0; |
198 | c < sizeof(namelist)/sizeof(namelist[0]); |
199 | c++) |
200 | if (namelist[c].n_type == 0) |
201 | fprintf(stderr(&__sF[2]), " %s", |
202 | namelist[c].n_name); |
203 | (void)fputc('\n', stderr(&__sF[2])); |
204 | exit(1); |
205 | } else |
206 | errx(1, "kvm_nlist: %s", kvm_geterr(kd)); |
207 | } |
208 | } |
209 | |
210 | if (todo & VMSTAT0x20) { |
211 | dkinit(0); /* Initialize disk stats, no disks selected. */ |
212 | argv = choosedrives(argv); /* Select disks. */ |
213 | } |
214 | |
215 | if (unveil("/", "") == -1) |
216 | err(1, "unveil /"); |
217 | if (unveil(NULL((void *)0), NULL((void *)0)) == -1) |
218 | err(1, "unveil"); |
219 | |
220 | winsize.ws_row = 0; |
221 | if (ioctl(STDOUT_FILENO1, TIOCGWINSZ((unsigned long)0x40000000 | ((sizeof(struct winsize) & 0x1fff ) << 16) | ((('t')) << 8) | ((104))), &winsize) == 0) { |
222 | if (winsize.ws_row > 0) |
223 | winlines = winsize.ws_row; |
224 | } |
225 | |
226 | #define BACKWARD_COMPATIBILITY |
227 | #ifdef BACKWARD_COMPATIBILITY |
228 | if (*argv) { |
229 | interval = (u_int)strtonum(*argv, 0, 1000, &errstr); |
230 | if (errstr) |
231 | errx(1, "interval %s: %s", *argv, errstr); |
232 | |
233 | if (*++argv) { |
234 | reps = strtonum(*argv, 0, INT_MAX2147483647, &errstr); |
235 | if (errstr) |
236 | errx(1, "reps %s: %s", *argv, errstr); |
237 | } |
238 | } |
239 | #endif |
240 | |
241 | if (interval) { |
242 | if (!reps) |
243 | reps = -1; |
244 | } else if (reps) |
245 | interval = 1; |
246 | |
247 | if (todo & FORKSTAT0x01) |
248 | doforkst(); |
249 | if (todo & MEMSTAT0x04) { |
250 | domem(); |
251 | dopool(); |
252 | } |
253 | if (todo & SUMSTAT0x08) |
254 | dosum(); |
255 | if (todo & TIMESTAT0x10) |
256 | dotimes(); |
257 | if (todo & INTRSTAT0x02) |
258 | dointr(); |
259 | if (todo & VMSTAT0x20) |
260 | dovmstat(interval, reps); |
261 | exit(0); |
262 | } |
263 | |
264 | char ** |
265 | choosedrives(char **argv) |
266 | { |
267 | int i; |
268 | |
269 | /* |
270 | * Choose drives to be displayed. Priority goes to (in order) drives |
271 | * supplied as arguments, default drives. If everything isn't filled |
272 | * in and there are drives not taken care of, display the first few |
273 | * that fit. |
274 | */ |
275 | #define BACKWARD_COMPATIBILITY |
276 | for (ndrives = 0; *argv; ++argv) { |
277 | #ifdef BACKWARD_COMPATIBILITY |
278 | if (isdigit((unsigned char)**argv)) |
279 | break; |
280 | #endif |
281 | for (i = 0; i < dk_ndrive; i++) { |
282 | if (strcmp(dr_name[i], *argv)) |
283 | continue; |
284 | dk_select[i] = 1; |
285 | ++ndrives; |
286 | break; |
287 | } |
288 | if (i == dk_ndrive) |
289 | errx(1, "invalid interval or drive name: %s", *argv); |
290 | } |
291 | for (i = 0; i < dk_ndrive && ndrives < 2; i++) { |
292 | if (dk_select[i]) |
293 | continue; |
294 | dk_select[i] = 1; |
295 | ++ndrives; |
296 | } |
297 | return(argv); |
298 | } |
299 | |
300 | time_t |
301 | getuptime(void) |
302 | { |
303 | struct timespec uptime; |
304 | time_t time_uptime, naptime; |
305 | |
306 | if (nlistf == NULL((void *)0) && memf == NULL((void *)0)) { |
307 | if (clock_gettime(CLOCK_UPTIME5, &uptime) == -1) |
308 | err(1, "clock_gettime"); |
309 | return (uptime.tv_sec); |
310 | } |
311 | |
312 | kread(X_NAPTIME8, &naptime, sizeof(naptime)); |
313 | kread(X_TIME_UPTIME1, &time_uptime, sizeof(time_uptime)); |
314 | return (time_uptime - naptime); |
315 | } |
316 | |
317 | int hz; |
318 | volatile sig_atomic_t hdrcnt; |
319 | |
320 | void |
321 | dovmstat(u_int interval, int reps) |
322 | { |
323 | time_t uptime, halfuptime; |
324 | struct clockinfo clkinfo; |
325 | struct vmtotal total; |
326 | size_t size; |
327 | int mib[2]; |
328 | |
329 | uptime = getuptime(); |
330 | halfuptime = uptime / 2; |
331 | (void)signal(SIGCONT19, needhdr); |
332 | |
333 | mib[0] = CTL_KERN1; |
334 | mib[1] = KERN_CLOCKRATE12; |
335 | size = sizeof(clkinfo); |
336 | if (sysctl(mib, 2, &clkinfo, &size, NULL((void *)0), 0) == -1) { |
337 | warn("could not read kern.clockrate"); |
338 | return; |
339 | } |
340 | hz = clkinfo.stathz; |
341 | |
342 | for (hdrcnt = 1;;) { |
343 | /* Read new disk statistics */ |
344 | dkreadstats(); |
345 | if (!--hdrcnt || last.dk_ndrive != cur.dk_ndrive) |
346 | printhdr(); |
347 | if (nlistf == NULL((void *)0) && memf == NULL((void *)0)) { |
348 | size = sizeof(struct uvmexp); |
349 | mib[0] = CTL_VM2; |
350 | mib[1] = VM_UVMEXP4; |
351 | if (sysctl(mib, 2, &uvmexp, &size, NULL((void *)0), 0) == -1) { |
352 | warn("could not get vm.uvmexp"); |
353 | memset(&uvmexp, 0, sizeof(struct uvmexp)); |
354 | } |
355 | } else { |
356 | kread(X_UVMEXP0, &uvmexp, sizeof(struct uvmexp)); |
357 | } |
358 | size = sizeof(total); |
359 | mib[0] = CTL_VM2; |
360 | mib[1] = VM_METER1; |
361 | if (sysctl(mib, 2, &total, &size, NULL((void *)0), 0) == -1) { |
362 | warn("could not read vm.vmmeter"); |
363 | memset(&total, 0, sizeof(total)); |
364 | } |
365 | (void)printf("%2u %3u", total.t_rq - 1, total.t_sl); |
366 | #define rate(x)((unsigned)((((unsigned)x) + halfuptime) / uptime)) ((unsigned)((((unsigned)x) + halfuptime) / uptime)) /* round */ |
367 | #define pgtok(a)((a) * ((unsigned int)uvmexp.pagesize >> 10)) ((a) * ((unsigned int)uvmexp.pagesize >> 10)) |
368 | (void)printf("%5uM %6uM ", |
369 | pgtok(uvmexp.active + uvmexp.swpginuse)((uvmexp.active + uvmexp.swpginuse) * ((unsigned int)uvmexp.pagesize >> 10)) / 1024, |
370 | pgtok(uvmexp.free)((uvmexp.free) * ((unsigned int)uvmexp.pagesize >> 10)) / 1024); |
371 | (void)printf("%4u ", rate(uvmexp.faults - ouvmexp.faults)((unsigned)((((unsigned)uvmexp.faults - ouvmexp.faults) + halfuptime ) / uptime))); |
372 | (void)printf("%3u ", rate(uvmexp.pdreact - ouvmexp.pdreact)((unsigned)((((unsigned)uvmexp.pdreact - ouvmexp.pdreact) + halfuptime ) / uptime))); |
373 | (void)printf("%3u ", rate(uvmexp.pageins - ouvmexp.pageins)((unsigned)((((unsigned)uvmexp.pageins - ouvmexp.pageins) + halfuptime ) / uptime))); |
374 | (void)printf("%3u %3u ", |
375 | rate(uvmexp.pdpageouts - ouvmexp.pdpageouts)((unsigned)((((unsigned)uvmexp.pdpageouts - ouvmexp.pdpageouts ) + halfuptime) / uptime)), 0); |
376 | (void)printf("%3u ", rate(uvmexp.pdscans - ouvmexp.pdscans)((unsigned)((((unsigned)uvmexp.pdscans - ouvmexp.pdscans) + halfuptime ) / uptime))); |
377 | dkstats(); |
378 | (void)printf("%4u %5u %4u ", |
379 | rate(uvmexp.intrs - ouvmexp.intrs)((unsigned)((((unsigned)uvmexp.intrs - ouvmexp.intrs) + halfuptime ) / uptime)), |
380 | rate(uvmexp.syscalls - ouvmexp.syscalls)((unsigned)((((unsigned)uvmexp.syscalls - ouvmexp.syscalls) + halfuptime) / uptime)), |
381 | rate(uvmexp.swtch - ouvmexp.swtch)((unsigned)((((unsigned)uvmexp.swtch - ouvmexp.swtch) + halfuptime ) / uptime))); |
382 | cpustats(); |
383 | (void)printf("\n"); |
384 | (void)fflush(stdout(&__sF[1])); |
385 | if (reps >= 0 && --reps <= 0) |
386 | break; |
387 | ouvmexp = uvmexp; |
388 | uptime = interval; |
389 | /* |
390 | * We round upward to avoid losing low-frequency events |
391 | * (i.e., >= 1 per interval but < 1 per second). |
392 | */ |
393 | halfuptime = uptime == 1 ? 0 : (uptime + 1) / 2; |
394 | (void)sleep(interval); |
395 | } |
396 | } |
397 | |
398 | void |
399 | printhdr(void) |
400 | { |
401 | int i; |
402 | static int printedhdr; |
403 | |
404 | if (printedhdr && !isatty(STDOUT_FILENO1)) |
405 | return; |
406 | |
407 | (void)printf(" procs memory page%*s", 20, ""); |
408 | if (ndrives > 0) |
409 | (void)printf("%s %*straps cpu\n", |
410 | ((ndrives > 1) ? "disks" : "disk"), |
411 | ((ndrives > 1) ? ndrives * 4 - 5 : 0), ""); |
412 | else |
413 | (void)printf("%*s traps cpu\n", |
414 | ndrives * 3, ""); |
415 | |
416 | (void)printf(" r s avm fre flt re pi po fr sr "); |
417 | for (i = 0; i < dk_ndrive; i++) |
418 | if (dk_select[i]) |
419 | (void)printf("%c%c%c ", dr_name[i][0], |
420 | dr_name[i][1], |
421 | dr_name[i][strlen(dr_name[i]) - 1]); |
422 | (void)printf(" int sys cs us sy id\n"); |
423 | hdrcnt = winlines - 2; |
424 | printedhdr = 1; |
425 | } |
426 | |
427 | /* |
428 | * Force a header to be prepended to the next output. |
429 | */ |
430 | void |
431 | needhdr(__unused__attribute__((__unused__)) int signo) |
432 | { |
433 | |
434 | hdrcnt = 1; |
435 | } |
436 | |
437 | void |
438 | dotimes(void) |
439 | { |
440 | u_int pgintime, rectime; |
441 | size_t size; |
442 | int mib[2]; |
443 | |
444 | /* XXX Why are these set to 0 ? This doesn't look right. */ |
445 | pgintime = 0; |
446 | rectime = 0; |
447 | |
448 | if (nlistf == NULL((void *)0) && memf == NULL((void *)0)) { |
449 | size = sizeof(struct uvmexp); |
450 | mib[0] = CTL_VM2; |
451 | mib[1] = VM_UVMEXP4; |
452 | if (sysctl(mib, 2, &uvmexp, &size, NULL((void *)0), 0) == -1) { |
453 | warn("could not read vm.uvmexp"); |
454 | memset(&uvmexp, 0, sizeof(struct uvmexp)); |
455 | } |
456 | } else { |
457 | kread(X_UVMEXP0, &uvmexp, sizeof(struct uvmexp)); |
458 | } |
459 | |
460 | (void)printf("%u reactivates, %u total time (usec)\n", |
461 | uvmexp.pdreact, rectime); |
462 | if (uvmexp.pdreact != 0) |
463 | (void)printf("average: %u usec / reclaim\n", |
464 | rectime / uvmexp.pdreact); |
465 | (void)printf("\n"); |
466 | (void)printf("%u page ins, %u total time (msec)\n", |
467 | uvmexp.pageins, pgintime / 10); |
468 | if (uvmexp.pageins != 0) |
469 | (void)printf("average: %8.1f msec / page in\n", |
470 | pgintime / (uvmexp.pageins * 10.0)); |
471 | } |
472 | |
473 | int |
474 | pct(int64_t top, int64_t bot) |
475 | { |
476 | int ans; |
477 | |
478 | if (bot == 0) |
479 | return(0); |
480 | ans = top * 100 / bot; |
481 | return (ans); |
482 | } |
483 | |
484 | void |
485 | dosum(void) |
486 | { |
487 | struct nchstats nchstats; |
488 | int mib[2], nselcoll; |
489 | long long nchtotal; |
490 | size_t size; |
491 | |
492 | if (nlistf == NULL((void *)0) && memf == NULL((void *)0)) { |
493 | size = sizeof(struct uvmexp); |
494 | mib[0] = CTL_VM2; |
495 | mib[1] = VM_UVMEXP4; |
496 | if (sysctl(mib, 2, &uvmexp, &size, NULL((void *)0), 0) == -1) { |
497 | warn("could not read vm.uvmexp"); |
498 | memset(&uvmexp, 0, sizeof(struct uvmexp)); |
499 | } |
500 | } else { |
501 | kread(X_UVMEXP0, &uvmexp, sizeof(struct uvmexp)); |
502 | } |
503 | |
504 | /* vm_page constants */ |
505 | (void)printf("%11u bytes per page\n", uvmexp.pagesize); |
506 | |
507 | /* vm_page counters */ |
508 | (void)printf("%11u pages managed\n", uvmexp.npages); |
509 | (void)printf("%11u pages free\n", uvmexp.free); |
510 | (void)printf("%11u pages active\n", uvmexp.active); |
511 | (void)printf("%11u pages inactive\n", uvmexp.inactive); |
512 | (void)printf("%11u pages being paged out\n", uvmexp.paging); |
513 | (void)printf("%11u pages wired\n", uvmexp.wired); |
514 | (void)printf("%11u pages zeroed\n", uvmexp.zeropages); |
515 | (void)printf("%11u pages reserved for pagedaemon\n", |
516 | uvmexp.reserve_pagedaemon); |
517 | (void)printf("%11u pages reserved for kernel\n", |
518 | uvmexp.reserve_kernel); |
519 | |
520 | /* swap */ |
521 | (void)printf("%11u swap pages\n", uvmexp.swpages); |
522 | (void)printf("%11u swap pages in use\n", uvmexp.swpginuse); |
523 | |
524 | /* stat counters */ |
525 | (void)printf("%11u page faults\n", uvmexp.faults); |
526 | (void)printf("%11u traps\n", uvmexp.traps); |
527 | (void)printf("%11u interrupts\n", uvmexp.intrs); |
528 | (void)printf("%11u cpu context switches\n", uvmexp.swtch); |
529 | (void)printf("%11u fpu context switches\n", uvmexp.fpswtch); |
530 | (void)printf("%11u software interrupts\n", uvmexp.softs); |
531 | (void)printf("%11u syscalls\n", uvmexp.syscalls); |
532 | (void)printf("%11u pagein operations\n", uvmexp.pageins); |
533 | (void)printf("%11u forks\n", uvmexp.forks); |
534 | (void)printf("%11u forks where vmspace is shared\n", |
535 | uvmexp.forks_sharevm); |
536 | (void)printf("%11u kernel map entries\n", uvmexp.kmapent); |
537 | (void)printf("%11u zeroed page hits\n", uvmexp.pga_zerohit); |
538 | (void)printf("%11u zeroed page misses\n", uvmexp.pga_zeromiss); |
539 | |
540 | /* daemon counters */ |
541 | (void)printf("%11u number of times the pagedaemon woke up\n", |
542 | uvmexp.pdwoke); |
543 | (void)printf("%11u revolutions of the clock hand\n", uvmexp.pdrevs); |
544 | (void)printf("%11u pages freed by pagedaemon\n", uvmexp.pdfreed); |
545 | (void)printf("%11u pages scanned by pagedaemon\n", uvmexp.pdscans); |
546 | (void)printf("%11u pages reactivated by pagedaemon\n", uvmexp.pdreact); |
547 | (void)printf("%11u busy pages found by pagedaemon\n", uvmexp.pdbusy); |
548 | |
549 | if (nlistf == NULL((void *)0) && memf == NULL((void *)0)) { |
550 | size = sizeof(nchstats); |
551 | mib[0] = CTL_KERN1; |
552 | mib[1] = KERN_NCHSTATS41; |
553 | if (sysctl(mib, 2, &nchstats, &size, NULL((void *)0), 0) == -1) { |
554 | warn("could not read kern.nchstats"); |
555 | memset(&nchstats, 0, sizeof(nchstats)); |
556 | } |
557 | } else { |
558 | kread(X_NCHSTATS2, &nchstats, sizeof(nchstats)); |
559 | } |
560 | |
561 | nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits + |
562 | nchstats.ncs_badhits + nchstats.ncs_falsehits + |
563 | nchstats.ncs_miss + nchstats.ncs_long; |
564 | (void)printf("%11lld total name lookups\n", nchtotal); |
565 | (void)printf("%11s cache hits (%d%% pos + %d%% neg) system %d%% " |
566 | "per-directory\n", |
567 | "", pct(nchstats.ncs_goodhits, nchtotal), |
568 | pct(nchstats.ncs_neghits, nchtotal), |
569 | pct(nchstats.ncs_pass2, nchtotal)); |
570 | (void)printf("%11s deletions %d%%, falsehits %d%%, toolong %d%%\n", "", |
571 | pct(nchstats.ncs_badhits, nchtotal), |
572 | pct(nchstats.ncs_falsehits, nchtotal), |
573 | pct(nchstats.ncs_long, nchtotal)); |
574 | |
575 | if (nlistf == NULL((void *)0) && memf == NULL((void *)0)) { |
576 | size = sizeof(nselcoll); |
577 | mib[0] = CTL_KERN1; |
578 | mib[1] = KERN_NSELCOLL43; |
579 | if (sysctl(mib, 2, &nselcoll, &size, NULL((void *)0), 0) == -1) { |
580 | warn("could not read kern.nselcoll"); |
581 | nselcoll = 0; |
582 | } |
583 | } else { |
584 | kread(X_NSELCOLL6, &nselcoll, sizeof(nselcoll)); |
585 | } |
586 | (void)printf("%11d select collisions\n", nselcoll); |
587 | } |
588 | |
589 | void |
590 | doforkst(void) |
591 | { |
592 | struct forkstat fks; |
593 | size_t size; |
594 | int mib[2]; |
595 | |
596 | if (nlistf == NULL((void *)0) && memf == NULL((void *)0)) { |
597 | size = sizeof(struct forkstat); |
598 | mib[0] = CTL_KERN1; |
599 | mib[1] = KERN_FORKSTAT42; |
600 | if (sysctl(mib, 2, &fks, &size, NULL((void *)0), 0) == -1) { |
601 | warn("could not read kern.forkstat"); |
602 | memset(&fks, 0, sizeof(struct forkstat)); |
603 | } |
604 | } else { |
605 | kread(X_FORKSTAT5, &fks, sizeof(struct forkstat)); |
606 | } |
607 | |
608 | (void)printf("%u forks, %llu pages, average %.2f\n", |
609 | fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork); |
610 | (void)printf("%u vforks, %llu pages, average %.2f\n", |
611 | fks.cntvfork, fks.sizvfork, |
612 | (double)fks.sizvfork / (fks.cntvfork ? fks.cntvfork : 1)); |
613 | (void)printf("%u __tforks, %llu pages, average %.2f\n", |
614 | fks.cnttfork, fks.siztfork, |
615 | (double)fks.siztfork / (fks.cnttfork ? fks.cnttfork : 1)); |
616 | (void)printf("%u kthread creations, %llu pages, average %.2f\n", |
617 | fks.cntkthread, fks.sizkthread, |
618 | (double)fks.sizkthread / (fks.cntkthread ? fks.cntkthread : 1)); |
619 | } |
620 | |
621 | void |
622 | dkstats(void) |
623 | { |
624 | int dn, state; |
625 | double etime; |
626 | |
627 | /* Calculate disk stat deltas. */ |
628 | dkswap(); |
629 | etime = 0; |
630 | for (state = 0; state < CPUSTATES6; ++state) { |
631 | etime += cur.cp_time[state]; |
632 | } |
633 | if (etime == 0) |
634 | etime = 1; |
635 | etime /= hz; |
636 | for (dn = 0; dn < dk_ndrive; ++dn) { |
637 | if (!dk_select[dn]) |
638 | continue; |
639 | (void)printf("%3.0f ", |
640 | (cur.dk_rxfer[dn] + cur.dk_rxfer[dn]) / etime); |
641 | } |
642 | } |
643 | |
644 | void |
645 | cpustats(void) |
646 | { |
647 | double percent, total; |
648 | int state; |
649 | |
650 | total = 0; |
651 | for (state = 0; state < CPUSTATES6; ++state) |
652 | total += cur.cp_time[state]; |
653 | if (total) |
654 | percent = 100 / total; |
655 | else |
656 | percent = 0; |
657 | (void)printf("%2.0f ", (cur.cp_time[CP_USER0] + cur.cp_time[CP_NICE1]) * percent); |
658 | (void)printf("%2.0f ", (cur.cp_time[CP_SYS2] + cur.cp_time[CP_SPIN3] + cur.cp_time[CP_INTR4]) * percent); |
659 | (void)printf("%2.0f", cur.cp_time[CP_IDLE5] * percent); |
660 | } |
661 | |
662 | void |
663 | dointr(void) |
664 | { |
665 | int nintr, mib[4], i; |
666 | char intrname[128]; |
667 | u_int64_t inttotal; |
668 | time_t uptime; |
669 | size_t siz; |
670 | |
671 | if (nlistf != NULL((void *)0) || memf != NULL((void *)0)) { |
672 | errx(1, |
673 | "interrupt statistics are only available on live kernels"); |
674 | } |
675 | |
676 | uptime = getuptime(); |
677 | |
678 | mib[0] = CTL_KERN1; |
679 | mib[1] = KERN_INTRCNT63; |
680 | mib[2] = KERN_INTRCNT_NUM1; |
681 | siz = sizeof(nintr); |
682 | if (sysctl(mib, 3, &nintr, &siz, NULL((void *)0), 0) == -1) { |
683 | warnx("could not read kern.intrcnt.nintrcnt"); |
684 | return; |
685 | } |
686 | |
687 | (void)printf("%-16s %20s %8s\n", "interrupt", "total", "rate"); |
688 | |
689 | inttotal = 0; |
690 | for (i = 0; i < nintr; i++) { |
691 | char name[128]; |
692 | uint64_t cnt; |
693 | int vector; |
694 | |
695 | mib[0] = CTL_KERN1; |
696 | mib[1] = KERN_INTRCNT63; |
697 | mib[2] = KERN_INTRCNT_NAME3; |
698 | mib[3] = i; |
699 | siz = sizeof(name); |
700 | if (sysctl(mib, 4, name, &siz, NULL((void *)0), 0) == -1) { |
701 | warnx("could not read kern.intrcnt.name.%d", i); |
702 | return; |
703 | } |
704 | |
705 | mib[0] = CTL_KERN1; |
706 | mib[1] = KERN_INTRCNT63; |
707 | mib[2] = KERN_INTRCNT_VECTOR4; |
708 | mib[3] = i; |
709 | siz = sizeof(vector); |
710 | if (sysctl(mib, 4, &vector, &siz, NULL((void *)0), 0) == -1) { |
711 | strlcpy(intrname, name, sizeof(intrname)); |
712 | } else { |
713 | snprintf(intrname, sizeof(intrname), "irq%d/%s", |
714 | vector, name); |
715 | } |
716 | |
717 | mib[0] = CTL_KERN1; |
718 | mib[1] = KERN_INTRCNT63; |
719 | mib[2] = KERN_INTRCNT_CNT2; |
720 | mib[3] = i; |
721 | siz = sizeof(cnt); |
722 | if (sysctl(mib, 4, &cnt, &siz, NULL((void *)0), 0) == -1) { |
723 | warnx("could not read kern.intrcnt.cnt.%d", i); |
724 | return; |
725 | } |
726 | |
727 | if (cnt || zflag) |
728 | (void)printf("%-16.16s %20llu %8llu\n", intrname, |
729 | cnt, cnt / uptime); |
730 | inttotal += cnt; |
731 | } |
732 | |
733 | (void)printf("%-16s %20llu %8llu\n", "Total", inttotal, |
734 | inttotal / uptime); |
735 | } |
736 | |
737 | /* |
738 | * These names are defined in <sys/malloc.h>. |
739 | */ |
740 | const char *kmemnames[] = INITKMEMNAMES{ "free", ((void *)0), "devbuf", ((void *)0), "pcb", "rtable" , ((void *)0), ((void *)0), ((void *)0), "ifaddr", "soopts", "sysctl" , "counters", ((void *)0), "ioctlops", ((void *)0), ((void *) 0), ((void *)0), ((void *)0), "iov", "mount", ((void *)0), "NFS req" , "NFS mount", "log", "vnodes", "namecache", "UFS quota", "UFS mount" , "shm", "VM map", "sem", "dirhash", "ACPI", "VM pmap", ((void *)0), ((void *)0), ((void *)0), "file", "file desc", "sigio" , "proc", "subproc", "VFS cluster", ((void *)0), ((void *)0), "MFS node", ((void *)0), ((void *)0), "Export Host", "NFS srvsock" , ((void *)0), "NFS daemon", "ip_moptions", "in_multi", "ether_multi" , "mrt", "ISOFS mount", "ISOFS node", "MSDOSFS mount", "MSDOSFS fat" , "MSDOSFS node", "ttys", "exec", "miscfs mount", "fusefs mount" , ((void *)0), ((void *)0), ((void *)0), ((void *)0), ((void * )0), ((void *)0), ((void *)0), ((void *)0), "pfkey data", "tdb" , "xform_data", ((void *)0), "pagedep", "inodedep", "newblk", ((void *)0), ((void *)0), "indirdep", ((void *)0), ((void *) 0), ((void *)0), ((void *)0), ((void *)0), ((void *)0), ((void *)0), ((void *)0), "VM swap", ((void *)0), ((void *)0), ((void *)0), ((void *)0), ((void *)0), "UVM amap", "UVM aobj", ((void *)0), "USB", "USB device", "USB HC", "witness", "memdesc", ( (void *)0), ((void *)0), "crypto data", ((void *)0), "IPsec creds" , ((void *)0), ((void *)0), ((void *)0), "emuldata", ((void * )0), ((void *)0), ((void *)0), ((void *)0), ((void *)0), ((void *)0), ((void *)0), ((void *)0), "ip6_options", "NDP", ((void *)0), ((void *)0), "temp", "NTFS mount", "NTFS node", "NTFS fnode" , "NTFS dir", "NTFS hash", "NTFS attr", "NTFS data", "NTFS decomp" , "NTFS vrun", "kqueue", ((void *)0), "SYN cache", "UDF mount" , "UDF file entry", "UDF file id", ((void *)0), "AGP Memory", "DRM", }; |
741 | |
742 | void |
743 | domem(void) |
744 | { |
745 | struct kmembuckets buckets[MINBUCKET4 + 16], *kp; |
746 | struct kmemstats kmemstats[M_LAST146], *ks; |
747 | int i, j, len, size, first, mib[4]; |
748 | u_long totuse = 0, totfree = 0; |
749 | char buf[BUFSIZ1024], *bufp, *ap; |
750 | unsigned long long totreq = 0; |
751 | const char *name; |
752 | size_t siz; |
753 | |
754 | if (memf == NULL((void *)0) && nlistf == NULL((void *)0)) { |
755 | mib[0] = CTL_KERN1; |
756 | mib[1] = KERN_MALLOCSTATS39; |
757 | mib[2] = KERN_MALLOC_BUCKETS1; |
758 | siz = sizeof(buf); |
759 | if (sysctl(mib, 3, buf, &siz, NULL((void *)0), 0) == -1) { |
760 | warnx("could not read kern.malloc.buckets"); |
761 | return; |
762 | } |
763 | |
764 | bufp = buf; |
765 | mib[2] = KERN_MALLOC_BUCKET2; |
766 | siz = sizeof(struct kmembuckets); |
767 | i = 0; |
768 | while ((ap = strsep(&bufp, ",")) != NULL((void *)0)) { |
769 | const char *errstr; |
770 | |
771 | mib[3] = strtonum(ap, 0, INT_MAX2147483647, &errstr); |
772 | if (errstr) { |
773 | warnx("kernel lied about %d being a number", mib[3]); |
774 | return; |
775 | } |
776 | |
777 | if (sysctl(mib, 4, &buckets[MINBUCKET4 + i], &siz, |
778 | NULL((void *)0), 0) == -1) { |
779 | warn("could not read kern.malloc.bucket.%d", mib[3]); |
780 | return; |
781 | } |
782 | i++; |
783 | } |
784 | } else { |
785 | kread(X_KMEMBUCKETS4, buckets, sizeof(buckets)); |
786 | } |
787 | |
788 | for (first = 1, i = MINBUCKET4, kp = &buckets[i]; i < MINBUCKET4 + 16; |
789 | i++, kp++) { |
790 | if (kp->kb_calls == 0 && !verbose) |
791 | continue; |
792 | if (first) { |
793 | (void)printf("Memory statistics by bucket size\n"); |
794 | (void)printf( |
795 | " Size In Use Free Requests HighWater Couldfree\n"); |
796 | first = 0; |
797 | } |
798 | size = 1 << i; |
799 | (void)printf("%8d %8llu %6llu %18llu %7llu %10llu\n", size, |
800 | (unsigned long long)(kp->kb_total - kp->kb_totalfree), |
801 | (unsigned long long)kp->kb_totalfree, |
802 | (unsigned long long)kp->kb_calls, |
803 | (unsigned long long)kp->kb_highwat, |
804 | (unsigned long long)kp->kb_couldfree); |
805 | totfree += size * kp->kb_totalfree; |
806 | } |
807 | |
808 | /* |
809 | * If kmem statistics are not being gathered by the kernel, |
810 | * first will still be 1. |
811 | */ |
812 | if (first) { |
813 | printf( |
814 | "Kmem statistics are not being gathered by the kernel.\n"); |
815 | return; |
816 | } |
817 | |
818 | if (memf == NULL((void *)0) && nlistf == NULL((void *)0)) { |
819 | memset(kmemstats, 0, sizeof(kmemstats)); |
820 | for (i = 0; i < M_LAST146; i++) { |
821 | mib[0] = CTL_KERN1; |
822 | mib[1] = KERN_MALLOCSTATS39; |
823 | mib[2] = KERN_MALLOC_KMEMSTATS4; |
824 | mib[3] = i; |
825 | siz = sizeof(struct kmemstats); |
826 | |
827 | /* |
828 | * Skip errors -- these are presumed to be unallocated |
829 | * entries. |
830 | */ |
831 | if (sysctl(mib, 4, &kmemstats[i], &siz, NULL((void *)0), 0) == -1) |
832 | continue; |
833 | } |
834 | } else { |
835 | kread(X_KMEMSTAT3, kmemstats, sizeof(kmemstats)); |
836 | } |
837 | |
838 | (void)printf("\nMemory usage type by bucket size\n"); |
839 | (void)printf(" Size Type(s)\n"); |
840 | kp = &buckets[MINBUCKET4]; |
841 | for (j = 1 << MINBUCKET4; j < 1 << (MINBUCKET4 + 16); j <<= 1, kp++) { |
842 | if (kp->kb_calls == 0) |
843 | continue; |
844 | first = 1; |
845 | len = 8; |
846 | for (i = 0, ks = &kmemstats[0]; i < M_LAST146; i++, ks++) { |
847 | if (ks->ks_calls == 0) |
848 | continue; |
849 | if ((ks->ks_size & j) == 0) |
850 | continue; |
851 | name = kmemnames[i] ? kmemnames[i] : "undefined"; |
852 | len += 2 + strlen(name); |
853 | if (first) |
854 | printf("%8d %s", j, name); |
855 | else |
856 | printf(","); |
857 | if (len >= 80) { |
858 | printf("\n\t "); |
859 | len = 10 + strlen(name); |
860 | } |
861 | if (!first) |
862 | printf(" %s", name); |
863 | first = 0; |
864 | } |
865 | printf("\n"); |
866 | } |
867 | |
868 | (void)printf( |
869 | "\nMemory statistics by type Type Kern\n"); |
870 | (void)printf( |
871 | " Type InUse MemUse HighUse Limit Requests Limit Size(s)\n"); |
872 | for (i = 0, ks = &kmemstats[0]; i < M_LAST146; i++, ks++) { |
873 | if (ks->ks_calls == 0) |
874 | continue; |
875 | (void)printf("%14s%6ld%6ldK%7ldK%6ldK%9ld%5u", |
876 | kmemnames[i] ? kmemnames[i] : "undefined", |
877 | ks->ks_inuse, (ks->ks_memuse + 1023) / 1024, |
878 | (ks->ks_maxused + 1023) / 1024, |
879 | (ks->ks_limit + 1023) / 1024, ks->ks_calls, |
880 | ks->ks_limblocks); |
881 | first = 1; |
882 | for (j = 1 << MINBUCKET4; j < 1 << (MINBUCKET4 + 16); j <<= 1) { |
883 | if ((ks->ks_size & j) == 0) |
884 | continue; |
885 | if (first) |
886 | printf(" %d", j); |
887 | else |
888 | printf(",%d", j); |
889 | first = 0; |
890 | } |
891 | printf("\n"); |
892 | totuse += ks->ks_memuse; |
893 | totreq += ks->ks_calls; |
894 | } |
895 | (void)printf("\nMemory Totals: In Use Free Requests\n"); |
896 | (void)printf(" %7luK %6luK %8llu\n", |
897 | (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq); |
898 | } |
899 | |
900 | static void |
901 | print_pool(struct kinfo_pool *pp, char *name) |
902 | { |
903 | static int first = 1; |
904 | char maxp[32]; |
905 | int ovflw; |
906 | |
907 | if (first) { |
908 | (void)printf("Memory resource pool statistics\n"); |
909 | (void)printf( |
910 | "%-11s%5s%9s%5s%9s%6s%6s%6s%6s%6s%6s%5s\n", |
911 | "Name", |
912 | "Size", |
913 | "Requests", |
914 | "Fail", |
915 | "InUse", |
916 | "Pgreq", |
917 | "Pgrel", |
918 | "Npage", |
919 | "Hiwat", |
920 | "Minpg", |
921 | "Maxpg", |
922 | "Idle"); |
923 | first = 0; |
924 | } |
925 | |
926 | /* Skip unused pools unless verbose output. */ |
927 | if (pp->pr_nget == 0 && !verbose) |
928 | return; |
929 | |
930 | if (pp->pr_maxpages == UINT_MAX(2147483647 *2U +1U)) |
931 | snprintf(maxp, sizeof maxp, "inf"); |
932 | else |
933 | snprintf(maxp, sizeof maxp, "%u", pp->pr_maxpages); |
934 | /* |
935 | * Print single word. `ovflow' is number of characters didn't fit |
936 | * on the last word. `fmt' is a format string to print this word. |
937 | * It must contain asterisk for field width. `width' is a width |
938 | * occupied by this word. `fixed' is a number of constant chars in |
939 | * `fmt'. `val' is a value to be printed using format string `fmt'. |
940 | */ |
941 | #define PRWORD(ovflw, fmt, width, fixed, val)do { (ovflw) += printf((fmt), (width) - (fixed) - (ovflw) > 0 ? (width) - (fixed) - (ovflw) : 0, (val)) - (width); if (( ovflw) < 0) (ovflw) = 0; } while ( 0) do { \ |
942 | (ovflw) += printf((fmt), \ |
943 | (width) - (fixed) - (ovflw) > 0 ? \ |
944 | (width) - (fixed) - (ovflw) : 0, \ |
945 | (val)) - (width); \ |
946 | if ((ovflw) < 0) \ |
947 | (ovflw) = 0; \ |
948 | } while (/* CONSTCOND */0) |
949 | |
950 | ovflw = 0; |
951 | PRWORD(ovflw, "%-*s", 11, 0, name)do { (ovflw) += printf(("%-*s"), (11) - (0) - (ovflw) > 0 ? (11) - (0) - (ovflw) : 0, (name)) - (11); if ((ovflw) < 0 ) (ovflw) = 0; } while ( 0); |
952 | PRWORD(ovflw, " %*u", 5, 1, pp->pr_size)do { (ovflw) += printf((" %*u"), (5) - (1) - (ovflw) > 0 ? (5) - (1) - (ovflw) : 0, (pp->pr_size)) - (5); if ((ovflw ) < 0) (ovflw) = 0; } while ( 0); |
953 | PRWORD(ovflw, " %*lu", 9, 1, pp->pr_nget)do { (ovflw) += printf((" %*lu"), (9) - (1) - (ovflw) > 0 ? (9) - (1) - (ovflw) : 0, (pp->pr_nget)) - (9); if ((ovflw ) < 0) (ovflw) = 0; } while ( 0); |
954 | PRWORD(ovflw, " %*lu", 5, 1, pp->pr_nfail)do { (ovflw) += printf((" %*lu"), (5) - (1) - (ovflw) > 0 ? (5) - (1) - (ovflw) : 0, (pp->pr_nfail)) - (5); if ((ovflw ) < 0) (ovflw) = 0; } while ( 0); |
955 | PRWORD(ovflw, " %*lu", 9, 1, pp->pr_nget - pp->pr_nput)do { (ovflw) += printf((" %*lu"), (9) - (1) - (ovflw) > 0 ? (9) - (1) - (ovflw) : 0, (pp->pr_nget - pp->pr_nput)) - (9); if ((ovflw) < 0) (ovflw) = 0; } while ( 0); |
956 | PRWORD(ovflw, " %*lu", 6, 1, pp->pr_npagealloc)do { (ovflw) += printf((" %*lu"), (6) - (1) - (ovflw) > 0 ? (6) - (1) - (ovflw) : 0, (pp->pr_npagealloc)) - (6); if ( (ovflw) < 0) (ovflw) = 0; } while ( 0); |
957 | PRWORD(ovflw, " %*lu", 6, 1, pp->pr_npagefree)do { (ovflw) += printf((" %*lu"), (6) - (1) - (ovflw) > 0 ? (6) - (1) - (ovflw) : 0, (pp->pr_npagefree)) - (6); if (( ovflw) < 0) (ovflw) = 0; } while ( 0); |
958 | PRWORD(ovflw, " %*d", 6, 1, pp->pr_npages)do { (ovflw) += printf((" %*d"), (6) - (1) - (ovflw) > 0 ? (6) - (1) - (ovflw) : 0, (pp->pr_npages)) - (6); if ((ovflw ) < 0) (ovflw) = 0; } while ( 0); |
959 | PRWORD(ovflw, " %*d", 6, 1, pp->pr_hiwat)do { (ovflw) += printf((" %*d"), (6) - (1) - (ovflw) > 0 ? (6) - (1) - (ovflw) : 0, (pp->pr_hiwat)) - (6); if ((ovflw ) < 0) (ovflw) = 0; } while ( 0); |
960 | PRWORD(ovflw, " %*d", 6, 1, pp->pr_minpages)do { (ovflw) += printf((" %*d"), (6) - (1) - (ovflw) > 0 ? (6) - (1) - (ovflw) : 0, (pp->pr_minpages)) - (6); if ((ovflw ) < 0) (ovflw) = 0; } while ( 0); |
961 | PRWORD(ovflw, " %*s", 6, 1, maxp)do { (ovflw) += printf((" %*s"), (6) - (1) - (ovflw) > 0 ? (6) - (1) - (ovflw) : 0, (maxp)) - (6); if ((ovflw) < 0) ( ovflw) = 0; } while ( 0); |
962 | PRWORD(ovflw, " %*lu\n", 5, 1, pp->pr_nidle)do { (ovflw) += printf((" %*lu\n"), (5) - (1) - (ovflw) > 0 ? (5) - (1) - (ovflw) : 0, (pp->pr_nidle)) - (5); if ((ovflw ) < 0) (ovflw) = 0; } while ( 0); |
963 | } |
964 | |
965 | static void dopool_kvm(void); |
966 | static void dopool_sysctl(void); |
967 | |
968 | void |
969 | dopool(void) |
970 | { |
971 | if (nlistf == NULL((void *)0) && memf == NULL((void *)0)) |
972 | dopool_sysctl(); |
973 | else |
974 | dopool_kvm(); |
975 | } |
976 | |
977 | void |
978 | dopool_sysctl(void) |
979 | { |
980 | int mib[4], npools, i; |
981 | long total = 0, inuse = 0; |
982 | struct kinfo_pool pool; |
983 | size_t size; |
984 | |
985 | mib[0] = CTL_KERN1; |
986 | mib[1] = KERN_POOL49; |
987 | mib[2] = KERN_POOL_NPOOLS1; |
988 | size = sizeof(npools); |
989 | if (sysctl(mib, 3, &npools, &size, NULL((void *)0), 0) == -1) { |
990 | warn("can't figure out number of pools in kernel"); |
991 | return; |
992 | } |
993 | |
994 | for (i = 1; npools; i++) { |
995 | char name[32]; |
996 | |
997 | mib[0] = CTL_KERN1; |
998 | mib[1] = KERN_POOL49; |
999 | mib[2] = KERN_POOL_POOL3; |
1000 | mib[3] = i; |
1001 | size = sizeof(pool); |
1002 | if (sysctl(mib, 4, &pool, &size, NULL((void *)0), 0) == -1) { |
1003 | if (errno(*__errno()) == ENOENT2) |
1004 | continue; |
1005 | warn("error getting pool"); |
1006 | return; |
1007 | } |
1008 | npools--; |
1009 | mib[2] = KERN_POOL_NAME2; |
1010 | size = sizeof(name); |
1011 | if (sysctl(mib, 4, &name, &size, NULL((void *)0), 0) == -1) { |
1012 | warn("error getting pool name"); |
1013 | return; |
1014 | } |
1015 | print_pool(&pool, name); |
1016 | |
1017 | inuse += (pool.pr_nget - pool.pr_nput) * pool.pr_size; |
1018 | total += pool.pr_npages * pool.pr_pgsize; |
1019 | } |
1020 | |
1021 | inuse /= 1024; |
1022 | total /= 1024; |
1023 | printf("\nIn use %ldK, total allocated %ldK; utilization %.1f%%\n", |
1024 | inuse, total, (double)(100 * inuse) / total); |
1025 | } |
1026 | |
1027 | void |
1028 | dopool_kvm(void) |
1029 | { |
1030 | SIMPLEQ_HEAD(,pool)struct { struct pool *sqh_first; struct pool **sqh_last; } pool_head; |
1031 | struct pool pool, *pp = &pool; |
1032 | struct kinfo_pool pi; |
1033 | long total = 0, inuse = 0; |
1034 | u_long addr; |
1035 | |
1036 | kread(X_POOLHEAD7, &pool_head, sizeof(pool_head)); |
1037 | addr = (u_long)SIMPLEQ_FIRST(&pool_head)((&pool_head)->sqh_first); |
1038 | |
1039 | while (addr != 0) { |
1040 | char name[32]; |
1041 | |
1042 | if (kvm_read(kd, addr, (void *)pp, sizeof *pp) != sizeof *pp) { |
1043 | (void)fprintf(stderr(&__sF[2]), |
1044 | "vmstat: pool chain trashed: %s\n", |
1045 | kvm_geterr(kd)); |
1046 | exit(1); |
1047 | } |
1048 | if (kvm_read(kd, (u_long)pp->pr_wchan, name, sizeof name) < 0) { |
1049 | (void)fprintf(stderr(&__sF[2]), |
1050 | "vmstat: pool name trashed: %s\n", |
1051 | kvm_geterr(kd)); |
1052 | exit(1); |
1053 | } |
1054 | name[31] = '\0'; |
1055 | |
1056 | memset(&pi, 0, sizeof(pi)); |
1057 | pi.pr_size = pp->pr_size; |
1058 | pi.pr_pgsize = pp->pr_pgsize; |
1059 | pi.pr_itemsperpage = pp->pr_itemsperpage; |
1060 | pi.pr_npages = pp->pr_npages; |
1061 | pi.pr_minpages = pp->pr_minpages; |
1062 | pi.pr_maxpages = pp->pr_maxpages; |
1063 | pi.pr_hardlimit = pp->pr_hardlimit; |
1064 | pi.pr_nout = pp->pr_nout; |
1065 | pi.pr_nitems = pp->pr_nitems; |
1066 | pi.pr_nget = pp->pr_nget; |
1067 | pi.pr_nput = pp->pr_nput; |
1068 | pi.pr_nfail = pp->pr_nfail; |
1069 | pi.pr_npagealloc = pp->pr_npagealloc; |
1070 | pi.pr_npagefree = pp->pr_npagefree; |
1071 | pi.pr_hiwat = pp->pr_hiwat; |
1072 | pi.pr_nidle = pp->pr_nidle; |
1073 | |
1074 | print_pool(&pi, name); |
1075 | |
1076 | inuse += (pi.pr_nget - pi.pr_nput) * pi.pr_size; |
1077 | total += pi.pr_npages * pi.pr_pgsize; |
1078 | |
1079 | addr = (u_long)SIMPLEQ_NEXT(pp, pr_poollist)((pp)->pr_poollist.sqe_next); |
1080 | } |
1081 | |
1082 | inuse /= 1024; |
1083 | total /= 1024; |
1084 | printf("\nIn use %ldK, total allocated %ldK; utilization %.1f%%\n", |
1085 | inuse, total, (double)(100 * inuse) / total); |
1086 | } |
1087 | |
1088 | /* |
1089 | * kread reads something from the kernel, given its nlist index. |
1090 | */ |
1091 | void |
1092 | kread(int nlx, void *addr, size_t size) |
1093 | { |
1094 | char *sym; |
1095 | |
1096 | if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) { |
1097 | sym = namelist[nlx].n_name; |
1098 | if (*sym == '_') |
1099 | ++sym; |
1100 | errx(1, "symbol %s not defined", sym); |
1101 | } |
1102 | if (kvm_read(kd, namelist[nlx].n_value, addr, size) != size) { |
1103 | sym = namelist[nlx].n_name; |
1104 | if (*sym == '_') |
1105 | ++sym; |
1106 | errx(1, "%s: %s", sym, kvm_geterr(kd)); |
1107 | } |
1108 | } |
1109 | |
1110 | void |
1111 | usage(void) |
1112 | { |
1113 | (void)fprintf(stderr(&__sF[2]), "usage: %s [-fimstvz] [-c count] [-M core] " |
1114 | "[-N system] [-w wait] [disk ...]\n", __progname); |
1115 | exit(1); |
1116 | } |