1 /* 2 * Copyright (c) 1983, 1989 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 static char sccsid[] = "@(#)vmstat.c 5.14 (Berkeley) 06/26/91"; 9 #endif not lint 10 11 /* 12 * Cursed vmstat -- from Robert Elz. 13 */ 14 15 #include "systat.h" 16 17 #include <ctype.h> 18 #include <utmp.h> 19 20 #include <vm/vm.h> 21 #include <sys/vmmeter.h> 22 #include <sys/buf.h> 23 #include <sys/stat.h> 24 #include <sys/time.h> 25 #include <sys/user.h> 26 #include <sys/proc.h> 27 #include <sys/namei.h> 28 29 #include <machine/pte.h> 30 #include <paths.h> 31 32 static int ut; 33 34 WINDOW * 35 openkre() 36 { 37 38 ut = open(_PATH_UTMP, O_RDONLY); 39 if (ut < 0) 40 error("No utmp"); 41 return (stdscr); 42 } 43 44 closekre(w) 45 WINDOW *w; 46 { 47 48 (void) close(ut); 49 if (w == NULL) 50 return; 51 wclear(w); 52 wrefresh(w); 53 } 54 55 float cputime(); 56 struct utmp utmp; 57 58 static struct nlist nlst[] = { 59 #define X_CPTIME 0 60 { "_cp_time" }, 61 #define X_CNT 1 62 { "_cnt" }, 63 #define X_TOTAL 2 64 { "_total" }, 65 #define X_VMSTAT 3 66 { "_vm_stat" }, 67 #define X_DK_BUSY 4 68 { "_dk_busy" }, 69 #define X_DK_TIME 5 70 { "_dk_time" }, 71 #define X_DK_XFER 6 72 { "_dk_xfer" }, 73 #define X_DK_WDS 7 74 { "_dk_wds" }, 75 #define X_DK_SEEK 8 76 { "_dk_seek" }, 77 #define X_NCHSTATS 9 78 { "_nchstats" }, 79 #define X_INTRNAMES 10 80 { "_intrnames" }, 81 #define X_EINTRNAMES 11 82 { "_eintrnames" }, 83 #define X_INTRCNT 12 84 { "_intrcnt" }, 85 #define X_EINTRCNT 13 86 { "_eintrcnt" }, 87 { "" }, 88 }; 89 90 static struct Info { 91 long time[CPUSTATES]; 92 struct vmmeter Cnt; 93 struct vmtotal Total; 94 struct vm_statistics Vmstat; 95 long *dk_time; 96 long *dk_wds; 97 long *dk_seek; 98 long *dk_xfer; 99 int dk_busy; 100 struct nchstats nchstats; 101 long nchcount; 102 long *intrcnt; 103 } s, s1, s2, z; 104 105 #define cnt s.Cnt 106 #define oldcnt s1.Cnt 107 #define total s.Total 108 #define vmstat s.Vmstat 109 #define oldvmstat s1.Vmstat 110 #define nchtotal s.nchstats 111 #define oldnchtotal s1.nchstats 112 113 static char buf[26]; 114 static time_t t; 115 static double etime; 116 static float hertz; 117 static int nintr; 118 static long *intrloc; 119 static char **intrname; 120 static int nextintsrow; 121 122 static enum state { BOOT, TIME, RUN } state = TIME; 123 124 static void putint(), putfloat(), putrate(); 125 static void getinfo(), allocinfo(), copyinfo(), dinfo(); 126 static int ucount(); 127 128 /* 129 * These constants define where the major pieces are laid out 130 */ 131 #define STATROW 0 /* uses 1 row and 68 cols */ 132 #define STATCOL 2 133 #define MEMROW 2 /* uses 4 rows and 31 cols */ 134 #define MEMCOL 0 135 #define PAGEROW 2 /* uses 4 rows and 26 cols */ 136 #define PAGECOL 36 137 #define INTSROW 2 /* uses all rows to bottom and 17 cols */ 138 #define INTSCOL 63 139 #define PROCSROW 7 /* uses 2 rows and 20 cols */ 140 #define PROCSCOL 0 141 #define VMSTATROW 7 /* uses 2 rows and 26 cols */ 142 #define VMSTATCOL 25 143 #define FILLSTATROW 7 /* uses 6 rows and 10 cols */ 144 #define FILLSTATCOL 53 145 #define GRAPHROW 10 /* uses 3 rows and 51 cols */ 146 #define GRAPHCOL 0 147 #define NAMEIROW 14 /* uses 3 rows and 38 cols */ 148 #define NAMEICOL 0 149 #define GENSTATROW 14 /* uses 9 rows and 11 cols */ 150 #define GENSTATCOL 52 151 #define DISKROW 18 /* uses 5 rows and 50 cols (for 9 drives) */ 152 #define DISKCOL 0 153 154 #define DRIVESPACE 9 /* max # for space */ 155 156 #if DK_NDRIVE > DRIVESPACE 157 #define MAXDRIVES DRIVESPACE /* max # to display */ 158 #else 159 #define MAXDRIVES DK_NDRIVE /* max # to display */ 160 #endif 161 162 initkre() 163 { 164 char *intrnamebuf, *cp; 165 int i; 166 static int once = 0; 167 168 if (nlst[0].n_type == 0) { 169 kvm_nlist(nlst); 170 if (nlst[0].n_type == 0) { 171 error("No namelist"); 172 return(0); 173 } 174 } 175 hertz = phz ? phz : hz; 176 if (! dkinit()) 177 return(0); 178 if (dk_ndrive && !once) { 179 #define allocate(e, t) \ 180 s./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \ 181 s1./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \ 182 s2./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \ 183 z./**/e = (t *)calloc(dk_ndrive, sizeof (t)); 184 allocate(dk_time, long); 185 allocate(dk_wds, long); 186 allocate(dk_seek, long); 187 allocate(dk_xfer, long); 188 once = 1; 189 #undef allocate 190 } 191 if (nintr == 0) { 192 nintr = (nlst[X_EINTRCNT].n_value - 193 nlst[X_INTRCNT].n_value) / sizeof (long); 194 intrloc = (long *) calloc(nintr, sizeof (long)); 195 intrname = (char **) calloc(nintr, sizeof (long)); 196 intrnamebuf = malloc(nlst[X_EINTRNAMES].n_value - 197 nlst[X_INTRNAMES].n_value); 198 if (intrnamebuf == 0 || intrname == 0 || intrloc == 0) { 199 error("Out of memory\n"); 200 if (intrnamebuf) 201 free(intrnamebuf); 202 if (intrname) 203 free(intrname); 204 if (intrloc) 205 free(intrloc); 206 nintr = 0; 207 return(0); 208 } 209 NREAD(X_INTRNAMES, intrnamebuf, NVAL(X_EINTRNAMES) - 210 NVAL(X_INTRNAMES)); 211 for (cp = intrnamebuf, i = 0; i < nintr; i++) { 212 intrname[i] = cp; 213 cp += strlen(cp) + 1; 214 } 215 nextintsrow = INTSROW + 2; 216 allocinfo(&s); 217 allocinfo(&s1); 218 allocinfo(&s2); 219 allocinfo(&z); 220 } 221 getinfo(&s2, RUN); 222 copyinfo(&s2, &s1); 223 return(1); 224 } 225 226 fetchkre() 227 { 228 time_t now; 229 230 time(&now); 231 strcpy(buf, ctime(&now)); 232 buf[16] = '\0'; 233 getinfo(&s, state); 234 } 235 236 labelkre() 237 { 238 register i, j; 239 240 clear(); 241 mvprintw(STATROW, STATCOL + 4, "users Load"); 242 mvprintw(MEMROW, MEMCOL, "Mem REAL VIRTUAL"); 243 mvprintw(MEMROW + 1, MEMCOL, " Tot Text Tot Text"); 244 mvprintw(MEMROW + 2, MEMCOL, "Act"); 245 mvprintw(MEMROW + 3, MEMCOL, "All"); 246 247 mvprintw(MEMROW + 1, MEMCOL + 28, "Free"); 248 249 mvprintw(PAGEROW, PAGECOL, " PAGING SWAPPING "); 250 mvprintw(PAGEROW + 1, PAGECOL, " in out in out "); 251 mvprintw(PAGEROW + 2, PAGECOL, "count"); 252 mvprintw(PAGEROW + 3, PAGECOL, "pages"); 253 254 mvprintw(INTSROW, INTSCOL + 3, " Interrupts"); 255 mvprintw(INTSROW + 1, INTSCOL + 9, "total"); 256 257 mvprintw(GENSTATROW, GENSTATCOL + 8, "Csw"); 258 mvprintw(GENSTATROW + 1, GENSTATCOL + 8, "Trp"); 259 mvprintw(GENSTATROW + 2, GENSTATCOL + 8, "Sys"); 260 mvprintw(GENSTATROW + 3, GENSTATCOL + 8, "Int"); 261 mvprintw(GENSTATROW + 4, GENSTATCOL + 8, "Pdm"); 262 mvprintw(GENSTATROW + 5, GENSTATCOL + 8, "Sof"); 263 mvprintw(GENSTATROW + 6, GENSTATCOL + 8, "Flt"); 264 mvprintw(GENSTATROW + 7, GENSTATCOL + 8, "Cow"); 265 266 mvprintw(VMSTATROW, VMSTATCOL, "Rec F/S F/F RFL Fre SFr"); 267 268 mvprintw(FILLSTATROW, FILLSTATCOL + 7, " zf"); 269 mvprintw(FILLSTATROW + 1, FILLSTATCOL + 7, "nzf"); 270 mvprintw(FILLSTATROW + 2, FILLSTATCOL + 7, "%%zf"); 271 mvprintw(FILLSTATROW + 3, FILLSTATCOL + 7, " xf"); 272 mvprintw(FILLSTATROW + 4, FILLSTATCOL + 7, "nxf"); 273 mvprintw(FILLSTATROW + 5, FILLSTATCOL + 7, "%%xf"); 274 275 mvprintw(GRAPHROW, GRAPHCOL, 276 " . %% Sys . %% User . %% Nice . %% Idle"); 277 mvprintw(PROCSROW, PROCSCOL, "Procs r p d s w"); 278 mvprintw(GRAPHROW + 1, GRAPHCOL, 279 "| | | | | | | | | | |"); 280 281 mvprintw(NAMEIROW, NAMEICOL, "Namei Sys-cache Proc-cache"); 282 mvprintw(NAMEIROW + 1, NAMEICOL, 283 " Calls hits %% hits %%"); 284 mvprintw(DISKROW, DISKCOL, "Discs"); 285 mvprintw(DISKROW + 1, DISKCOL, "seeks"); 286 mvprintw(DISKROW + 2, DISKCOL, "xfers"); 287 mvprintw(DISKROW + 3, DISKCOL, " blks"); 288 mvprintw(DISKROW + 4, DISKCOL, " msps"); 289 j = 0; 290 for (i = 0; i < dk_ndrive && j < MAXDRIVES; i++) 291 if (dk_select[i]) { 292 mvprintw(DISKROW, DISKCOL + 5 + 5 * j, 293 " %3.3s", dr_name[j]); 294 j++; 295 } 296 for (i = 0; i < nintr; i++) { 297 if (intrloc[i] == 0) 298 continue; 299 mvprintw(intrloc[i], INTSCOL + 9, "%-8.8s", intrname[i]); 300 } 301 } 302 303 #define X(fld) {t=s.fld[i]; s.fld[i]-=s1.fld[i]; if(state==TIME) s1.fld[i]=t;} 304 #define Y(fld) {t = s.fld; s.fld -= s1.fld; if(state == TIME) s1.fld = t;} 305 #define Z(fld) {t = s.nchstats.fld; s.nchstats.fld -= s1.nchstats.fld; \ 306 if(state == TIME) s1.nchstats.fld = t;} 307 #define MAXFAIL 5 308 309 static char cpuchar[CPUSTATES] = { '=' , '>', '-', ' ' }; 310 static char cpuorder[CPUSTATES] = { CP_SYS, CP_USER, CP_NICE, CP_IDLE }; 311 312 showkre() 313 { 314 float f1, f2; 315 int psiz, inttotal; 316 int i, l, c; 317 static int failcnt = 0; 318 319 for (i = 0; i < dk_ndrive; i++) { 320 X(dk_xfer); X(dk_seek); X(dk_wds); X(dk_time); 321 } 322 etime = 0; 323 for(i = 0; i < CPUSTATES; i++) { 324 X(time); 325 etime += s.time[i]; 326 } 327 if (etime < 5.0) { /* < 5 ticks - ignore this trash */ 328 if (failcnt++ >= MAXFAIL) { 329 clear(); 330 mvprintw(2, 10, "The alternate system clock has died!"); 331 mvprintw(3, 10, "Reverting to ``pigs'' display."); 332 move(CMDLINE, 0); 333 refresh(); 334 failcnt = 0; 335 sleep(5); 336 command("pigs"); 337 } 338 return; 339 } 340 failcnt = 0; 341 etime /= hertz; 342 inttotal = 0; 343 for (i = 0; i < nintr; i++) { 344 if (s.intrcnt[i] == 0) 345 continue; 346 if (intrloc[i] == 0) { 347 if (nextintsrow == LINES) 348 continue; 349 intrloc[i] = nextintsrow++; 350 mvprintw(intrloc[i], INTSCOL + 9, "%-8.8s", 351 intrname[i]); 352 } 353 X(intrcnt); 354 l = (int)((float)s.intrcnt[i]/etime + 0.5); 355 inttotal += l; 356 putint(l, intrloc[i], INTSCOL, 8); 357 } 358 putint(inttotal, INTSROW + 1, INTSCOL, 8); 359 Z(ncs_goodhits); Z(ncs_badhits); Z(ncs_miss); 360 Z(ncs_long); Z(ncs_pass2); Z(ncs_2passes); 361 s.nchcount = nchtotal.ncs_goodhits + nchtotal.ncs_badhits + 362 nchtotal.ncs_miss + nchtotal.ncs_long; 363 if (state == TIME) 364 s1.nchcount = s.nchcount; 365 366 psiz = 0; 367 f2 = 0.0; 368 for (c = 0; c < CPUSTATES; c++) { 369 i = cpuorder[c]; 370 f1 = cputime(i); 371 f2 += f1; 372 l = (int) ((f2 + 1.0) / 2.0) - psiz; 373 if (c == 0) 374 putfloat(f1, GRAPHROW, GRAPHCOL + 1, 5, 1, 0); 375 else 376 putfloat(f1, GRAPHROW, GRAPHCOL + 12 * c, 377 5, 1, 0); 378 move(GRAPHROW + 2, psiz); 379 psiz += l; 380 while (l-- > 0) 381 addch(cpuchar[c]); 382 } 383 384 putint(ucount(), STATROW, STATCOL, 3); 385 putfloat(avenrun[0], STATROW, STATCOL + 17, 6, 2, 0); 386 putfloat(avenrun[1], STATROW, STATCOL + 23, 6, 2, 0); 387 putfloat(avenrun[2], STATROW, STATCOL + 29, 6, 2, 0); 388 mvaddstr(STATROW, STATCOL + 53, buf); 389 #define pgtokb(pg) ((pg) * NBPG / 1024) 390 putint(pgtokb(total.t_arm), MEMROW + 2, MEMCOL + 4, 5); 391 putint(pgtokb(total.t_armtxt), MEMROW + 2, MEMCOL + 9, 5); 392 putint(pgtokb(total.t_avm), MEMROW + 2, MEMCOL + 14, 6); 393 putint(pgtokb(total.t_avmtxt), MEMROW + 2, MEMCOL + 20, 5); 394 putint(pgtokb(total.t_rm), MEMROW + 3, MEMCOL + 4, 5); 395 putint(pgtokb(total.t_rmtxt), MEMROW + 3, MEMCOL + 9, 5); 396 putint(pgtokb(total.t_vm), MEMROW + 3, MEMCOL + 14, 6); 397 putint(pgtokb(total.t_vmtxt), MEMROW + 3, MEMCOL + 20, 5); 398 putint(pgtokb(total.t_free), MEMROW + 2, MEMCOL + 27, 5); 399 putint(total.t_rq, PROCSROW + 1, PROCSCOL + 5, 3); 400 putint(total.t_pw, PROCSROW + 1, PROCSCOL + 8, 3); 401 putint(total.t_dw, PROCSROW + 1, PROCSCOL + 11, 3); 402 putint(total.t_sl, PROCSROW + 1, PROCSCOL + 14, 3); 403 putint(total.t_sw, PROCSROW + 1, PROCSCOL + 17, 3); 404 putrate(cnt.v_swtch, oldcnt.v_swtch, 405 GENSTATROW, GENSTATCOL, 7); 406 putrate(cnt.v_trap, oldcnt.v_trap, 407 GENSTATROW + 1, GENSTATCOL, 7); 408 putrate(cnt.v_syscall, oldcnt.v_syscall, 409 GENSTATROW + 2, GENSTATCOL, 7); 410 putrate(cnt.v_intr, oldcnt.v_intr, 411 GENSTATROW + 3, GENSTATCOL, 7); 412 putrate(cnt.v_pdma, oldcnt.v_pdma, 413 GENSTATROW + 4, GENSTATCOL, 7); 414 putrate(cnt.v_soft, oldcnt.v_soft, 415 GENSTATROW + 5, GENSTATCOL, 7); 416 putrate(vmstat.faults, oldvmstat.faults, 417 GENSTATROW + 6, GENSTATCOL, 7); 418 putrate(vmstat.cow_faults, oldvmstat.cow_faults, 419 GENSTATROW + 7, GENSTATCOL, 7); 420 putrate(vmstat.pageins, oldvmstat.pageins, PAGEROW + 2, 421 PAGECOL + 5, 5); 422 putrate(vmstat.pageouts, oldvmstat.pageouts, PAGEROW + 2, 423 PAGECOL + 10, 5); 424 putrate(cnt.v_swpin, oldcnt.v_swpin, PAGEROW + 2, /* - */ 425 PAGECOL + 15, 5); 426 putrate(cnt.v_swpout, oldcnt.v_swpout, PAGEROW + 2, /* - */ 427 PAGECOL + 20, 5); 428 putrate(cnt.v_pgpgin, oldcnt.v_pgpgin, PAGEROW + 3, /* ? */ 429 PAGECOL + 5, 5); 430 putrate(cnt.v_pgpgout, oldcnt.v_pgpgout, PAGEROW + 3, /* ? */ 431 PAGECOL + 10, 5); 432 putrate(cnt.v_pswpin, oldcnt.v_pswpin, PAGEROW + 3, /* - */ 433 PAGECOL + 15, 5); 434 putrate(cnt.v_pswpout, oldcnt.v_pswpout, PAGEROW + 3, /* - */ 435 PAGECOL + 20, 5); 436 437 putrate(vmstat.reactivations, oldvmstat.reactivations, 438 VMSTATROW + 1, VMSTATCOL, 3); 439 putrate(cnt.v_xsfrec, oldcnt.v_xsfrec, VMSTATROW + 1, 440 VMSTATCOL + 7, 3); 441 putrate(cnt.v_xifrec, oldcnt.v_xifrec, VMSTATROW + 1, 442 VMSTATCOL + 11, 3); 443 putrate(cnt.v_pgfrec, oldcnt.v_pgfrec, VMSTATROW + 1, 444 VMSTATCOL + 15, 3); 445 putrate(cnt.v_dfree, oldcnt.v_dfree, VMSTATROW + 1, 446 VMSTATCOL + 19, 3); 447 putrate(cnt.v_seqfree, oldcnt.v_seqfree, VMSTATROW + 1, 448 VMSTATCOL + 23, 3); 449 450 putrate(vmstat.zero_fill_count, oldvmstat.zero_fill_count, 451 FILLSTATROW, FILLSTATCOL, 6); 452 /******* begin XXX 453 putrate(cnt.v_nzfod, oldcnt.v_nzfod, FILLSTATROW + 1, FILLSTATCOL, 6); 454 putrate(cnt.v_exfod, oldcnt.v_exfod, FILLSTATROW + 3, 455 FILLSTATCOL, 6); 456 putrate(cnt.v_nexfod, oldcnt.v_nexfod, FILLSTATROW + 4, 457 FILLSTATCOL, 6); 458 putfloat ( 459 cnt.v_nzfod == 0 ? 460 0.0 461 : state != RUN ? 462 ( 100.0 * cnt.v_zfod / cnt.v_nzfod ) 463 : cnt.v_nzfod == oldcnt.v_nzfod ? 464 0.0 465 : 466 ( 100.0 * (cnt.v_zfod-oldcnt.v_zfod) 467 / (cnt.v_nzfod-oldcnt.v_nzfod) ) 468 , FILLSTATROW + 2 469 , FILLSTATCOL 470 , 6 471 , 2 472 , 1 473 ); 474 putfloat ( 475 cnt.v_nexfod == 0 ? 476 0.0 477 : state != RUN ? 478 ( 100.0 * cnt.v_exfod / cnt.v_nexfod ) 479 : cnt.v_nexfod == oldcnt.v_nexfod ? 480 0.0 481 : 482 ( 100.0 * (cnt.v_exfod-oldcnt.v_exfod) 483 / (cnt.v_nexfod-oldcnt.v_nexfod) ) 484 , FILLSTATROW + 5 485 , FILLSTATCOL 486 , 6 487 , 2 488 , 1 489 ); 490 ******* end XXX */ 491 492 mvprintw(DISKROW,DISKCOL+5," "); 493 for (i = 0, c = 0; i < dk_ndrive && c < MAXDRIVES; i++) 494 if (dk_select[i]) { 495 mvprintw(DISKROW, DISKCOL + 5 + 5 * c, 496 " %3.3s", dr_name[i]); 497 dinfo(i, ++c); 498 } 499 putint(s.nchcount, NAMEIROW + 2, NAMEICOL, 9); 500 putint(nchtotal.ncs_goodhits, NAMEIROW + 2, NAMEICOL + 9, 9); 501 #define nz(x) ((x) ? (x) : 1) 502 putfloat(nchtotal.ncs_goodhits * 100.0 / nz(s.nchcount), 503 NAMEIROW + 2, NAMEICOL + 19, 4, 0, 1); 504 putint(nchtotal.ncs_pass2, NAMEIROW + 2, NAMEICOL + 23, 9); 505 putfloat(nchtotal.ncs_pass2 * 100.0 / nz(s.nchcount), 506 NAMEIROW + 2, NAMEICOL + 34, 4, 0, 1); 507 #undef nz 508 } 509 510 cmdkre(cmd, args) 511 char *cmd, *args; 512 { 513 514 if (prefix(cmd, "run")) { 515 copyinfo(&s2, &s1); 516 state = RUN; 517 return (1); 518 } 519 if (prefix(cmd, "boot")) { 520 state = BOOT; 521 copyinfo(&z, &s1); 522 return (1); 523 } 524 if (prefix(cmd, "time")) { 525 state = TIME; 526 return (1); 527 } 528 if (prefix(cmd, "zero")) { 529 if (state == RUN) 530 getinfo(&s1, RUN); 531 return (1); 532 } 533 return (dkcmd(cmd, args)); 534 } 535 536 /* calculate number of users on the system */ 537 static int 538 ucount() 539 { 540 register int nusers = 0; 541 542 if (ut < 0) 543 return (0); 544 while (read(ut, &utmp, sizeof(utmp))) 545 if (utmp.ut_name[0] != '\0') 546 nusers++; 547 548 lseek(ut, 0L, L_SET); 549 return (nusers); 550 } 551 552 static float 553 cputime(indx) 554 int indx; 555 { 556 double t; 557 register i; 558 559 t = 0; 560 for (i = 0; i < CPUSTATES; i++) 561 t += s.time[i]; 562 if (t == 0.0) 563 t = 1.0; 564 return (s.time[indx] * 100.0 / t); 565 } 566 567 static void 568 putrate(r, or, l, c, w) 569 int r, or, l, c, w; 570 { 571 572 if (state == RUN || state == TIME) 573 r -= or; 574 putint((int)((float)r/etime + 0.5), l, c, w); 575 } 576 577 static void 578 putint(n, l, c, w) 579 int n, l, c, w; 580 { 581 char b[128]; 582 583 move(l, c); 584 if (n == 0) { 585 while (w-- > 0) 586 addch(' '); 587 return; 588 } 589 sprintf(b, "%*d", w, n); 590 if (strlen(b) > w) { 591 while (w-- > 0) 592 addch('*'); 593 return; 594 } 595 addstr(b); 596 } 597 598 static void 599 putfloat(f, l, c, w, d, nz) 600 float f; 601 int l, c, w, d, nz; 602 { 603 char b[128]; 604 605 move(l, c); 606 if (nz && f == 0.0) { 607 while (--w >= 0) 608 addch(' '); 609 return; 610 } 611 sprintf(b, "%*.*f", w, d, f); 612 if (strlen(b) > w) { 613 while (--w >= 0) 614 addch('*'); 615 return; 616 } 617 addstr(b); 618 } 619 620 static void 621 getinfo(s, st) 622 struct Info *s; 623 enum state st; 624 { 625 626 NREAD(X_CPTIME, s->time, sizeof s->time); 627 NREAD(X_CNT, &s->Cnt, sizeof s->Cnt); 628 NREAD(X_TOTAL, &s->Total, sizeof s->Total); 629 NREAD(X_VMSTAT, &s->Vmstat, sizeof s->Vmstat); 630 NREAD(X_DK_BUSY, &s->dk_busy, LONG); 631 NREAD(X_DK_TIME, s->dk_time, dk_ndrive * LONG); 632 NREAD(X_DK_XFER, s->dk_xfer, dk_ndrive * LONG); 633 NREAD(X_DK_WDS, s->dk_wds, dk_ndrive * LONG); 634 NREAD(X_DK_SEEK, s->dk_seek, dk_ndrive * LONG); 635 NREAD(X_NCHSTATS, &s->nchstats, sizeof s->nchstats); 636 NREAD(X_INTRCNT, s->intrcnt, nintr * LONG); 637 } 638 639 static void 640 allocinfo(s) 641 struct Info *s; 642 { 643 644 s->intrcnt = (long *) malloc(nintr * sizeof(long)); 645 if (s->intrcnt == NULL) { 646 fprintf(stderr, "systat: out of memory\n"); 647 exit(2); 648 } 649 } 650 651 static void 652 copyinfo(from, to) 653 register struct Info *from, *to; 654 { 655 long *time, *wds, *seek, *xfer; 656 long *intrcnt; 657 658 /* 659 * time, wds, seek, and xfer are malloc'd so we have to 660 * save the pointers before the structure copy and then 661 * copy by hand. 662 */ 663 time = to->dk_time; wds = to->dk_wds; seek = to->dk_seek; 664 xfer = to->dk_xfer; intrcnt = to->intrcnt; 665 *to = *from; 666 bcopy(from->dk_time, to->dk_time = time, dk_ndrive * sizeof (long)); 667 bcopy(from->dk_wds, to->dk_wds = wds, dk_ndrive * sizeof (long)); 668 bcopy(from->dk_seek, to->dk_seek = seek, dk_ndrive * sizeof (long)); 669 bcopy(from->dk_xfer, to->dk_xfer = xfer, dk_ndrive * sizeof (long)); 670 bcopy(from->intrcnt, to->intrcnt = intrcnt, nintr * sizeof (int)); 671 } 672 673 static void 674 dinfo(dn, c) 675 int dn, c; 676 { 677 double words, atime, itime, xtime; 678 679 c = DISKCOL + c * 5; 680 atime = s.dk_time[dn]; 681 atime /= hertz; 682 words = s.dk_wds[dn]*32.0; /* number of words transferred */ 683 xtime = dk_mspw[dn]*words; /* transfer time */ 684 itime = atime - xtime; /* time not transferring */ 685 if (xtime < 0) 686 itime += xtime, xtime = 0; 687 if (itime < 0) 688 xtime += itime, itime = 0; 689 putint((int)((float)s.dk_seek[dn]/etime+0.5), DISKROW + 1, c, 5); 690 putint((int)((float)s.dk_xfer[dn]/etime+0.5), DISKROW + 2, c, 5); 691 putint((int)(words/etime/512.0 + 0.5), DISKROW + 3, c, 5); 692 if (s.dk_seek[dn]) 693 putfloat(itime*1000.0/s.dk_seek[dn], DISKROW + 4, c, 5, 1, 1); 694 else 695 putint(0, DISKROW + 4, c, 5); 696 } 697