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