| 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 | } |