1 /* $OpenBSD: vmstat.c,v 1.81 2016/08/24 03:13:45 guenther Exp $ */ 2 /* $NetBSD: vmstat.c,v 1.5 1996/05/10 23:16:40 thorpej Exp $ */ 3 4 /*- 5 * Copyright (c) 1983, 1989, 1992, 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 /* 34 * Cursed vmstat -- from Robert Elz. 35 */ 36 37 #include <sys/param.h> /* MAXCOMLEN */ 38 #include <sys/types.h> 39 #include <sys/namei.h> 40 #include <sys/proc.h> 41 #include <sys/sched.h> 42 #include <sys/stat.h> 43 #include <sys/sysctl.h> 44 #include <sys/time.h> 45 #include <sys/vmmeter.h> 46 47 #include <ctype.h> 48 #include <errno.h> 49 #include <err.h> 50 #include <paths.h> 51 #include <signal.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <unistd.h> 55 56 #include "systat.h" 57 #include "dkstats.h" 58 59 #define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) 60 61 static struct Info { 62 long time[CPUSTATES]; 63 struct uvmexp uvmexp; 64 struct vmtotal Total; 65 struct nchstats nchstats; 66 long nchcount; 67 uint64_t *intrcnt; 68 } s, s1, s2, s3, z; 69 70 extern struct _disk cur; 71 72 #define cnt s.Cnt 73 #define oldcnt s1.Cnt 74 #define total s.Total 75 #define nchtotal s.nchstats 76 #define oldnchtotal s1.nchstats 77 78 static enum state { BOOT, TIME, RUN } state = TIME; 79 80 static void allocinfo(struct Info *); 81 static void copyinfo(struct Info *, struct Info *); 82 static float cputime(int); 83 static void dinfo(int, int); 84 static void getinfo(struct Info *); 85 void putint(int, int, int, int); 86 void putintmk(int, int, int, int); 87 void putuint64(u_int64_t, int, int, int); 88 void putfloat(double, int, int, int, int, int); 89 int ucount(void); 90 91 void print_vm(void); 92 int read_vm(void); 93 int select_vm(void); 94 int vm_keyboard_callback(int); 95 96 static time_t t; 97 static double etime; 98 static float hertz; 99 static int nintr; 100 static long *intrloc; 101 static char **intrname; 102 static int nextintsrow; 103 104 WINDOW * 105 openkre(void) 106 { 107 return (subwin(stdscr, LINES-1-1, 0, 1, 0)); 108 } 109 110 void 111 closekre(WINDOW *w) 112 { 113 114 if (w == NULL) 115 return; 116 wclear(w); 117 wrefresh(w); 118 delwin(w); 119 } 120 121 /* 122 * These constants define where the major pieces are laid out 123 */ 124 #define STATROW 0 /* uses 1 row and 68 cols */ 125 #define STATCOL 2 126 #define MEMROW 2 /* uses 4 rows and 34 cols */ 127 #define MEMCOL 0 128 #define PAGEROW 2 /* uses 4 rows and 26 cols */ 129 #define PAGECOL 37 130 #define INTSROW 2 /* uses all rows to bottom and 17 cols */ 131 #define INTSCOL 63 132 #define PROCSROW 7 /* uses 2 rows and 20 cols */ 133 #define PROCSCOL 0 134 #define GENSTATROW 7 /* uses 2 rows and 35 cols */ 135 #define GENSTATCOL 16 136 #define VMSTATROW 7 /* uses 18 rows and 12 cols */ 137 #define VMSTATCOL 48 138 #define GRAPHROW 10 /* uses 3 rows and 51 cols */ 139 #define GRAPHCOL 0 140 #define NAMEIROW 14 /* uses 3 rows and 49 cols */ 141 #define NAMEICOL 0 142 #define DISKROW 18 /* uses 5 rows and 50 cols (for 9 drives) */ 143 #define DISKCOL 0 144 145 #define DRIVESPACE 45 /* max space for drives */ 146 147 148 field_def *view_vm_0[] = { 149 NULL 150 }; 151 152 /* Define view managers */ 153 struct view_manager vmstat_mgr = { 154 "VMstat", select_vm, read_vm, NULL, print_header, 155 print_vm, vm_keyboard_callback, NULL, NULL 156 }; 157 158 field_view views_vm[] = { 159 {view_vm_0, "vmstat", '7', &vmstat_mgr}, 160 {NULL, NULL, 0, NULL} 161 }; 162 163 int 164 initvmstat(void) 165 { 166 field_view *v; 167 int mib[4], i; 168 size_t size; 169 170 hertz = stathz; 171 if (!dkinit(1)) 172 return(0); 173 174 mib[0] = CTL_KERN; 175 mib[1] = KERN_INTRCNT; 176 mib[2] = KERN_INTRCNT_NUM; 177 size = sizeof(nintr); 178 if (sysctl(mib, 3, &nintr, &size, NULL, 0) < 0) 179 return (-1); 180 181 intrloc = calloc(nintr, sizeof(long)); 182 intrname = calloc(nintr, sizeof(char *)); 183 184 for (i = 0; i < nintr; i++) { 185 char name[128]; 186 187 mib[0] = CTL_KERN; 188 mib[1] = KERN_INTRCNT; 189 mib[2] = KERN_INTRCNT_NAME; 190 mib[3] = i; 191 size = sizeof(name); 192 if (sysctl(mib, 4, name, &size, NULL, 0) < 0) 193 return (-1); 194 195 intrname[i] = strdup(name); 196 if (intrname[i] == NULL) 197 return (-1); 198 } 199 200 nextintsrow = INTSROW + 2; 201 allocinfo(&s); 202 allocinfo(&s1); 203 allocinfo(&s2); 204 allocinfo(&s3); 205 allocinfo(&z); 206 207 getinfo(&s2); 208 copyinfo(&z, &s1); 209 210 for (v = views_vm; v->name != NULL; v++) 211 add_view(v); 212 213 return(1); 214 } 215 216 void 217 fetchkre(void) 218 { 219 getinfo(&s3); 220 } 221 222 void 223 labelkre(void) 224 { 225 int i, j, l; 226 227 mvprintw(MEMROW, MEMCOL, " memory totals (in KB)"); 228 mvprintw(MEMROW + 1, MEMCOL, " real virtual free"); 229 mvprintw(MEMROW + 2, MEMCOL, "Active"); 230 mvprintw(MEMROW + 3, MEMCOL, "All"); 231 232 mvprintw(PAGEROW, PAGECOL, " PAGING SWAPPING "); 233 mvprintw(PAGEROW + 1, PAGECOL, " in out in out "); 234 mvprintw(PAGEROW + 2, PAGECOL, "ops"); 235 mvprintw(PAGEROW + 3, PAGECOL, "pages"); 236 237 mvprintw(INTSROW, INTSCOL + 3, " Interrupts"); 238 mvprintw(INTSROW + 1, INTSCOL + 9, "total"); 239 240 mvprintw(LINES - 3, INTSCOL + 9, "IPKTS"); 241 mvprintw(LINES - 2, INTSCOL + 9, "OPKTS"); 242 243 mvprintw(VMSTATROW + 0, VMSTATCOL + 10, "forks"); 244 mvprintw(VMSTATROW + 1, VMSTATCOL + 10, "fkppw"); 245 mvprintw(VMSTATROW + 2, VMSTATCOL + 10, "fksvm"); 246 mvprintw(VMSTATROW + 3, VMSTATCOL + 10, "pwait"); 247 mvprintw(VMSTATROW + 4, VMSTATCOL + 10, "relck"); 248 mvprintw(VMSTATROW + 5, VMSTATCOL + 10, "rlkok"); 249 mvprintw(VMSTATROW + 6, VMSTATCOL + 10, "noram"); 250 mvprintw(VMSTATROW + 7, VMSTATCOL + 10, "ndcpy"); 251 mvprintw(VMSTATROW + 8, VMSTATCOL + 10, "fltcp"); 252 mvprintw(VMSTATROW + 9, VMSTATCOL + 10, "zfod"); 253 mvprintw(VMSTATROW + 10, VMSTATCOL + 10, "cow"); 254 mvprintw(VMSTATROW + 11, VMSTATCOL + 10, "fmin"); 255 mvprintw(VMSTATROW + 12, VMSTATCOL + 10, "ftarg"); 256 mvprintw(VMSTATROW + 13, VMSTATCOL + 10, "itarg"); 257 mvprintw(VMSTATROW + 14, VMSTATCOL + 10, "wired"); 258 mvprintw(VMSTATROW + 15, VMSTATCOL + 10, "pdfre"); 259 if (LINES - 1 > VMSTATROW + 16) 260 mvprintw(VMSTATROW + 16, VMSTATCOL + 10, "pdscn"); 261 if (LINES - 1 > VMSTATROW + 17) 262 mvprintw(VMSTATROW + 17, VMSTATCOL + 10, "pzidle"); 263 if (LINES - 1 > VMSTATROW + 18) 264 mvprintw(VMSTATROW + 18, VMSTATCOL + 10, "kmapent"); 265 266 mvprintw(GENSTATROW, GENSTATCOL, " Csw Trp Sys Int Sof Flt"); 267 268 mvprintw(GRAPHROW, GRAPHCOL, 269 " . %%Int . %%Sys . %%Usr . %%Nic . %%Idle"); 270 mvprintw(PROCSROW, PROCSCOL, "Proc:r d s w"); 271 mvprintw(GRAPHROW + 1, GRAPHCOL, 272 "| | | | | | | | | | |"); 273 274 mvprintw(NAMEIROW, NAMEICOL, 275 "Namei Sys-cache Proc-cache No-cache"); 276 mvprintw(NAMEIROW + 1, NAMEICOL, 277 " Calls hits %% hits %% miss %%"); 278 mvprintw(DISKROW, DISKCOL, "Disks"); 279 mvprintw(DISKROW + 1, DISKCOL, "seeks"); 280 mvprintw(DISKROW + 2, DISKCOL, "xfers"); 281 mvprintw(DISKROW + 3, DISKCOL, "speed"); 282 mvprintw(DISKROW + 4, DISKCOL, " sec"); 283 for (i = 0, j = 0; i < cur.dk_ndrive && j < DRIVESPACE; i++) 284 if (cur.dk_select[i] && (j + strlen(dr_name[i])) < DRIVESPACE) { 285 l = MAXIMUM(5, strlen(dr_name[i])); 286 mvprintw(DISKROW, DISKCOL + 5 + j, 287 " %*s", l, dr_name[i]); 288 j += 1 + l; 289 } 290 for (i = 0; i < nintr; i++) { 291 if (intrloc[i] == 0) 292 continue; 293 mvprintw(intrloc[i], INTSCOL + 9, "%-8.8s", intrname[i]); 294 } 295 } 296 297 #define X(fld) {s.fld[i]; s.fld[i]-=s1.fld[i];} 298 #define Y(fld) {s.fld; s.fld -= s1.fld;} 299 #define Z(fld) {s.nchstats.fld; s.nchstats.fld -= s1.nchstats.fld;} 300 #define PUTRATE(fld, l, c, w) \ 301 do { \ 302 Y(fld); \ 303 putint((int)((float)s.fld/etime + 0.5), l, c, w); \ 304 } while (0) 305 #define MAXFAIL 5 306 307 static char cpuchar[CPUSTATES] = { '|', '=', '>', '-', ' ' }; 308 static char cpuorder[CPUSTATES] = { CP_INTR, CP_SYS, CP_USER, CP_NICE, CP_IDLE }; 309 310 void 311 showkre(void) 312 { 313 float f1, f2; 314 int psiz; 315 u_int64_t inttotal, intcnt; 316 int i, l, c; 317 static int failcnt = 0, first_run = 0; 318 319 if (state == TIME) { 320 if (!first_run) { 321 first_run = 1; 322 return; 323 } 324 } 325 etime = 0; 326 for (i = 0; i < CPUSTATES; i++) { 327 X(time); 328 etime += s.time[i]; 329 } 330 if (etime < 5.0) { /* < 5 ticks - ignore this trash */ 331 if (failcnt++ >= MAXFAIL) { 332 error("The alternate system clock has died!"); 333 failcnt = 0; 334 } 335 return; 336 } 337 failcnt = 0; 338 etime /= hertz; 339 inttotal = 0; 340 for (i = 0; i < nintr; i++) { 341 if (s.intrcnt[i] == 0) 342 continue; 343 if (intrloc[i] == 0) { 344 if (nextintsrow == LINES) 345 continue; 346 intrloc[i] = nextintsrow++; 347 mvprintw(intrloc[i], INTSCOL + 9, "%-8.8s", 348 intrname[i]); 349 } 350 t = intcnt = s.intrcnt[i]; 351 s.intrcnt[i] -= s1.intrcnt[i]; 352 intcnt = (u_int64_t)((float)s.intrcnt[i]/etime + 0.5); 353 inttotal += intcnt; 354 putuint64(intcnt, intrloc[i], INTSCOL, 8); 355 } 356 putuint64(inttotal, INTSROW + 1, INTSCOL, 8); 357 Z(ncs_goodhits); Z(ncs_badhits); Z(ncs_miss); 358 Z(ncs_long); Z(ncs_pass2); Z(ncs_2passes); 359 s.nchcount = nchtotal.ncs_goodhits + nchtotal.ncs_badhits + 360 nchtotal.ncs_miss + nchtotal.ncs_long; 361 362 putint(sum.ifc_ip, LINES - 3, INTSCOL, 8); 363 putint(sum.ifc_op, LINES - 2, INTSCOL, 8); 364 365 psiz = 0; 366 f2 = 0.0; 367 368 for (c = 0; c < CPUSTATES; c++) { 369 i = cpuorder[c]; 370 f1 = cputime(i); 371 f2 += f1; 372 l = (int) ((f2 + 1.0) / 2.0) - psiz; 373 putfloat(f1, GRAPHROW, GRAPHCOL + 1 + (10 * c), 5, 1, 0); 374 move(GRAPHROW + 2, psiz); 375 psiz += l; 376 while (l-- > 0) 377 addch(cpuchar[c]); 378 } 379 380 #define pgtokb(pg) ((pg) * (s.uvmexp.pagesize / 1024)) 381 382 putint(pgtokb(s.uvmexp.active), MEMROW + 2, MEMCOL + 7, 8); 383 putint(pgtokb(s.uvmexp.active + s.uvmexp.swpginuse), /* XXX */ 384 MEMROW + 2, MEMCOL + 17, 8); 385 putint(pgtokb(s.uvmexp.npages - s.uvmexp.free), MEMROW + 3, MEMCOL + 7, 8); 386 putint(pgtokb(s.uvmexp.npages - s.uvmexp.free + s.uvmexp.swpginuse), 387 MEMROW + 3, MEMCOL + 17, 8); 388 putint(pgtokb(s.uvmexp.free), MEMROW + 2, MEMCOL + 26, 8); 389 putint(pgtokb(s.uvmexp.free + s.uvmexp.swpages - s.uvmexp.swpginuse), 390 MEMROW + 3, MEMCOL + 26, 8); 391 putint(total.t_rq - 1, PROCSROW + 1, PROCSCOL + 3, 3); 392 393 putint(total.t_dw, PROCSROW + 1, PROCSCOL + 6, 3); 394 putint(total.t_sl, PROCSROW + 1, PROCSCOL + 9, 3); 395 putint(total.t_sw, PROCSROW + 1, PROCSCOL + 12, 3); 396 PUTRATE(uvmexp.forks, VMSTATROW + 0, VMSTATCOL + 3, 6); 397 PUTRATE(uvmexp.forks_ppwait, VMSTATROW + 1, VMSTATCOL + 3, 6); 398 PUTRATE(uvmexp.forks_sharevm, VMSTATROW + 2, VMSTATCOL + 3, 6); 399 PUTRATE(uvmexp.fltpgwait, VMSTATROW + 3, VMSTATCOL + 4, 5); 400 PUTRATE(uvmexp.fltrelck, VMSTATROW + 4, VMSTATCOL + 3, 6); 401 PUTRATE(uvmexp.fltrelckok, VMSTATROW + 5, VMSTATCOL + 3, 6); 402 PUTRATE(uvmexp.fltnoram, VMSTATROW + 6, VMSTATCOL + 3, 6); 403 PUTRATE(uvmexp.fltamcopy, VMSTATROW + 7, VMSTATCOL + 3, 6); 404 PUTRATE(uvmexp.flt_prcopy, VMSTATROW + 8, VMSTATCOL + 3, 6); 405 PUTRATE(uvmexp.flt_przero, VMSTATROW + 9, VMSTATCOL + 3, 6); 406 PUTRATE(uvmexp.flt_acow, VMSTATROW + 10, VMSTATCOL, 9); 407 putint(s.uvmexp.freemin, VMSTATROW + 11, VMSTATCOL, 9); 408 putint(s.uvmexp.freetarg, VMSTATROW + 12, VMSTATCOL, 9); 409 putint(s.uvmexp.inactarg, VMSTATROW + 13, VMSTATCOL, 9); 410 putint(s.uvmexp.wired, VMSTATROW + 14, VMSTATCOL, 9); 411 PUTRATE(uvmexp.pdfreed, VMSTATROW + 15, VMSTATCOL, 9); 412 if (LINES - 1 > VMSTATROW + 16) 413 PUTRATE(uvmexp.pdscans, VMSTATROW + 16, VMSTATCOL, 9); 414 if (LINES - 1 > VMSTATROW + 17) 415 PUTRATE(uvmexp.zeropages, VMSTATROW + 17, VMSTATCOL, 9); 416 if (LINES - 1 > VMSTATROW + 18) 417 putint(s.uvmexp.kmapent, VMSTATROW + 18, VMSTATCOL, 9); 418 419 PUTRATE(uvmexp.pageins, PAGEROW + 2, PAGECOL + 5, 5); 420 PUTRATE(uvmexp.pdpageouts, PAGEROW + 2, PAGECOL + 10, 5); 421 PUTRATE(uvmexp.pgswapin, PAGEROW + 3, PAGECOL + 5, 5); 422 PUTRATE(uvmexp.pgswapout, PAGEROW + 3, PAGECOL + 10, 5); 423 424 PUTRATE(uvmexp.swtch, GENSTATROW + 1, GENSTATCOL, 6); 425 PUTRATE(uvmexp.traps, GENSTATROW + 1, GENSTATCOL + 6, 6); 426 PUTRATE(uvmexp.syscalls, GENSTATROW + 1, GENSTATCOL + 12, 6); 427 PUTRATE(uvmexp.intrs, GENSTATROW + 1, GENSTATCOL + 18, 6); 428 PUTRATE(uvmexp.softs, GENSTATROW + 1, GENSTATCOL + 24, 6); 429 PUTRATE(uvmexp.faults, GENSTATROW + 1, GENSTATCOL + 30, 5); 430 mvprintw(DISKROW, DISKCOL + 5, " "); 431 for (i = 0, c = 0; i < cur.dk_ndrive && c < DRIVESPACE; i++) 432 if (cur.dk_select[i] && (c + strlen(dr_name[i])) < DRIVESPACE) { 433 l = MAXIMUM(5, strlen(dr_name[i])); 434 mvprintw(DISKROW, DISKCOL + 5 + c, 435 " %*s", l, dr_name[i]); 436 c += 1 + l; 437 dinfo(i, c); 438 } 439 /* and pad the DRIVESPACE */ 440 l = DRIVESPACE - c; 441 for (i = 0; i < 5; i++) 442 mvprintw(DISKROW + i, DISKCOL + 5 + c, "%*s", l, ""); 443 444 putint(s.nchcount, NAMEIROW + 2, NAMEICOL, 9); 445 putint(nchtotal.ncs_goodhits, NAMEIROW + 2, NAMEICOL + 10, 8); 446 #define nz(x) ((x) ? (x) : 1) 447 putfloat(nchtotal.ncs_goodhits * 100.0 / nz(s.nchcount), 448 NAMEIROW + 2, NAMEICOL + 19, 4, 0, 1); 449 putint(nchtotal.ncs_pass2, NAMEIROW + 2, NAMEICOL + 24, 7); 450 putfloat(nchtotal.ncs_pass2 * 100.0 / nz(s.nchcount), 451 NAMEIROW + 2, NAMEICOL + 33, 4, 0, 1); 452 putint(nchtotal.ncs_miss + nchtotal.ncs_long - nchtotal.ncs_pass2, 453 NAMEIROW + 2, NAMEICOL + 38, 7); 454 putfloat((nchtotal.ncs_miss + nchtotal.ncs_long - nchtotal.ncs_pass2) * 455 100.0 / nz(s.nchcount), NAMEIROW + 2, NAMEICOL + 45, 4, 0, 1); 456 #undef nz 457 458 } 459 460 int 461 vm_keyboard_callback(int ch) 462 { 463 switch(ch) { 464 case 'r': 465 copyinfo(&s2, &s1); 466 state = RUN; 467 break; 468 case 'b': 469 state = BOOT; 470 copyinfo(&z, &s1); 471 break; 472 case 't': 473 state = TIME; 474 break; 475 case 'z': 476 if (state == RUN) 477 getinfo(&s1); 478 break; 479 } 480 return (keyboard_callback(ch)); 481 } 482 483 484 static float 485 cputime(int indx) 486 { 487 double tm; 488 int i; 489 490 tm = 0; 491 for (i = 0; i < CPUSTATES; i++) 492 tm += s.time[i]; 493 if (tm == 0.0) 494 tm = 1.0; 495 return (s.time[indx] * 100.0 / tm); 496 } 497 498 void 499 putint(int n, int l, int c, int w) 500 { 501 char b[128]; 502 503 move(l, c); 504 if (n == 0) { 505 while (w-- > 0) 506 addch(' '); 507 return; 508 } 509 snprintf(b, sizeof b, "%*d", w, n); 510 if (strlen(b) > w) { 511 while (w-- > 0) 512 addch('*'); 513 return; 514 } 515 addstr(b); 516 } 517 518 void 519 putintmk(int n, int l, int c, int w) 520 { 521 char b[128]; 522 523 move(l, c); 524 if (n == 0) { 525 while (w-- > 0) 526 addch(' '); 527 return; 528 } 529 if (n > 9999 * 1024) 530 snprintf(b, sizeof b, "%*dG", w - 1, n / 1024 / 1024); 531 else if (n > 9999) 532 snprintf(b, sizeof b, "%*dM", w - 1, n / 1024); 533 else 534 snprintf(b, sizeof b, "%*dK", w - 1, n); 535 if (strlen(b) > w) { 536 while (w-- > 0) 537 addch('*'); 538 return; 539 } 540 addstr(b); 541 } 542 543 void 544 putuint64(u_int64_t n, int l, int c, int w) 545 { 546 char b[128]; 547 548 move(l, c); 549 if (n == 0) { 550 while (w-- > 0) 551 addch(' '); 552 return; 553 } 554 snprintf(b, sizeof b, "%*llu", w, n); 555 if (strlen(b) > w) { 556 while (w-- > 0) 557 addch('*'); 558 return; 559 } 560 addstr(b); 561 } 562 563 void 564 putfloat(double f, int l, int c, int w, int d, int nz) 565 { 566 char b[128]; 567 568 move(l, c); 569 if (nz && f == 0.0) { 570 while (--w >= 0) 571 addch(' '); 572 return; 573 } 574 snprintf(b, sizeof b, "%*.*f", w, d, f); 575 if (strlen(b) > w) { 576 while (--w >= 0) 577 addch('*'); 578 return; 579 } 580 addstr(b); 581 } 582 583 static void 584 getinfo(struct Info *si) 585 { 586 static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME }; 587 static int nchstats_mib[2] = { CTL_KERN, KERN_NCHSTATS }; 588 static int uvmexp_mib[2] = { CTL_VM, VM_UVMEXP }; 589 static int vmtotal_mib[2] = { CTL_VM, VM_METER }; 590 int mib[4], i; 591 size_t size; 592 593 dkreadstats(); 594 595 for (i = 0; i < nintr; i++) { 596 mib[0] = CTL_KERN; 597 mib[1] = KERN_INTRCNT; 598 mib[2] = KERN_INTRCNT_CNT; 599 mib[3] = i; 600 size = sizeof(si->intrcnt[i]); 601 if (sysctl(mib, 4, &si->intrcnt[i], &size, NULL, 0) < 0) { 602 si->intrcnt[i] = 0; 603 } 604 } 605 606 size = sizeof(si->time); 607 if (sysctl(cp_time_mib, 2, &si->time, &size, NULL, 0) < 0) { 608 error("Can't get KERN_CPTIME: %s\n", strerror(errno)); 609 memset(&si->time, 0, sizeof(si->time)); 610 } 611 612 size = sizeof(si->nchstats); 613 if (sysctl(nchstats_mib, 2, &si->nchstats, &size, NULL, 0) < 0) { 614 error("Can't get KERN_NCHSTATS: %s\n", strerror(errno)); 615 memset(&si->nchstats, 0, sizeof(si->nchstats)); 616 } 617 618 size = sizeof(si->uvmexp); 619 if (sysctl(uvmexp_mib, 2, &si->uvmexp, &size, NULL, 0) < 0) { 620 error("Can't get VM_UVMEXP: %s\n", strerror(errno)); 621 memset(&si->uvmexp, 0, sizeof(si->uvmexp)); 622 } 623 624 size = sizeof(si->Total); 625 if (sysctl(vmtotal_mib, 2, &si->Total, &size, NULL, 0) < 0) { 626 error("Can't get VM_METER: %s\n", strerror(errno)); 627 memset(&si->Total, 0, sizeof(si->Total)); 628 } 629 } 630 631 static void 632 allocinfo(struct Info *si) 633 { 634 memset(si, 0, sizeof(*si)); 635 si->intrcnt = calloc(nintr, sizeof(*si->intrcnt)); 636 if (si->intrcnt == NULL) 637 errx(2, "out of memory"); 638 } 639 640 static void 641 copyinfo(struct Info *from, struct Info *to) 642 { 643 uint64_t *intrcnt; 644 645 intrcnt = to->intrcnt; 646 *to = *from; 647 memcpy(to->intrcnt = intrcnt, from->intrcnt, nintr * sizeof(*intrcnt)); 648 } 649 650 static void 651 dinfo(int dn, int c) 652 { 653 double words, atime; 654 655 c += DISKCOL; 656 657 /* time busy in disk activity */ 658 atime = (double)cur.dk_time[dn].tv_sec + 659 ((double)cur.dk_time[dn].tv_usec / (double)1000000); 660 661 /* # of K transferred */ 662 words = (cur.dk_rbytes[dn] + cur.dk_wbytes[dn]) / 1024.0; 663 664 putint((int)((float)cur.dk_seek[dn]/etime+0.5), DISKROW + 1, c, 5); 665 putint((int)((float)(cur.dk_rxfer[dn] + cur.dk_wxfer[dn])/etime+0.5), 666 DISKROW + 2, c, 5); 667 putintmk((int)(words/etime + 0.5), DISKROW + 3, c, 5); 668 putfloat(atime/etime, DISKROW + 4, c, 5, 1, 1); 669 } 670 671 672 673 int 674 select_vm(void) 675 { 676 num_disp = 0; 677 return (0); 678 } 679 680 int 681 read_vm(void) 682 { 683 if (state == TIME) 684 copyinfo(&s3, &s1); 685 fetchkre(); 686 fetchifstat(); 687 if (state == TIME) 688 dkswap(); 689 num_disp = 0; 690 return 0; 691 } 692 693 694 void 695 print_vm(void) 696 { 697 copyinfo(&s3, &s); 698 labelkre(); 699 showkre(); 700 } 701