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