1 /* $OpenBSD: vmstat.c,v 1.72 2009/10/27 23:59:44 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 /* 34 * Cursed vmstat -- from Robert Elz. 35 */ 36 37 #include <sys/param.h> 38 #include <sys/dkstat.h> 39 #include <sys/buf.h> 40 #include <sys/stat.h> 41 #include <sys/time.h> 42 #include <sys/user.h> 43 #include <sys/proc.h> 44 #include <sys/namei.h> 45 #include <sys/sysctl.h> 46 47 #include <uvm/uvm_extern.h> 48 49 #include <ctype.h> 50 #include <err.h> 51 #include <paths.h> 52 #include <signal.h> 53 #include <stdlib.h> 54 #include <string.h> 55 #include <unistd.h> 56 57 #include "systat.h" 58 59 static struct Info { 60 long time[CPUSTATES]; 61 struct uvmexp uvmexp; 62 struct vmtotal Total; 63 struct nchstats nchstats; 64 long nchcount; 65 u_quad_t *intrcnt; 66 } s, s1, s2, s3, z; 67 68 #include "dkstats.h" 69 extern struct _disk cur; 70 71 #define cnt s.Cnt 72 #define oldcnt s1.Cnt 73 #define total s.Total 74 #define nchtotal s.nchstats 75 #define oldnchtotal s1.nchstats 76 77 static enum state { BOOT, TIME, RUN } state = TIME; 78 79 static void allocinfo(struct Info *); 80 static void copyinfo(struct Info *, struct Info *); 81 static float cputime(int); 82 static void dinfo(int, int); 83 static void getinfo(struct Info *); 84 void putint(int, int, int, int); 85 void putintmk(int, int, int, int); 86 void putuint64(u_int64_t, int, int, int); 87 void putfloat(double, int, int, int, int, int); 88 int ucount(void); 89 90 void print_vm(void); 91 int read_vm(void); 92 int select_vm(void); 93 int vm_keyboard_callback(int); 94 95 static time_t t; 96 static double etime; 97 static float hertz; 98 static int nintr; 99 static long *intrloc; 100 static char **intrname; 101 static int nextintsrow; 102 103 WINDOW * 104 openkre(void) 105 { 106 return (subwin(stdscr, LINES-1-1, 0, 1, 0)); 107 } 108 109 void 110 closekre(WINDOW *w) 111 { 112 113 if (w == NULL) 114 return; 115 wclear(w); 116 wrefresh(w); 117 delwin(w); 118 } 119 120 /* 121 * These constants define where the major pieces are laid out 122 */ 123 #define STATROW 0 /* uses 1 row and 68 cols */ 124 #define STATCOL 2 125 #define MEMROW 2 /* uses 4 rows and 34 cols */ 126 #define MEMCOL 0 127 #define PAGEROW 2 /* uses 4 rows and 26 cols */ 128 #define PAGECOL 37 129 #define INTSROW 2 /* uses all rows to bottom and 17 cols */ 130 #define INTSCOL 63 131 #define PROCSROW 7 /* uses 2 rows and 20 cols */ 132 #define PROCSCOL 0 133 #define GENSTATROW 7 /* uses 2 rows and 35 cols */ 134 #define GENSTATCOL 16 135 #define VMSTATROW 7 /* uses 18 rows and 12 cols */ 136 #define VMSTATCOL 48 137 #define GRAPHROW 10 /* uses 3 rows and 51 cols */ 138 #define GRAPHCOL 0 139 #define NAMEIROW 14 /* uses 3 rows and 49 cols */ 140 #define NAMEICOL 0 141 #define DISKROW 18 /* uses 5 rows and 50 cols (for 9 drives) */ 142 #define DISKCOL 0 143 144 #define DRIVESPACE 45 /* max space for drives */ 145 146 147 field_def *view_vm_0[] = { 148 NULL 149 }; 150 151 /* Define view managers */ 152 struct view_manager vmstat_mgr = { 153 "VMstat", select_vm, read_vm, NULL, print_header, 154 print_vm, vm_keyboard_callback, NULL, NULL 155 }; 156 157 field_view views_vm[] = { 158 {view_vm_0, "vmstat", '7', &vmstat_mgr}, 159 {NULL, NULL, 0, NULL} 160 }; 161 162 int ncpu = 1; 163 164 int 165 initvmstat(void) 166 { 167 field_view *v; 168 int mib[4], i; 169 size_t size; 170 171 mib[0] = CTL_HW; 172 mib[1] = HW_NCPU; 173 size = sizeof(ncpu); 174 if (sysctl(mib, 2, &ncpu, &size, NULL, 0) < 0) 175 return (-1); 176 177 hertz = stathz ? stathz : hz; 178 if (!dkinit(1)) 179 return(0); 180 181 mib[0] = CTL_KERN; 182 mib[1] = KERN_INTRCNT; 183 mib[2] = KERN_INTRCNT_NUM; 184 size = sizeof(nintr); 185 if (sysctl(mib, 3, &nintr, &size, NULL, 0) < 0) 186 return (-1); 187 188 intrloc = calloc(nintr, sizeof(long)); 189 intrname = calloc(nintr, sizeof(char *)); 190 191 for (i = 0; i < nintr; i++) { 192 char name[128]; 193 194 mib[0] = CTL_KERN; 195 mib[1] = KERN_INTRCNT; 196 mib[2] = KERN_INTRCNT_NAME; 197 mib[3] = i; 198 size = sizeof(name); 199 if (sysctl(mib, 4, name, &size, NULL, 0) < 0) 200 return (-1); 201 202 intrname[i] = strdup(name); 203 if (intrname[i] == NULL) 204 return (-1); 205 } 206 207 nextintsrow = INTSROW + 2; 208 allocinfo(&s); 209 allocinfo(&s1); 210 allocinfo(&s2); 211 allocinfo(&s3); 212 allocinfo(&z); 213 214 getinfo(&s2); 215 copyinfo(&z, &s1); 216 217 for (v = views_vm; v->name != NULL; v++) 218 add_view(v); 219 220 return(1); 221 } 222 223 void 224 fetchkre(void) 225 { 226 getinfo(&s3); 227 } 228 229 void 230 labelkre(void) 231 { 232 int i, j, l; 233 234 mvprintw(MEMROW, MEMCOL, " memory totals (in KB)"); 235 mvprintw(MEMROW + 1, MEMCOL, " real virtual free"); 236 mvprintw(MEMROW + 2, MEMCOL, "Active"); 237 mvprintw(MEMROW + 3, MEMCOL, "All"); 238 239 mvprintw(PAGEROW, PAGECOL, " PAGING SWAPPING "); 240 mvprintw(PAGEROW + 1, PAGECOL, " in out in out "); 241 mvprintw(PAGEROW + 2, PAGECOL, "ops"); 242 mvprintw(PAGEROW + 3, PAGECOL, "pages"); 243 244 mvprintw(INTSROW, INTSCOL + 3, " Interrupts"); 245 mvprintw(INTSROW + 1, INTSCOL + 9, "total"); 246 247 mvprintw(LINES - 3, INTSCOL + 9, "IPKTS"); 248 mvprintw(LINES - 2, INTSCOL + 9, "OPKTS"); 249 250 mvprintw(VMSTATROW + 0, VMSTATCOL + 10, "forks"); 251 mvprintw(VMSTATROW + 1, VMSTATCOL + 10, "fkppw"); 252 mvprintw(VMSTATROW + 2, VMSTATCOL + 10, "fksvm"); 253 mvprintw(VMSTATROW + 3, VMSTATCOL + 10, "pwait"); 254 mvprintw(VMSTATROW + 4, VMSTATCOL + 10, "relck"); 255 mvprintw(VMSTATROW + 5, VMSTATCOL + 10, "rlkok"); 256 mvprintw(VMSTATROW + 6, VMSTATCOL + 10, "noram"); 257 mvprintw(VMSTATROW + 7, VMSTATCOL + 10, "ndcpy"); 258 mvprintw(VMSTATROW + 8, VMSTATCOL + 10, "fltcp"); 259 mvprintw(VMSTATROW + 9, VMSTATCOL + 10, "zfod"); 260 mvprintw(VMSTATROW + 10, VMSTATCOL + 10, "cow"); 261 mvprintw(VMSTATROW + 11, VMSTATCOL + 10, "fmin"); 262 mvprintw(VMSTATROW + 12, VMSTATCOL + 10, "ftarg"); 263 mvprintw(VMSTATROW + 13, VMSTATCOL + 10, "itarg"); 264 mvprintw(VMSTATROW + 14, VMSTATCOL + 10, "wired"); 265 mvprintw(VMSTATROW + 15, VMSTATCOL + 10, "pdfre"); 266 if (LINES - 1 > VMSTATROW + 16) 267 mvprintw(VMSTATROW + 16, VMSTATCOL + 10, "pdscn"); 268 if (LINES - 1 > VMSTATROW + 17) 269 mvprintw(VMSTATROW + 17, VMSTATCOL + 10, "pzidle"); 270 if (LINES - 1 > VMSTATROW + 18) 271 mvprintw(VMSTATROW + 18, VMSTATCOL + 10, "kmapent"); 272 273 mvprintw(GENSTATROW, GENSTATCOL, " Csw Trp Sys Int Sof Flt"); 274 275 mvprintw(GRAPHROW, GRAPHCOL, 276 " . %%Int . %%Sys . %%Usr . %%Nic . %%Idle"); 277 mvprintw(PROCSROW, PROCSCOL, "Proc:r d s w"); 278 mvprintw(GRAPHROW + 1, GRAPHCOL, 279 "| | | | | | | | | | |"); 280 281 mvprintw(NAMEIROW, NAMEICOL, 282 "Namei Sys-cache Proc-cache No-cache"); 283 mvprintw(NAMEIROW + 1, NAMEICOL, 284 " Calls hits %% hits %% miss %%"); 285 mvprintw(DISKROW, DISKCOL, "Disks"); 286 mvprintw(DISKROW + 1, DISKCOL, "seeks"); 287 mvprintw(DISKROW + 2, DISKCOL, "xfers"); 288 mvprintw(DISKROW + 3, DISKCOL, "speed"); 289 mvprintw(DISKROW + 4, DISKCOL, " sec"); 290 for (i = 0, j = 0; i < cur.dk_ndrive && j < DRIVESPACE; i++) 291 if (cur.dk_select[i] && (j + strlen(dr_name[i])) < DRIVESPACE) { 292 l = MAX(5, strlen(dr_name[i])); 293 mvprintw(DISKROW, DISKCOL + 5 + j, 294 " %*s", l, dr_name[i]); 295 j += 1 + l; 296 } 297 for (i = 0; i < nintr; i++) { 298 if (intrloc[i] == 0) 299 continue; 300 mvprintw(intrloc[i], INTSCOL + 9, "%-8.8s", intrname[i]); 301 } 302 } 303 304 #define X(fld) {s.fld[i]; s.fld[i]-=s1.fld[i];} 305 #define Y(fld) {s.fld; s.fld -= s1.fld;} 306 #define Z(fld) {s.nchstats.fld; s.nchstats.fld -= s1.nchstats.fld;} 307 #define PUTRATE(fld, l, c, w) \ 308 do { \ 309 Y(fld); \ 310 putint((int)((float)s.fld/etime + 0.5), l, c, w); \ 311 } while (0) 312 #define MAXFAIL 5 313 314 static char cpuchar[CPUSTATES] = { '|', '=', '>', '-', ' ' }; 315 static char cpuorder[CPUSTATES] = { CP_INTR, CP_SYS, CP_USER, CP_NICE, CP_IDLE }; 316 317 void 318 showkre(void) 319 { 320 float f1, f2; 321 int psiz; 322 u_int64_t inttotal, intcnt; 323 int i, l, c; 324 static int failcnt = 0, first_run = 0; 325 326 if (state == TIME) { 327 if (!first_run) { 328 first_run = 1; 329 return; 330 } 331 } 332 etime = 0; 333 for (i = 0; i < CPUSTATES; i++) { 334 X(time); 335 etime += s.time[i]; 336 } 337 if (etime < 5.0) { /* < 5 ticks - ignore this trash */ 338 if (failcnt++ >= MAXFAIL) { 339 error("The alternate system clock has died!"); 340 failcnt = 0; 341 } 342 return; 343 } 344 failcnt = 0; 345 etime /= hertz; 346 etime /= ncpu; 347 inttotal = 0; 348 for (i = 0; i < nintr; i++) { 349 if (s.intrcnt[i] == 0) 350 continue; 351 if (intrloc[i] == 0) { 352 if (nextintsrow == LINES) 353 continue; 354 intrloc[i] = nextintsrow++; 355 mvprintw(intrloc[i], INTSCOL + 9, "%-8.8s", 356 intrname[i]); 357 } 358 t = intcnt = s.intrcnt[i]; 359 s.intrcnt[i] -= s1.intrcnt[i]; 360 intcnt = (u_int64_t)((float)s.intrcnt[i]/etime + 0.5); 361 inttotal += intcnt; 362 putuint64(intcnt, intrloc[i], INTSCOL, 8); 363 } 364 putuint64(inttotal, INTSROW + 1, INTSCOL, 8); 365 Z(ncs_goodhits); Z(ncs_badhits); Z(ncs_miss); 366 Z(ncs_long); Z(ncs_pass2); Z(ncs_2passes); 367 s.nchcount = nchtotal.ncs_goodhits + nchtotal.ncs_badhits + 368 nchtotal.ncs_miss + nchtotal.ncs_long; 369 370 putint(sum.ifc_ip, LINES - 3, INTSCOL, 8); 371 putint(sum.ifc_op, LINES - 2, INTSCOL, 8); 372 373 psiz = 0; 374 f2 = 0.0; 375 376 for (c = 0; c < CPUSTATES; c++) { 377 i = cpuorder[c]; 378 f1 = cputime(i); 379 f2 += f1; 380 l = (int) ((f2 + 1.0) / 2.0) - psiz; 381 putfloat(f1, GRAPHROW, GRAPHCOL + 1 + (10 * c), 5, 1, 0); 382 move(GRAPHROW + 2, psiz); 383 psiz += l; 384 while (l-- > 0) 385 addch(cpuchar[c]); 386 } 387 388 #define pgtokb(pg) ((pg) * (s.uvmexp.pagesize / 1024)) 389 390 putint(pgtokb(s.uvmexp.active), MEMROW + 2, MEMCOL + 7, 8); 391 putint(pgtokb(s.uvmexp.active + s.uvmexp.swpginuse), /* XXX */ 392 MEMROW + 2, MEMCOL + 17, 8); 393 putint(pgtokb(s.uvmexp.npages - s.uvmexp.free), MEMROW + 3, MEMCOL + 7, 8); 394 putint(pgtokb(s.uvmexp.npages - s.uvmexp.free + s.uvmexp.swpginuse), 395 MEMROW + 3, MEMCOL + 17, 8); 396 putint(pgtokb(s.uvmexp.free), MEMROW + 2, MEMCOL + 26, 8); 397 putint(pgtokb(s.uvmexp.free + s.uvmexp.swpages - s.uvmexp.swpginuse), 398 MEMROW + 3, MEMCOL + 26, 8); 399 putint(total.t_rq - 1, PROCSROW + 1, PROCSCOL + 3, 3); 400 401 putint(total.t_dw, PROCSROW + 1, PROCSCOL + 6, 3); 402 putint(total.t_sl, PROCSROW + 1, PROCSCOL + 9, 3); 403 putint(total.t_sw, PROCSROW + 1, PROCSCOL + 12, 3); 404 PUTRATE(uvmexp.forks, VMSTATROW + 0, VMSTATCOL + 3, 6); 405 PUTRATE(uvmexp.forks_ppwait, VMSTATROW + 1, VMSTATCOL + 3, 6); 406 PUTRATE(uvmexp.forks_sharevm, VMSTATROW + 2, VMSTATCOL + 3, 6); 407 PUTRATE(uvmexp.fltpgwait, VMSTATROW + 3, VMSTATCOL + 4, 5); 408 PUTRATE(uvmexp.fltrelck, VMSTATROW + 4, VMSTATCOL + 3, 6); 409 PUTRATE(uvmexp.fltrelckok, VMSTATROW + 5, VMSTATCOL + 3, 6); 410 PUTRATE(uvmexp.fltnoram, VMSTATROW + 6, VMSTATCOL + 3, 6); 411 PUTRATE(uvmexp.fltamcopy, VMSTATROW + 7, VMSTATCOL + 3, 6); 412 PUTRATE(uvmexp.flt_prcopy, VMSTATROW + 8, VMSTATCOL + 3, 6); 413 PUTRATE(uvmexp.flt_przero, VMSTATROW + 9, VMSTATCOL + 3, 6); 414 PUTRATE(uvmexp.flt_acow, VMSTATROW + 10, VMSTATCOL, 9); 415 putint(s.uvmexp.freemin, VMSTATROW + 11, VMSTATCOL, 9); 416 putint(s.uvmexp.freetarg, VMSTATROW + 12, VMSTATCOL, 9); 417 putint(s.uvmexp.inactarg, VMSTATROW + 13, VMSTATCOL, 9); 418 putint(s.uvmexp.wired, VMSTATROW + 14, VMSTATCOL, 9); 419 PUTRATE(uvmexp.pdfreed, VMSTATROW + 15, VMSTATCOL, 9); 420 if (LINES - 1 > VMSTATROW + 16) 421 PUTRATE(uvmexp.pdscans, VMSTATROW + 16, VMSTATCOL, 9); 422 if (LINES - 1 > VMSTATROW + 17) 423 PUTRATE(uvmexp.zeropages, VMSTATROW + 17, VMSTATCOL, 9); 424 if (LINES - 1 > VMSTATROW + 18) 425 putint(s.uvmexp.kmapent, VMSTATROW + 18, VMSTATCOL, 9); 426 427 PUTRATE(uvmexp.pageins, PAGEROW + 2, PAGECOL + 5, 5); 428 PUTRATE(uvmexp.pdpageouts, PAGEROW + 2, PAGECOL + 10, 5); 429 PUTRATE(uvmexp.swapins, PAGEROW + 2, PAGECOL + 15, 5); 430 PUTRATE(uvmexp.swapouts, PAGEROW + 2, PAGECOL + 20, 5); 431 PUTRATE(uvmexp.pgswapin, PAGEROW + 3, PAGECOL + 5, 5); 432 PUTRATE(uvmexp.pgswapout, PAGEROW + 3, PAGECOL + 10, 5); 433 434 PUTRATE(uvmexp.swtch, GENSTATROW + 1, GENSTATCOL, 6); 435 PUTRATE(uvmexp.traps, GENSTATROW + 1, GENSTATCOL + 6, 6); 436 PUTRATE(uvmexp.syscalls, GENSTATROW + 1, GENSTATCOL + 12, 6); 437 PUTRATE(uvmexp.intrs, GENSTATROW + 1, GENSTATCOL + 18, 6); 438 PUTRATE(uvmexp.softs, GENSTATROW + 1, GENSTATCOL + 24, 6); 439 PUTRATE(uvmexp.faults, GENSTATROW + 1, GENSTATCOL + 30, 5); 440 mvprintw(DISKROW, DISKCOL + 5, " "); 441 for (i = 0, c = 0; i < cur.dk_ndrive && c < DRIVESPACE; i++) 442 if (cur.dk_select[i] && (c + strlen(dr_name[i])) < DRIVESPACE) { 443 l = MAX(5, strlen(dr_name[i])); 444 mvprintw(DISKROW, DISKCOL + 5 + c, 445 " %*s", l, dr_name[i]); 446 c += 1 + l; 447 dinfo(i, c); 448 } 449 /* and pad the DRIVESPACE */ 450 l = DRIVESPACE - c; 451 for (i = 0; i < 5; i++) 452 mvprintw(DISKROW + i, DISKCOL + 5 + c, "%*s", l, ""); 453 454 putint(s.nchcount, NAMEIROW + 2, NAMEICOL, 9); 455 putint(nchtotal.ncs_goodhits, NAMEIROW + 2, NAMEICOL + 10, 8); 456 #define nz(x) ((x) ? (x) : 1) 457 putfloat(nchtotal.ncs_goodhits * 100.0 / nz(s.nchcount), 458 NAMEIROW + 2, NAMEICOL + 19, 4, 0, 1); 459 putint(nchtotal.ncs_pass2, NAMEIROW + 2, NAMEICOL + 24, 7); 460 putfloat(nchtotal.ncs_pass2 * 100.0 / nz(s.nchcount), 461 NAMEIROW + 2, NAMEICOL + 33, 4, 0, 1); 462 putint(nchtotal.ncs_miss + nchtotal.ncs_long - nchtotal.ncs_pass2, 463 NAMEIROW + 2, NAMEICOL + 38, 7); 464 putfloat((nchtotal.ncs_miss + nchtotal.ncs_long - nchtotal.ncs_pass2) * 465 100.0 / nz(s.nchcount), NAMEIROW + 2, NAMEICOL + 45, 4, 0, 1); 466 #undef nz 467 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 > 9999 * 1024) 540 snprintf(b, sizeof b, "%*dG", w - 1, n / 1024 / 1024); 541 else if (n > 9999) 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 fetchifstat(); 697 if (state == TIME) 698 dkswap(); 699 num_disp = 0; 700 return 0; 701 } 702 703 704 void 705 print_vm(void) 706 { 707 copyinfo(&s3, &s); 708 labelkre(); 709 showkre(); 710 } 711