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 63static 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 72static int ncpu; 73 74extern 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 82static enum state { BOOT, TIME, RUN } state = TIME; 83 84static void allocinfo(struct Info *); 85static void copyinfo(struct Info *, struct Info *); 86static float cputime(int); 87static void dinfo(int, int, double); 88static void getinfo(struct Info *); 89void putint(int, int, int, int); 90void putintmk(int, int, int, int); 91void putuint64(u_int64_t, int, int, int); 92void putfloat(double, int, int, int, int, int); 93int ucount(void); 94 95void print_vm(void); 96int read_vm(void); 97int select_vm(void); 98int vm_keyboard_callback(int); 99 100static time_t t; 101static int nintr; 102static long *intrloc; 103static char **intrname; 104static int ipktsrow; 105 106WINDOW * 107openkre(void) 108{ 109 return (subwin(stdscr, LINES-1-1, 0, 1, 0)); 110} 111 112void 113closekre(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 150field_def *view_vm_0[] = { 151 NULL 152}; 153 154/* Define view managers */ 155struct view_manager vmstat_mgr = { 156 "VMstat", select_vm, read_vm, NULL, print_header, 157 print_vm, vm_keyboard_callback, NULL, NULL 158}; 159 160field_view views_vm[] = { 161 {view_vm_0, "vmstat", '7', &vmstat_mgr}, 162 {NULL, NULL, 0, NULL} 163}; 164 165int 166initvmstat(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 224void 225fetchkre(void) 226{ 227 getinfo(&s3); 228} 229 230void 231labelkre(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 325static char cpuchar[] = { '|', '@', '=', '>', ' ' }; 326static char cpuorder[] = { CP_INTR, CP_SPIN, CP_SYS, CP_USER, CP_IDLE }; 327 328void 329showkre(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 469int 470vm_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 493static float 494cputime(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 507void 508putint(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 527void 528putintmk(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 552void 553putuint64(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 572void 573putfloat(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 592static void 593getinfo(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 649static void 650allocinfo(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 658static void 659copyinfo(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 668static void 669dinfo(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 691int 692select_vm(void) 693{ 694 num_disp = 0; 695 return (0); 696} 697 698int 699read_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 712void 713print_vm(void) 714{ 715 copyinfo(&s3, &s); 716 labelkre(); 717 showkre(); 718} 719