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