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