1 /* 2 * Copyright (c) 1997, 1998 Kenneth D. Merry. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 /* 31 * Parts of this program are derived from the original FreeBSD iostat 32 * program: 33 */ 34 /*- 35 * Copyright (c) 1986, 1991, 1993 36 * The Regents of the University of California. All rights reserved. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 3. All advertising materials mentioning features or use of this software 47 * must display the following acknowledgement: 48 * This product includes software developed by the University of 49 * California, Berkeley and its contributors. 50 * 4. Neither the name of the University nor the names of its contributors 51 * may be used to endorse or promote products derived from this software 52 * without specific prior written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 64 * SUCH DAMAGE. 65 */ 66 /* 67 * Ideas for the new iostat statistics output modes taken from the NetBSD 68 * version of iostat: 69 */ 70 /* 71 * Copyright (c) 1996 John M. Vinopal 72 * All rights reserved. 73 * 74 * Redistribution and use in source and binary forms, with or without 75 * modification, are permitted provided that the following conditions 76 * are met: 77 * 1. Redistributions of source code must retain the above copyright 78 * notice, this list of conditions and the following disclaimer. 79 * 2. Redistributions in binary form must reproduce the above copyright 80 * notice, this list of conditions and the following disclaimer in the 81 * documentation and/or other materials provided with the distribution. 82 * 3. All advertising materials mentioning features or use of this software 83 * must display the following acknowledgement: 84 * This product includes software developed for the NetBSD Project 85 * by John M. Vinopal. 86 * 4. The name of the author may not be used to endorse or promote products 87 * derived from this software without specific prior written permission. 88 * 89 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 90 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 91 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 92 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 93 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 94 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 95 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 96 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 97 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 98 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 99 * SUCH DAMAGE. 100 */ 101 102 103 #include <sys/param.h> 104 #include <sys/errno.h> 105 #include <sys/dkstat.h> 106 #include <sys/sysctl.h> 107 108 #include <err.h> 109 #include <ctype.h> 110 #include <fcntl.h> 111 #include <kvm.h> 112 #include <stdio.h> 113 #include <stdlib.h> 114 #include <string.h> 115 #include <unistd.h> 116 #include <limits.h> 117 #include <devstat.h> 118 119 struct nlist namelist[] = { 120 #define X_TK_NIN 0 121 { "_tk_nin" }, 122 #define X_TK_NOUT 1 123 { "_tk_nout" }, 124 #define X_CP_TIME 2 125 { "_cp_time" }, 126 #define X_HZ 3 127 { "_hz" }, 128 #define X_STATHZ 4 129 { "_stathz" }, 130 #define X_END 4 131 { NULL }, 132 }; 133 134 struct statinfo cur, last; 135 int num_devices; 136 struct device_selection *dev_select; 137 int maxshowdevs; 138 int dflag = 0, Iflag = 0, Cflag = 0, Tflag = 0, oflag = 0, Kflag = 0; 139 140 #define nlread(x, v) \ 141 kvm_read(kd, namelist[x].n_value, &(v), sizeof(v)) 142 143 /* local function declarations */ 144 static void usage(void); 145 static void phdr(int signo); 146 static void devstats(int perf_select,double etime, int havelast); 147 static void cpustats(void); 148 static void getsysctl(const char *, void *, size_t); 149 150 static void 151 usage(void) 152 { 153 /* 154 * We also support the following 'traditional' syntax: 155 * iostat [drives] [wait [count]] 156 * This isn't mentioned in the man page, or the usage statement, 157 * but it is supported. 158 */ 159 fprintf(stderr, "usage: iostat [-CdhIKoT?] [-c count] [-M core]" 160 " [-n devs] [-N system]\n" 161 "\t [-t type,if,pass] [-w wait] [drives]\n"); 162 } 163 164 int 165 main(int argc, char **argv) 166 { 167 int c; 168 register int i; 169 int tflag = 0, hflag = 0, cflag = 0, wflag = 0, nflag = 0; 170 int count = 0, waittime = 0; 171 char *memf = NULL, *nlistf = NULL; 172 struct devstat_match *matches; 173 int num_matches = 0; 174 char errbuf[_POSIX2_LINE_MAX]; 175 kvm_t *kd = NULL; 176 int hz, stathz; 177 int headercount; 178 long generation; 179 int num_devices_specified; 180 int num_selected, num_selections; 181 long select_generation; 182 char **specified_devices; 183 devstat_select_mode select_mode; 184 int use_kvm, havelast = 0; 185 struct clockinfo clkinfo; 186 187 matches = NULL; 188 maxshowdevs = 3; 189 190 while ((c = getopt(argc, argv, "c:CdhIKM:n:N:ot:Tw:?")) != -1) { 191 switch(c) { 192 case 'c': 193 cflag++; 194 count = atoi(optarg); 195 if (count < 1) 196 errx(1, "count %d is < 1", count); 197 break; 198 case 'C': 199 Cflag++; 200 break; 201 case 'd': 202 dflag++; 203 break; 204 case 'h': 205 hflag++; 206 break; 207 case 'I': 208 Iflag++; 209 break; 210 case 'K': 211 Kflag++; 212 break; 213 case 'M': 214 memf = optarg; 215 break; 216 case 'n': 217 nflag++; 218 maxshowdevs = atoi(optarg); 219 if (maxshowdevs < 0) 220 errx(1, "number of devices %d is < 0", 221 maxshowdevs); 222 break; 223 case 'N': 224 nlistf = optarg; 225 break; 226 case 'o': 227 oflag++; 228 break; 229 case 't': 230 tflag++; 231 if (devstat_buildmatch(optarg, &matches, 232 &num_matches) != 0) 233 errx(1, "%s", devstat_errbuf); 234 break; 235 case 'T': 236 Tflag++; 237 break; 238 case 'w': 239 wflag++; 240 waittime = atoi(optarg); 241 if (waittime < 1) 242 errx(1, "wait time is < 1"); 243 break; 244 default: 245 usage(); 246 exit(1); 247 break; 248 } 249 } 250 251 argc -= optind; 252 argv += optind; 253 254 if (nlistf == NULL && memf == NULL) { 255 use_kvm = 0; 256 getsysctl("kern.clockrate", &clkinfo, sizeof(clkinfo)); 257 hz = clkinfo.hz; 258 } else { 259 use_kvm = 1; 260 kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); 261 262 if (kd == 0) 263 errx(1, "kvm_openfiles: %s", errbuf); 264 265 if (kvm_nlist(kd, namelist) == -1) 266 errx(1, "kvm_nlist: %s", kvm_geterr(kd)); 267 268 (void)nlread(X_HZ, hz); 269 (void)nlread(X_STATHZ, stathz); 270 if (stathz) 271 hz = stathz; 272 } 273 274 /* 275 * Make sure that the userland devstat version matches the kernel 276 * devstat version. If not, exit and print a message informing 277 * the user of his mistake. 278 */ 279 if (devstat_checkversion(kd) < 0) 280 errx(1, "%s", devstat_errbuf); 281 282 /* 283 * Figure out how many devices we should display. 284 */ 285 if (nflag == 0) { 286 if (oflag > 0) { 287 if ((dflag > 0) && (Cflag == 0) && (Tflag == 0)) 288 maxshowdevs = 5; 289 else if ((dflag > 0) && (Tflag > 0) && (Cflag == 0)) 290 maxshowdevs = 5; 291 else 292 maxshowdevs = 4; 293 } else { 294 if ((dflag > 0) && (Cflag == 0)) 295 maxshowdevs = 4; 296 else 297 maxshowdevs = 3; 298 } 299 } 300 301 /* find out how many devices we have */ 302 if ((num_devices = devstat_getnumdevs(kd)) < 0) 303 err(1, "can't get number of devices"); 304 305 if ((cur.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo))) == 306 NULL) 307 err(1, "devinfo malloc failed"); 308 if ((last.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo))) == 309 NULL) 310 err(1, "devinfo malloc failed"); 311 bzero(cur.dinfo, sizeof(struct devinfo)); 312 bzero(last.dinfo, sizeof(struct devinfo)); 313 314 /* 315 * Grab all the devices. We don't look to see if the list has 316 * changed here, since it almost certainly has. We only look for 317 * errors. 318 */ 319 if (devstat_getdevs(kd, &cur) == -1) 320 errx(1, "%s", devstat_errbuf); 321 322 num_devices = cur.dinfo->numdevs; 323 generation = cur.dinfo->generation; 324 325 /* 326 * If the user specified any devices on the command line, see if 327 * they are in the list of devices we have now. 328 */ 329 if ((specified_devices = (char **)malloc(sizeof(char *))) == NULL) 330 err(1, "specified_devices malloc failed"); 331 for (num_devices_specified = 0; *argv; ++argv) { 332 if (isdigit(**argv)) 333 break; 334 num_devices_specified++; 335 specified_devices = (char **)realloc(specified_devices, 336 sizeof(char *) * 337 num_devices_specified); 338 specified_devices[num_devices_specified - 1] = *argv; 339 340 } 341 if (nflag == 0 && maxshowdevs < num_devices_specified) 342 maxshowdevs = num_devices_specified; 343 344 dev_select = NULL; 345 346 if ((num_devices_specified == 0) && (num_matches == 0)) 347 select_mode = DS_SELECT_ADD; 348 else 349 select_mode = DS_SELECT_ONLY; 350 351 /* 352 * At this point, selectdevs will almost surely indicate that the 353 * device list has changed, so we don't look for return values of 0 354 * or 1. If we get back -1, though, there is an error. 355 */ 356 if (devstat_selectdevs(&dev_select, &num_selected, 357 &num_selections, &select_generation, generation, 358 cur.dinfo->devices, num_devices, matches, 359 num_matches, specified_devices, 360 num_devices_specified, select_mode, maxshowdevs, 361 hflag) == -1) 362 errx(1, "%s", devstat_errbuf); 363 364 /* 365 * Look for the traditional wait time and count arguments. 366 */ 367 if (*argv) { 368 waittime = atoi(*argv); 369 370 /* Let the user know he goofed, but keep going anyway */ 371 if (wflag != 0) 372 warnx("discarding previous wait interval, using" 373 " %d instead", waittime); 374 wflag++; 375 376 if (*++argv) { 377 count = atoi(*argv); 378 if (cflag != 0) 379 warnx("discarding previous count, using %d" 380 " instead", count); 381 cflag++; 382 } else 383 count = -1; 384 } 385 386 /* 387 * If the user specified a count, but not an interval, we default 388 * to an interval of 1 second. 389 */ 390 if ((wflag == 0) && (cflag > 0)) 391 waittime = 1; 392 393 /* 394 * If the user specified a wait time, but not a count, we want to 395 * go on ad infinitum. This can be redundant if the user uses the 396 * traditional method of specifying the wait, since in that case we 397 * already set count = -1 above. Oh well. 398 */ 399 if ((wflag > 0) && (cflag == 0)) 400 count = -1; 401 402 /* 403 * If the user stops the program (control-Z) and then resumes it, 404 * print out the header again. 405 */ 406 (void)signal(SIGCONT, phdr); 407 408 for (headercount = 1;;) { 409 struct devinfo *tmp_dinfo; 410 long tmp; 411 double etime; 412 413 if (!--headercount) { 414 phdr(0); 415 headercount = 20; 416 } 417 if (use_kvm) { 418 (void)kvm_read(kd, namelist[X_TK_NIN].n_value, 419 &cur.tk_nin, sizeof(cur.tk_nin)); 420 (void)kvm_read(kd, namelist[X_TK_NOUT].n_value, 421 &cur.tk_nout, sizeof(cur.tk_nout)); 422 (void)kvm_read(kd, namelist[X_CP_TIME].n_value, 423 cur.cp_time, sizeof(cur.cp_time)); 424 } else { 425 getsysctl("kern.tty_nin", &cur.tk_nin, 426 sizeof(cur.tk_nin)); 427 getsysctl("kern.tty_nout", &cur.tk_nout, 428 sizeof(cur.tk_nout)); 429 getsysctl("kern.cp_time", &cur.cp_time, 430 sizeof(cur.cp_time)); 431 } 432 433 tmp_dinfo = last.dinfo; 434 last.dinfo = cur.dinfo; 435 cur.dinfo = tmp_dinfo; 436 437 last.busy_time = cur.busy_time; 438 439 /* 440 * Here what we want to do is refresh our device stats. 441 * devstat_getdevs() returns 1 when the device list has changed. 442 * If the device list has changed, we want to go through 443 * the selection process again, in case a device that we 444 * were previously displaying has gone away. 445 */ 446 switch (devstat_getdevs(kd, &cur)) { 447 case -1: 448 errx(1, "%s", devstat_errbuf); 449 break; 450 case 1: { 451 int retval; 452 453 num_devices = cur.dinfo->numdevs; 454 generation = cur.dinfo->generation; 455 retval = devstat_selectdevs(&dev_select, &num_selected, 456 &num_selections, 457 &select_generation, 458 generation, 459 cur.dinfo->devices, 460 num_devices, matches, 461 num_matches, 462 specified_devices, 463 num_devices_specified, 464 select_mode, maxshowdevs, 465 hflag); 466 switch(retval) { 467 case -1: 468 errx(1, "%s", devstat_errbuf); 469 break; 470 case 1: 471 phdr(0); 472 headercount = 20; 473 break; 474 default: 475 break; 476 } 477 break; 478 } 479 default: 480 break; 481 } 482 483 /* 484 * We only want to re-select devices if we're in 'top' 485 * mode. This is the only mode where the devices selected 486 * could actually change. 487 */ 488 if (hflag > 0) { 489 int retval; 490 retval = devstat_selectdevs(&dev_select, &num_selected, 491 &num_selections, 492 &select_generation, 493 generation, 494 cur.dinfo->devices, 495 num_devices, matches, 496 num_matches, 497 specified_devices, 498 num_devices_specified, 499 select_mode, maxshowdevs, 500 hflag); 501 switch(retval) { 502 case -1: 503 errx(1,"%s", devstat_errbuf); 504 break; 505 case 1: 506 phdr(0); 507 headercount = 20; 508 break; 509 default: 510 break; 511 } 512 } 513 514 tmp = cur.tk_nin; 515 cur.tk_nin -= last.tk_nin; 516 last.tk_nin = tmp; 517 tmp = cur.tk_nout; 518 cur.tk_nout -= last.tk_nout; 519 last.tk_nout = tmp; 520 521 etime = 0.0; 522 523 #define X(fld) tmp = cur.fld[i]; cur.fld[i] -= last.fld[i]; last.fld[i] = tmp 524 525 for (i = 0; i < CPUSTATES; i++) { 526 X(cp_time); 527 etime += cur.cp_time[i]; 528 } 529 etime /= (float)hz; 530 if (etime == 0.0) 531 etime = 1.0; 532 if ((dflag == 0) || (Tflag > 0)) 533 printf("%4.0f%5.0f", cur.tk_nin / etime, 534 cur.tk_nout/etime); 535 devstats(hflag, etime, havelast); 536 if ((dflag == 0) || (Cflag > 0)) 537 cpustats(); 538 printf("\n"); 539 fflush(stdout); 540 541 if (count >= 0 && --count <= 0) 542 break; 543 544 sleep(waittime); 545 havelast = 1; 546 } 547 548 exit(0); 549 } 550 551 static void 552 phdr(int signo) 553 { 554 register int i; 555 int printed; 556 557 if ((dflag == 0) || (Tflag > 0)) 558 (void)printf(" tty"); 559 for (i = 0, printed=0;(i < num_devices) && (printed < maxshowdevs);i++){ 560 int di; 561 if ((dev_select[i].selected != 0) 562 && (dev_select[i].selected <= maxshowdevs)) { 563 di = dev_select[i].position; 564 if (oflag > 0) 565 (void)printf("%12.6s%d ", 566 cur.dinfo->devices[di].device_name, 567 cur.dinfo->devices[di].unit_number); 568 else 569 printf("%15.6s%d ", 570 cur.dinfo->devices[di].device_name, 571 cur.dinfo->devices[di].unit_number); 572 printed++; 573 } 574 } 575 if ((dflag == 0) || (Cflag > 0)) 576 (void)printf(" cpu\n"); 577 else 578 (void)printf("\n"); 579 580 if ((dflag == 0) || (Tflag > 0)) 581 (void)printf(" tin tout"); 582 583 for (i=0, printed = 0;(i < num_devices) && (printed < maxshowdevs);i++){ 584 if ((dev_select[i].selected != 0) 585 && (dev_select[i].selected <= maxshowdevs)) { 586 if (oflag > 0) { 587 if (Iflag == 0) 588 (void)printf(" sps tps msps "); 589 else 590 (void)printf(" blk xfr msps "); 591 } else { 592 if (Iflag == 0) 593 printf(" KB/t tps MB/s "); 594 else 595 printf(" KB/t xfrs MB "); 596 } 597 printed++; 598 } 599 } 600 if ((dflag == 0) || (Cflag > 0)) 601 (void)printf(" us ni sy in id\n"); 602 else 603 printf("\n"); 604 605 } 606 607 static void 608 devstats(int perf_select, double etime, int havelast) 609 { 610 register int dn; 611 long double transfers_per_second; 612 long double kb_per_transfer, mb_per_second; 613 u_int64_t total_bytes, total_transfers, total_blocks; 614 long double busy_seconds; 615 long double total_mb; 616 long double blocks_per_second, ms_per_transaction; 617 618 /* 619 * Calculate elapsed time up front, since it's the same for all 620 * devices. 621 */ 622 if (havelast) 623 busy_seconds = devstat_compute_etime(cur.busy_time, 624 last.busy_time); 625 else 626 busy_seconds = etime; 627 628 for (dn = 0; dn < num_devices; dn++) { 629 int di; 630 631 if (((perf_select == 0) && (dev_select[dn].selected == 0)) 632 || (dev_select[dn].selected > maxshowdevs)) 633 continue; 634 635 di = dev_select[dn].position; 636 637 if (devstat_compute_statistics(&cur.dinfo->devices[di], 638 havelast ? &last.dinfo->devices[di] : NULL, busy_seconds, 639 DSM_TOTAL_BYTES, &total_bytes, 640 DSM_TOTAL_TRANSFERS, &total_transfers, 641 DSM_TOTAL_BLOCKS, &total_blocks, 642 DSM_KB_PER_TRANSFER, &kb_per_transfer, 643 DSM_TRANSFERS_PER_SECOND, &transfers_per_second, 644 DSM_MB_PER_SECOND, &mb_per_second, 645 DSM_BLOCKS_PER_SECOND, &blocks_per_second, 646 DSM_MS_PER_TRANSACTION, &ms_per_transaction, 647 DSM_NONE) != 0) 648 errx(1, "%s", devstat_errbuf); 649 650 if (perf_select != 0) { 651 dev_select[dn].bytes = total_bytes; 652 if ((dev_select[dn].selected == 0) 653 || (dev_select[dn].selected > maxshowdevs)) 654 continue; 655 } 656 657 if (Kflag) { 658 int block_size = cur.dinfo->devices[di].block_size; 659 total_blocks = total_blocks * (block_size ? 660 block_size : 512) / 1024; 661 } 662 663 if (oflag > 0) { 664 int msdig = (ms_per_transaction < 100.0) ? 1 : 0; 665 666 if (Iflag == 0) 667 printf("%4.0Lf%4.0Lf%5.*Lf ", 668 blocks_per_second, 669 transfers_per_second, 670 msdig, 671 ms_per_transaction); 672 else 673 printf("%4.1qu%4.1qu%5.*Lf ", 674 total_blocks, 675 total_transfers, 676 msdig, 677 ms_per_transaction); 678 } else { 679 if (Iflag == 0) 680 printf(" %5.2Lf %3.0Lf %5.2Lf ", 681 kb_per_transfer, 682 transfers_per_second, 683 mb_per_second); 684 else { 685 total_mb = total_bytes; 686 total_mb /= 1024 * 1024; 687 688 printf(" %5.2Lf %3.1qu %5.2Lf ", 689 kb_per_transfer, 690 total_transfers, 691 total_mb); 692 } 693 } 694 } 695 } 696 697 static void 698 cpustats(void) 699 { 700 register int state; 701 double time; 702 703 time = 0.0; 704 705 for (state = 0; state < CPUSTATES; ++state) 706 time += cur.cp_time[state]; 707 for (state = 0; state < CPUSTATES; ++state) 708 printf("%3.0f", 709 100. * cur.cp_time[state] / (time ? time : 1)); 710 } 711 712 static void 713 getsysctl(const char *name, void *ptr, size_t len) 714 { 715 size_t nlen = len; 716 717 if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) 718 err(1, "sysctl(%s...) failed", name); 719 if (nlen != len) 720 errx(1, "sysctl(%s...): expected %lu, got %lu", name, 721 (unsigned long)len, (unsigned long)nlen); 722 } 723