1 /* $OpenBSD: vmstat.c,v 1.96 2022/12/28 20:49:05 cheloha 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/types.h> 38 #include <sys/namei.h> 39 #include <sys/signal.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 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) 62 63 static struct Info { 64 struct cpustats cpustats; 65 struct uvmexp uvmexp; 66 struct vmtotal Total; 67 struct nchstats nchstats; 68 long nchcount; 69 uint64_t *intrcnt; 70 } s, s1, s2, s3, z; 71 72 static int ncpu; 73 74 extern struct _disk cur; 75 76 #define cnt s.Cnt 77 #define oldcnt s1.Cnt 78 #define total s.Total 79 #define nchtotal s.nchstats 80 #define oldnchtotal s1.nchstats 81 82 static enum state { BOOT, TIME, RUN } state = TIME; 83 84 static void allocinfo(struct Info *); 85 static void copyinfo(struct Info *, struct Info *); 86 static float cputime(int); 87 static void dinfo(int, int, double); 88 static void getinfo(struct Info *); 89 void putint(int, int, int, int); 90 void putintmk(int, int, int, int); 91 void putuint64(u_int64_t, int, int, int); 92 void putfloat(double, int, int, int, int, int); 93 int ucount(void); 94 95 void print_vm(void); 96 int read_vm(void); 97 int select_vm(void); 98 int vm_keyboard_callback(int); 99 100 static time_t t; 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 if (!dkinit(1)) 173 return(0); 174 175 mib[0] = CTL_HW; 176 mib[1] = HW_NCPU; 177 size = sizeof(ncpu); 178 if (sysctl(mib, 2, &ncpu, &size, NULL, 0) == -1) 179 return (-1); 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) == -1) 186 return (-1); 187 188 intrloc = calloc(nintr, sizeof(long)); 189 intrname = calloc(nintr, sizeof(char *)); 190 if (intrloc == NULL || intrname == NULL) 191 err(2, NULL); 192 193 for (i = 0; i < nintr; i++) { 194 char name[128]; 195 196 mib[0] = CTL_KERN; 197 mib[1] = KERN_INTRCNT; 198 mib[2] = KERN_INTRCNT_NAME; 199 mib[3] = i; 200 size = sizeof(name); 201 if (sysctl(mib, 4, name, &size, NULL, 0) == -1) 202 return (-1); 203 204 intrname[i] = strdup(name); 205 if (intrname[i] == NULL) 206 return (-1); 207 } 208 209 allocinfo(&s); 210 allocinfo(&s1); 211 allocinfo(&s2); 212 allocinfo(&s3); 213 allocinfo(&z); 214 215 getinfo(&s2); 216 copyinfo(&z, &s1); 217 218 for (v = views_vm; v->name != NULL; v++) 219 add_view(v); 220 221 return(1); 222 } 223 224 void 225 fetchkre(void) 226 { 227 getinfo(&s3); 228 } 229 230 void 231 labelkre(void) 232 { 233 int i, j, l; 234 235 mvprintw(MEMROW, MEMCOL, " memory totals (in KB)"); 236 mvprintw(MEMROW + 1, MEMCOL, " real virtual free"); 237 mvprintw(MEMROW + 2, MEMCOL, "Active"); 238 mvprintw(MEMROW + 3, MEMCOL, "All"); 239 240 mvprintw(PAGEROW, PAGECOL, " PAGING SWAPPING "); 241 mvprintw(PAGEROW + 1, PAGECOL, " in out in out "); 242 mvprintw(PAGEROW + 2, PAGECOL, "ops"); 243 mvprintw(PAGEROW + 3, PAGECOL, "pages"); 244 245 mvprintw(INTSROW, INTSCOL + 3, " Interrupts"); 246 mvprintw(INTSROW + 1, INTSCOL + 9, "total"); 247 248 j = INTSROW + 2; 249 for (i = 0; i < nintr; i++) { 250 intrloc[i] = 0; 251 if (s.intrcnt[i] == 0 || ipktsrow == LINES) 252 continue; 253 intrloc[i] = j++; 254 mvprintw(intrloc[i], INTSCOL + 9, "%-8.8s", intrname[i]); 255 } 256 ipktsrow = MAXIMUM(j, MINIMUM(LINES - 3, VMSTATROW + 17)); 257 if (LINES - 1 > ipktsrow) 258 mvprintw(ipktsrow, INTSCOL + 9, "IPKTS"); 259 if (LINES - 1 > ipktsrow + 1) 260 mvprintw(ipktsrow + 1, INTSCOL + 9, "OPKTS"); 261 262 mvprintw(VMSTATROW + 0, VMSTATCOL + 10, "forks"); 263 mvprintw(VMSTATROW + 1, VMSTATCOL + 10, "fkppw"); 264 mvprintw(VMSTATROW + 2, VMSTATCOL + 10, "fksvm"); 265 mvprintw(VMSTATROW + 3, VMSTATCOL + 10, "pwait"); 266 mvprintw(VMSTATROW + 4, VMSTATCOL + 10, "relck"); 267 mvprintw(VMSTATROW + 5, VMSTATCOL + 10, "rlkok"); 268 mvprintw(VMSTATROW + 6, VMSTATCOL + 10, "noram"); 269 mvprintw(VMSTATROW + 7, VMSTATCOL + 10, "ndcpy"); 270 mvprintw(VMSTATROW + 8, VMSTATCOL + 10, "fltcp"); 271 mvprintw(VMSTATROW + 9, VMSTATCOL + 10, "zfod"); 272 mvprintw(VMSTATROW + 10, VMSTATCOL + 10, "cow"); 273 mvprintw(VMSTATROW + 11, VMSTATCOL + 10, "fmin"); 274 mvprintw(VMSTATROW + 12, VMSTATCOL + 10, "ftarg"); 275 mvprintw(VMSTATROW + 13, VMSTATCOL + 10, "itarg"); 276 mvprintw(VMSTATROW + 14, VMSTATCOL + 10, "wired"); 277 mvprintw(VMSTATROW + 15, VMSTATCOL + 10, "pdfre"); 278 if (LINES - 1 > VMSTATROW + 16) 279 mvprintw(VMSTATROW + 16, VMSTATCOL + 10, "pdscn"); 280 if (LINES - 1 > VMSTATROW + 17) 281 mvprintw(VMSTATROW + 17, VMSTATCOL + 10, "pzidl"); 282 if (LINES - 1 > VMSTATROW + 18) 283 mvprintw(VMSTATROW + 18, VMSTATCOL + 10, "kmape"); 284 285 mvprintw(GENSTATROW, GENSTATCOL, " Csw Trp Sys Int Sof Flt"); 286 287 mvprintw(GRAPHROW, GRAPHCOL, 288 " . %%Int . %%Spn . %%Sys . %%Usr . %%Idle"); 289 mvprintw(PROCSROW, PROCSCOL, "Proc:r d s w"); 290 mvprintw(GRAPHROW + 1, GRAPHCOL, 291 "| | | | | | | | | | |"); 292 293 mvprintw(NAMEIROW, NAMEICOL, 294 "Namei Sys-cache Proc-cache No-cache"); 295 mvprintw(NAMEIROW + 1, NAMEICOL, 296 " Calls hits %% hits %% miss %%"); 297 mvprintw(DISKROW, DISKCOL, "Disks"); 298 mvprintw(DISKROW + 1, DISKCOL, "seeks"); 299 mvprintw(DISKROW + 2, DISKCOL, "xfers"); 300 mvprintw(DISKROW + 3, DISKCOL, "speed"); 301 mvprintw(DISKROW + 4, DISKCOL, " sec"); 302 for (i = 0, j = 0; i < cur.dk_ndrive && j < DRIVESPACE; i++) 303 if (cur.dk_select[i] && (j + strlen(dr_name[i])) < DRIVESPACE) { 304 l = MAXIMUM(5, strlen(dr_name[i])); 305 mvprintw(DISKROW, DISKCOL + 5 + j, 306 " %*s", l, dr_name[i]); 307 j += 1 + l; 308 } 309 for (i = 0; i < nintr; i++) { 310 if (intrloc[i] == 0) 311 continue; 312 mvprintw(intrloc[i], INTSCOL + 9, "%-8.8s", intrname[i]); 313 } 314 } 315 316 #define X(fld) {s.fld[i]-=s1.fld[i];} 317 #define Y(fld) {s.fld -= s1.fld;} 318 #define Z(fld) {s.nchstats.fld -= s1.nchstats.fld;} 319 #define PUTRATE(fld, l, c, w) \ 320 do { \ 321 Y(fld); \ 322 putint((int)((float)s.fld/etime + 0.5), l, c, w); \ 323 } while (0) 324 325 static char cpuchar[] = { '|', '@', '=', '>', ' ' }; 326 static char cpuorder[] = { CP_INTR, CP_SPIN, CP_SYS, CP_USER, CP_IDLE }; 327 328 void 329 showkre(void) 330 { 331 static struct timespec prev; 332 struct timespec elapsed, now; 333 float f1, f2; 334 int psiz; 335 u_int64_t inttotal, intcnt; 336 int i, l, c; 337 static int first_run = 0; 338 double etime; 339 340 clock_gettime(CLOCK_UPTIME, &now); 341 timespecsub(&now, &prev, &elapsed); 342 prev = now; 343 if (state == TIME) { 344 if (!first_run) { 345 first_run = 1; 346 return; 347 } 348 } 349 etime = elapsed.tv_sec + elapsed.tv_nsec / 1000000000.0; 350 for (i = 0; i < CPUSTATES; i++) 351 X(cpustats.cs_time); 352 inttotal = 0; 353 for (i = 0; i < nintr; i++) { 354 t = intcnt = s.intrcnt[i]; 355 s.intrcnt[i] -= s1.intrcnt[i]; 356 intcnt = (u_int64_t)((float)s.intrcnt[i]/etime + 0.5); 357 inttotal += intcnt; 358 if (intrloc[i] != 0) 359 putuint64(intcnt, intrloc[i], INTSCOL, 8); 360 } 361 putuint64(inttotal, INTSROW + 1, INTSCOL, 8); 362 Z(ncs_goodhits); Z(ncs_badhits); Z(ncs_miss); 363 Z(ncs_long); Z(ncs_pass2); Z(ncs_2passes); 364 s.nchcount = nchtotal.ncs_goodhits + nchtotal.ncs_badhits + 365 nchtotal.ncs_miss + nchtotal.ncs_long; 366 367 if (LINES - 1 > ipktsrow) 368 putint(sum.ifc_ip, ipktsrow, INTSCOL, 8); 369 if (LINES - 1 > ipktsrow + 1) 370 putint(sum.ifc_op, ipktsrow + 1, INTSCOL, 8); 371 372 psiz = 0; 373 f2 = 0.0; 374 375 for (c = 0; c < nitems(cpuorder); c++) { 376 i = cpuorder[c]; 377 f1 = cputime(i); 378 if (i == CP_USER) 379 f1 += cputime(CP_NICE); 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.pgswapin, PAGEROW + 3, PAGECOL + 5, 5); 431 PUTRATE(uvmexp.pgswapout, PAGEROW + 3, PAGECOL + 10, 5); 432 433 PUTRATE(uvmexp.swtch, GENSTATROW + 1, GENSTATCOL, 6); 434 PUTRATE(uvmexp.traps, GENSTATROW + 1, GENSTATCOL + 6, 6); 435 PUTRATE(uvmexp.syscalls, GENSTATROW + 1, GENSTATCOL + 12, 6); 436 PUTRATE(uvmexp.intrs, GENSTATROW + 1, GENSTATCOL + 18, 6); 437 PUTRATE(uvmexp.softs, GENSTATROW + 1, GENSTATCOL + 24, 6); 438 PUTRATE(uvmexp.faults, GENSTATROW + 1, GENSTATCOL + 30, 5); 439 mvprintw(DISKROW, DISKCOL + 5, " "); 440 for (i = 0, c = 0; i < cur.dk_ndrive && c < DRIVESPACE; i++) 441 if (cur.dk_select[i] && (c + strlen(dr_name[i])) < DRIVESPACE) { 442 l = MAXIMUM(5, strlen(dr_name[i])); 443 mvprintw(DISKROW, DISKCOL + 5 + c, 444 " %*s", l, dr_name[i]); 445 c += 1 + l; 446 dinfo(i, c, etime); 447 } 448 /* and pad the DRIVESPACE */ 449 l = DRIVESPACE - c; 450 for (i = 0; i < 5; i++) 451 mvprintw(DISKROW + i, DISKCOL + 5 + c, "%*s", l, ""); 452 453 putint(s.nchcount, NAMEIROW + 2, NAMEICOL, 9); 454 putint(nchtotal.ncs_goodhits, NAMEIROW + 2, NAMEICOL + 10, 8); 455 #define nz(x) ((x) ? (x) : 1) 456 putfloat(nchtotal.ncs_goodhits * 100.0 / nz(s.nchcount), 457 NAMEIROW + 2, NAMEICOL + 19, 4, 0, 1); 458 putint(nchtotal.ncs_pass2, NAMEIROW + 2, NAMEICOL + 24, 7); 459 putfloat(nchtotal.ncs_pass2 * 100.0 / nz(s.nchcount), 460 NAMEIROW + 2, NAMEICOL + 33, 4, 0, 1); 461 putint(nchtotal.ncs_miss + nchtotal.ncs_long - nchtotal.ncs_pass2, 462 NAMEIROW + 2, NAMEICOL + 38, 7); 463 putfloat((nchtotal.ncs_miss + nchtotal.ncs_long - nchtotal.ncs_pass2) * 464 100.0 / nz(s.nchcount), NAMEIROW + 2, NAMEICOL + 45, 4, 0, 1); 465 #undef nz 466 467 } 468 469 int 470 vm_keyboard_callback(int ch) 471 { 472 switch(ch) { 473 case 'r': 474 copyinfo(&s2, &s1); 475 state = RUN; 476 break; 477 case 'b': 478 state = BOOT; 479 copyinfo(&z, &s1); 480 break; 481 case 't': 482 state = TIME; 483 break; 484 case 'z': 485 if (state == RUN) 486 getinfo(&s1); 487 break; 488 } 489 return (keyboard_callback(ch)); 490 } 491 492 493 static float 494 cputime(int indx) 495 { 496 double tm; 497 int i; 498 499 tm = 0; 500 for (i = 0; i < nitems(s.cpustats.cs_time); i++) 501 tm += s.cpustats.cs_time[i]; 502 if (tm == 0.0) 503 tm = 1.0; 504 return (s.cpustats.cs_time[indx] * 100.0 / tm); 505 } 506 507 void 508 putint(int n, int l, int c, int w) 509 { 510 char b[128]; 511 512 move(l, c); 513 if (n == 0) { 514 while (w-- > 0) 515 addch(' '); 516 return; 517 } 518 snprintf(b, sizeof b, "%*d", w, n); 519 if (strlen(b) > w) { 520 while (w-- > 0) 521 addch('*'); 522 return; 523 } 524 addstr(b); 525 } 526 527 void 528 putintmk(int n, int l, int c, int w) 529 { 530 char b[128]; 531 532 move(l, c); 533 if (n == 0) { 534 while (w-- > 0) 535 addch(' '); 536 return; 537 } 538 if (n > 9999 * 1024) 539 snprintf(b, sizeof b, "%*dG", w - 1, n / 1024 / 1024); 540 else if (n > 9999) 541 snprintf(b, sizeof b, "%*dM", w - 1, n / 1024); 542 else 543 snprintf(b, sizeof b, "%*dK", w - 1, n); 544 if (strlen(b) > w) { 545 while (w-- > 0) 546 addch('*'); 547 return; 548 } 549 addstr(b); 550 } 551 552 void 553 putuint64(u_int64_t n, int l, int c, int w) 554 { 555 char b[128]; 556 557 move(l, c); 558 if (n == 0) { 559 while (w-- > 0) 560 addch(' '); 561 return; 562 } 563 snprintf(b, sizeof b, "%*llu", w, n); 564 if (strlen(b) > w) { 565 while (w-- > 0) 566 addch('*'); 567 return; 568 } 569 addstr(b); 570 } 571 572 void 573 putfloat(double f, int l, int c, int w, int d, int nz) 574 { 575 char b[128]; 576 577 move(l, c); 578 if (nz && f == 0.0) { 579 while (--w >= 0) 580 addch(' '); 581 return; 582 } 583 snprintf(b, sizeof b, "%*.*f", w, d, f); 584 if (strlen(b) > w) { 585 while (--w >= 0) 586 addch('*'); 587 return; 588 } 589 addstr(b); 590 } 591 592 static void 593 getinfo(struct Info *si) 594 { 595 static int cpustats_mib[3] = { CTL_KERN, KERN_CPUSTATS, 0 }; 596 static int nchstats_mib[2] = { CTL_KERN, KERN_NCHSTATS }; 597 static int uvmexp_mib[2] = { CTL_VM, VM_UVMEXP }; 598 static int vmtotal_mib[2] = { CTL_VM, VM_METER }; 599 struct cpustats cs; 600 int mib[4], i, j; 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) == -1) { 612 si->intrcnt[i] = 0; 613 } 614 } 615 616 memset(&si->cpustats.cs_time, 0, sizeof(si->cpustats.cs_time)); 617 for (i = 0; i < ncpu; i++) { 618 cpustats_mib[2] = i; 619 size = sizeof(cs); 620 if (sysctl(cpustats_mib, 3, &cs, &size, NULL, 0) == -1) { 621 error("Can't get KERN_CPUSTATS: %s\n", strerror(errno)); 622 memset(&si->cpustats, 0, sizeof(si->cpustats)); 623 } 624 if ((cs.cs_flags & CPUSTATS_ONLINE) == 0) 625 continue; /* omit totals for offline CPUs */ 626 for (j = 0; j < nitems(cs.cs_time); j++) 627 si->cpustats.cs_time[j] += cs.cs_time[j]; 628 } 629 630 size = sizeof(si->nchstats); 631 if (sysctl(nchstats_mib, 2, &si->nchstats, &size, NULL, 0) == -1) { 632 error("Can't get KERN_NCHSTATS: %s\n", strerror(errno)); 633 memset(&si->nchstats, 0, sizeof(si->nchstats)); 634 } 635 636 size = sizeof(si->uvmexp); 637 if (sysctl(uvmexp_mib, 2, &si->uvmexp, &size, NULL, 0) == -1) { 638 error("Can't get VM_UVMEXP: %s\n", strerror(errno)); 639 memset(&si->uvmexp, 0, sizeof(si->uvmexp)); 640 } 641 642 size = sizeof(si->Total); 643 if (sysctl(vmtotal_mib, 2, &si->Total, &size, NULL, 0) == -1) { 644 error("Can't get VM_METER: %s\n", strerror(errno)); 645 memset(&si->Total, 0, sizeof(si->Total)); 646 } 647 } 648 649 static void 650 allocinfo(struct Info *si) 651 { 652 memset(si, 0, sizeof(*si)); 653 si->intrcnt = calloc(nintr, sizeof(*si->intrcnt)); 654 if (si->intrcnt == NULL) 655 err(2, NULL); 656 } 657 658 static void 659 copyinfo(struct Info *from, struct Info *to) 660 { 661 uint64_t *intrcnt; 662 663 intrcnt = to->intrcnt; 664 *to = *from; 665 memcpy(to->intrcnt = intrcnt, from->intrcnt, nintr * sizeof(*intrcnt)); 666 } 667 668 static void 669 dinfo(int dn, int c, double etime) 670 { 671 double words, atime; 672 673 c += DISKCOL; 674 675 /* time busy in disk activity */ 676 atime = (double)cur.dk_time[dn].tv_sec + 677 ((double)cur.dk_time[dn].tv_usec / (double)1000000); 678 679 /* # of K transferred */ 680 words = (cur.dk_rbytes[dn] + cur.dk_wbytes[dn]) / 1024.0; 681 682 putint((int)((float)cur.dk_seek[dn]/etime+0.5), DISKROW + 1, c, 5); 683 putint((int)((float)(cur.dk_rxfer[dn] + cur.dk_wxfer[dn])/etime+0.5), 684 DISKROW + 2, c, 5); 685 putintmk((int)(words/etime + 0.5), DISKROW + 3, c, 5); 686 putfloat(atime/etime, DISKROW + 4, c, 5, 1, 1); 687 } 688 689 690 691 int 692 select_vm(void) 693 { 694 num_disp = 0; 695 return (0); 696 } 697 698 int 699 read_vm(void) 700 { 701 if (state == TIME) 702 copyinfo(&s3, &s1); 703 fetchkre(); 704 fetchifstat(); 705 if (state == TIME) 706 dkswap(); 707 num_disp = 0; 708 return 0; 709 } 710 711 712 void 713 print_vm(void) 714 { 715 copyinfo(&s3, &s); 716 labelkre(); 717 showkre(); 718 } 719