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