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