1 /* 2 * Copyright (c) 1980 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 char copyright[] = 9 "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10 All rights reserved.\n"; 11 #endif not lint 12 13 #ifndef lint 14 static char sccsid[] = "@(#)pstat.c 5.1 (Berkeley) 06/04/85"; 15 #endif not lint 16 17 /* 18 * Print system stuff 19 */ 20 21 #define mask(x) (x&0377) 22 #define clear(x) ((int)x&0x7fffffff) 23 24 #include <sys/param.h> 25 #include <sys/dir.h> 26 #define KERNEL 27 #include <sys/file.h> 28 #undef KERNEL 29 #include <sys/user.h> 30 #include <sys/proc.h> 31 #include <sys/text.h> 32 #include <sys/inode.h> 33 #include <sys/map.h> 34 #include <sys/ioctl.h> 35 #include <sys/tty.h> 36 #include <sys/conf.h> 37 #include <sys/vm.h> 38 #include <nlist.h> 39 #include <machine/pte.h> 40 41 char *fcore = "/dev/kmem"; 42 char *fmem = "/dev/mem"; 43 char *fnlist = "/vmunix"; 44 int fc, fm; 45 46 struct nlist nl[] = { 47 #define SINODE 0 48 { "_inode" }, 49 #define STEXT 1 50 { "_text" }, 51 #define SPROC 2 52 { "_proc" }, 53 #define SDZ 3 54 { "_dz_tty" }, 55 #define SNDZ 4 56 { "_dz_cnt" }, 57 #define SKL 5 58 { "_cons" }, 59 #define SFIL 6 60 { "_file" }, 61 #define USRPTMA 7 62 { "_Usrptmap" }, 63 #define USRPT 8 64 { "_usrpt" }, 65 #define SWAPMAP 9 66 { "_swapmap" }, 67 #define SDH 10 68 { "_dh11" }, 69 #define SNDH 11 70 { "_ndh11" }, 71 #define SNPROC 12 72 { "_nproc" }, 73 #define SNTEXT 13 74 { "_ntext" }, 75 #define SNFILE 14 76 { "_nfile" }, 77 #define SNINODE 15 78 { "_ninode" }, 79 #define SNSWAPMAP 16 80 { "_nswapmap" }, 81 #define SPTY 17 82 { "_pt_tty" }, 83 #define SDMMIN 18 84 { "_dmmin" }, 85 #define SDMMAX 19 86 { "_dmmax" }, 87 #define SNSWDEV 20 88 { "_nswdev" }, 89 #define SSWDEVT 21 90 { "_swdevt" }, 91 #define SDMF 22 92 { "_dmf_tty" }, 93 #define SNDMF 23 94 { "_ndmf" }, 95 #define SNPTY 24 96 { "_npty" }, 97 { "" } 98 }; 99 100 int inof; 101 int txtf; 102 int prcf; 103 int ttyf; 104 int usrf; 105 long ubase; 106 int filf; 107 int swpf; 108 int totflg; 109 char partab[1]; 110 struct cdevsw cdevsw[1]; 111 struct bdevsw bdevsw[1]; 112 int allflg; 113 int kflg; 114 struct pte *Usrptma; 115 struct pte *usrpt; 116 117 main(argc, argv) 118 char **argv; 119 { 120 register char *argp; 121 int allflags; 122 123 argc--, argv++; 124 while (argc > 0 && **argv == '-') { 125 argp = *argv++; 126 argp++; 127 argc--; 128 while (*argp++) 129 switch (argp[-1]) { 130 131 case 'T': 132 totflg++; 133 break; 134 135 case 'a': 136 allflg++; 137 break; 138 139 case 'i': 140 inof++; 141 break; 142 143 case 'k': 144 kflg++; 145 fcore = fmem = "/vmcore"; 146 break; 147 148 case 'x': 149 txtf++; 150 break; 151 152 case 'p': 153 prcf++; 154 break; 155 156 case 't': 157 ttyf++; 158 break; 159 160 case 'u': 161 if (argc == 0) 162 break; 163 argc--; 164 usrf++; 165 sscanf( *argv++, "%x", &ubase); 166 break; 167 168 case 'f': 169 filf++; 170 break; 171 case 's': 172 swpf++; 173 break; 174 default: 175 usage(); 176 exit(1); 177 } 178 } 179 if (argc>1) 180 fcore = fmem = argv[1]; 181 if ((fc = open(fcore, 0)) < 0) { 182 printf("Can't find %s\n", fcore); 183 exit(1); 184 } 185 if ((fm = open(fmem, 0)) < 0) { 186 printf("Can't find %s\n", fmem); 187 exit(1); 188 } 189 if (argc>0) 190 fnlist = argv[0]; 191 nlist(fnlist, nl); 192 usrpt = (struct pte *)nl[USRPT].n_value; 193 Usrptma = (struct pte *)nl[USRPTMA].n_value; 194 if (nl[0].n_type == 0) { 195 printf("no namelist\n"); 196 exit(1); 197 } 198 allflags = filf | totflg | inof | prcf | txtf | ttyf | usrf | swpf; 199 if (allflags == 0) { 200 printf("pstat: one or more of -[aixptfsu] is required\n"); 201 exit(1); 202 } 203 if (filf||totflg) 204 dofile(); 205 if (inof||totflg) 206 doinode(); 207 if (prcf||totflg) 208 doproc(); 209 if (txtf||totflg) 210 dotext(); 211 if (ttyf) 212 dotty(); 213 if (usrf) 214 dousr(); 215 if (swpf||totflg) 216 doswap(); 217 } 218 219 usage() 220 { 221 222 printf("usage: pstat -[aixptfs] [-u [ubase]] [system] [core]\n"); 223 } 224 225 doinode() 226 { 227 register struct inode *ip; 228 struct inode *xinode, *ainode; 229 register int nin; 230 int ninode; 231 232 nin = 0; 233 ninode = getw(nl[SNINODE].n_value); 234 xinode = (struct inode *)calloc(ninode, sizeof (struct inode)); 235 lseek(fc, (int)(ainode = (struct inode *)getw(nl[SINODE].n_value)), 0); 236 read(fc, xinode, ninode * sizeof(struct inode)); 237 for (ip = xinode; ip < &xinode[ninode]; ip++) 238 if (ip->i_count) 239 nin++; 240 if (totflg) { 241 printf("%3d/%3d inodes\n", nin, ninode); 242 return; 243 } 244 printf("%d/%d active inodes\n", nin, ninode); 245 printf(" LOC FLAGS CNT DEVICE RDC WRC INO MODE NLK UID SIZE/DEV\n"); 246 for (ip = xinode; ip < &xinode[ninode]; ip++) { 247 if (ip->i_count == 0) 248 continue; 249 printf("%8.1x ", ainode + (ip - xinode)); 250 putf(ip->i_flag&ILOCKED, 'L'); 251 putf(ip->i_flag&IUPD, 'U'); 252 putf(ip->i_flag&IACC, 'A'); 253 putf(ip->i_flag&IMOUNT, 'M'); 254 putf(ip->i_flag&IWANT, 'W'); 255 putf(ip->i_flag&ITEXT, 'T'); 256 putf(ip->i_flag&ICHG, 'C'); 257 putf(ip->i_flag&ISHLOCK, 'S'); 258 putf(ip->i_flag&IEXLOCK, 'E'); 259 putf(ip->i_flag&ILWAIT, 'Z'); 260 printf("%4d", ip->i_count&0377); 261 printf("%4d,%3d", major(ip->i_dev), minor(ip->i_dev)); 262 printf("%4d", ip->i_shlockc&0377); 263 printf("%4d", ip->i_exlockc&0377); 264 printf("%6d", ip->i_number); 265 printf("%6x", ip->i_mode & 0xffff); 266 printf("%4d", ip->i_nlink); 267 printf("%4d", ip->i_uid); 268 if ((ip->i_mode&IFMT)==IFBLK || (ip->i_mode&IFMT)==IFCHR) 269 printf("%6d,%3d", major(ip->i_rdev), minor(ip->i_rdev)); 270 else 271 printf("%10ld", ip->i_size); 272 printf("\n"); 273 } 274 free(xinode); 275 } 276 277 getw(loc) 278 off_t loc; 279 { 280 int word; 281 282 if (kflg) 283 loc &= 0x7fffffff; 284 lseek(fc, loc, 0); 285 read(fc, &word, sizeof (word)); 286 if (kflg) 287 word &= 0x7fffffff; 288 return (word); 289 } 290 291 putf(v, n) 292 { 293 if (v) 294 printf("%c", n); 295 else 296 printf(" "); 297 } 298 299 dotext() 300 { 301 register struct text *xp; 302 int ntext; 303 struct text *xtext, *atext; 304 int ntx; 305 306 ntx = 0; 307 ntext = getw(nl[SNTEXT].n_value); 308 xtext = (struct text *)calloc(ntext, sizeof (struct text)); 309 lseek(fc, (int)(atext = (struct text *)getw(nl[STEXT].n_value)), 0); 310 read(fc, xtext, ntext * sizeof (struct text)); 311 for (xp = xtext; xp < &xtext[ntext]; xp++) 312 if (xp->x_iptr!=NULL) 313 ntx++; 314 if (totflg) { 315 printf("%3d/%3d texts\n", ntx, ntext); 316 return; 317 } 318 printf("%d/%d active texts\n", ntx, ntext); 319 printf(" LOC FLAGS DADDR CADDR RSS SIZE IPTR CNT CCNT\n"); 320 for (xp = xtext; xp < &xtext[ntext]; xp++) { 321 if (xp->x_iptr == NULL) 322 continue; 323 printf("%8.1x", atext + (xp - xtext)); 324 printf(" "); 325 putf(xp->x_flag&XPAGI, 'P'); 326 putf(xp->x_flag&XTRC, 'T'); 327 putf(xp->x_flag&XWRIT, 'W'); 328 putf(xp->x_flag&XLOAD, 'L'); 329 putf(xp->x_flag&XLOCK, 'K'); 330 putf(xp->x_flag&XWANT, 'w'); 331 printf("%5x", xp->x_daddr[0]); 332 printf("%11x", xp->x_caddr); 333 printf("%5d", xp->x_rssize); 334 printf("%5d", xp->x_size); 335 printf("%10.1x", xp->x_iptr); 336 printf("%5d", xp->x_count&0377); 337 printf("%5d", xp->x_ccount); 338 printf("\n"); 339 } 340 free(xtext); 341 } 342 343 doproc() 344 { 345 struct proc *xproc, *aproc; 346 int nproc; 347 register struct proc *pp; 348 register loc, np; 349 struct pte apte; 350 351 nproc = getw(nl[SNPROC].n_value); 352 xproc = (struct proc *)calloc(nproc, sizeof (struct proc)); 353 lseek(fc, (int)(aproc = (struct proc *)getw(nl[SPROC].n_value)), 0); 354 read(fc, xproc, nproc * sizeof (struct proc)); 355 np = 0; 356 for (pp=xproc; pp < &xproc[nproc]; pp++) 357 if (pp->p_stat) 358 np++; 359 if (totflg) { 360 printf("%3d/%3d processes\n", np, nproc); 361 return; 362 } 363 printf("%d/%d processes\n", np, nproc); 364 printf(" LOC S F POIP PRI SIG UID SLP TIM CPU NI PGRP PID PPID ADDR RSS SRSS SIZE WCHAN LINK TEXTP\n"); 365 for (pp=xproc; pp<&xproc[nproc]; pp++) { 366 if (pp->p_stat==0 && allflg==0) 367 continue; 368 printf("%8x", aproc + (pp - xproc)); 369 printf(" %2d", pp->p_stat); 370 printf(" %4x", pp->p_flag & 0xffff); 371 printf(" %4d", pp->p_poip); 372 printf(" %3d", pp->p_pri); 373 printf(" %8x", pp->p_sig); 374 printf(" %4d", pp->p_uid); 375 printf(" %3d", pp->p_slptime); 376 printf(" %3d", pp->p_time); 377 printf(" %4d", pp->p_cpu&0377); 378 printf(" %3d", pp->p_nice); 379 printf(" %6d", pp->p_pgrp); 380 printf(" %6d", pp->p_pid); 381 printf(" %6d", pp->p_ppid); 382 if (kflg) 383 pp->p_addr = (struct pte *)clear((int)pp->p_addr); 384 if (pp->p_flag & SLOAD) { 385 lseek(fc, (long)pp->p_addr, 0); 386 read(fc, &apte, sizeof(apte)); 387 printf(" %8x", apte.pg_pfnum); 388 } else 389 printf(" %8x", pp->p_swaddr); 390 printf(" %4x", pp->p_rssize); 391 printf(" %4x", pp->p_swrss); 392 printf(" %5x", pp->p_dsize+pp->p_ssize); 393 printf(" %7x", clear(pp->p_wchan)); 394 printf(" %7x", clear(pp->p_link)); 395 printf(" %7x", clear(pp->p_textp)); 396 printf("\n"); 397 } 398 } 399 400 dotty() 401 { 402 struct tty *tty; 403 int ntty, ttyspace = 128; 404 register struct tty *tp; 405 extern char *malloc(), *realloc(); 406 static char mesg[] = 407 " # RAW CAN OUT MODE ADDR DEL COL STATE PGRP DISC\n"; 408 409 if ((tty = (struct tty *)malloc(ttyspace * sizeof(*tty))) == 0) { 410 printf("pstat: out of memory\n"); 411 return; 412 } 413 printf("1 cons\n"); 414 if (kflg) 415 nl[SKL].n_value = clear(nl[SKL].n_value); 416 lseek(fc, (long)nl[SKL].n_value, 0); 417 read(fc, tty, sizeof(*tty)); 418 printf(mesg); 419 ttyprt(&tty[0], 0); 420 if (nl[SNDZ].n_type == 0) 421 goto dh; 422 if (kflg) { 423 nl[SNDZ].n_value = clear(nl[SNDZ].n_value); 424 nl[SDZ].n_value = clear(nl[SDZ].n_value); 425 } 426 lseek(fc, (long)nl[SNDZ].n_value, 0); 427 read(fc, &ntty, sizeof(ntty)); 428 printf("%d dz lines\n", ntty); 429 if (ntty > ttyspace) { 430 ttyspace = ntty; 431 if ((tty = (struct tty *)realloc(tty, ttyspace * sizeof(*tty))) == 0) { 432 printf("pstat: out of memory\n"); 433 return; 434 } 435 } 436 lseek(fc, (long)nl[SDZ].n_value, 0); 437 read(fc, tty, ntty * sizeof (struct tty)); 438 printf(mesg); 439 for (tp = tty; tp < &tty[ntty]; tp++) 440 ttyprt(tp, tp - tty); 441 dh: 442 if (nl[SNDH].n_type == 0) 443 goto dmf; 444 if (kflg) { 445 nl[SNDH].n_value = clear(nl[SNDH].n_value); 446 nl[SDH].n_value = clear(nl[SDH].n_value); 447 } 448 lseek(fc, (long)nl[SNDH].n_value, 0); 449 read(fc, &ntty, sizeof(ntty)); 450 printf("%d dh lines\n", ntty); 451 if (ntty > ttyspace) { 452 ttyspace = ntty; 453 if ((tty = (struct tty *)realloc(tty, ttyspace * sizeof(*tty))) == 0) { 454 printf("pstat: out of memory\n"); 455 return; 456 } 457 } 458 lseek(fc, (long)nl[SDH].n_value, 0); 459 read(fc, tty, ntty * sizeof(struct tty)); 460 printf(mesg); 461 for (tp = tty; tp < &tty[ntty]; tp++) 462 ttyprt(tp, tp - tty); 463 dmf: 464 if (nl[SNDMF].n_type == 0) 465 goto pty; 466 if (kflg) { 467 nl[SNDMF].n_value = clear(nl[SNDMF].n_value); 468 nl[SDMF].n_value = clear(nl[SDMF].n_value); 469 } 470 lseek(fc, (long)nl[SNDMF].n_value, 0); 471 read(fc, &ntty, sizeof(ntty)); 472 printf("%d dmf lines\n", ntty); 473 if (ntty > ttyspace) { 474 ttyspace = ntty; 475 if ((tty = (struct tty *)realloc(tty, ttyspace * sizeof(*tty))) == 0) { 476 printf("pstat: out of memory\n"); 477 return; 478 } 479 } 480 lseek(fc, (long)nl[SDMF].n_value, 0); 481 read(fc, tty, ntty * sizeof(struct tty)); 482 printf(mesg); 483 for (tp = tty; tp < &tty[ntty]; tp++) 484 ttyprt(tp, tp - tty); 485 pty: 486 if (nl[SPTY].n_type == 0) 487 return; 488 if (kflg) { 489 nl[SPTY].n_value = clear(nl[SPTY].n_value); 490 nl[SNPTY].n_value = clear(nl[SNPTY].n_value); 491 } 492 lseek(fc, (long)nl[SNPTY].n_value, 0); 493 read(fc, &ntty, sizeof(ntty)); 494 printf("%d pty lines\n", ntty); 495 if (ntty > ttyspace) { 496 ttyspace = ntty; 497 if ((tty = (struct tty *)realloc(tty, ttyspace * sizeof(*tty))) == 0) { 498 printf("pstat: out of memory\n"); 499 return; 500 } 501 } 502 lseek(fc, (long)nl[SPTY].n_value, 0); 503 read(fc, tty, ntty*sizeof(struct tty)); 504 printf(mesg); 505 for (tp = tty; tp < &tty[ntty]; tp++) 506 ttyprt(tp, tp - tty); 507 } 508 509 ttyprt(atp, line) 510 struct tty *atp; 511 { 512 register struct tty *tp; 513 514 printf("%2d", line); 515 tp = atp; 516 switch (tp->t_line) { 517 518 /* 519 case NETLDISC: 520 if (tp->t_rec) 521 printf("%4d%4d", 0, tp->t_inbuf); 522 else 523 printf("%4d%4d", tp->t_inbuf, 0); 524 break; 525 */ 526 527 default: 528 printf("%4d%4d", tp->t_rawq.c_cc, tp->t_canq.c_cc); 529 } 530 printf("%4d %8x %8x%4d%4d", tp->t_outq.c_cc, tp->t_flags, 531 tp->t_addr, tp->t_delct, tp->t_col); 532 putf(tp->t_state&TS_TIMEOUT, 'T'); 533 putf(tp->t_state&TS_WOPEN, 'W'); 534 putf(tp->t_state&TS_ISOPEN, 'O'); 535 putf(tp->t_state&TS_FLUSH, 'F'); 536 putf(tp->t_state&TS_CARR_ON, 'C'); 537 putf(tp->t_state&TS_BUSY, 'B'); 538 putf(tp->t_state&TS_ASLEEP, 'A'); 539 putf(tp->t_state&TS_XCLUDE, 'X'); 540 putf(tp->t_state&TS_TTSTOP, 'S'); 541 putf(tp->t_state&TS_HUPCLS, 'H'); 542 printf("%6d", tp->t_pgrp); 543 switch (tp->t_line) { 544 545 case OTTYDISC: 546 printf("\n"); 547 break; 548 549 case NTTYDISC: 550 printf(" ntty\n"); 551 break; 552 553 case NETLDISC: 554 printf(" net\n"); 555 break; 556 557 case TABLDISC: 558 printf(" tab\n"); 559 break; 560 561 case NTABLDISC: 562 printf(" ntab\n"); 563 break; 564 565 default: 566 printf(" %d\n", tp->t_line); 567 } 568 } 569 570 dousr() 571 { 572 struct user U; 573 register i, j, *ip; 574 register struct nameidata *nd = &U.u_nd; 575 576 /* This wins only if CLBYTES >= sizeof (struct user) */ 577 lseek(fm, ubase * NBPG, 0); 578 read(fm, &U, sizeof(U)); 579 printf("pcb"); 580 ip = (int *)&U.u_pcb; 581 while (ip < &U.u_arg[0]) { 582 if ((ip - (int *)&U.u_pcb) % 4 == 0) 583 printf("\t"); 584 printf("%x ", *ip++); 585 if ((ip - (int *)&U.u_pcb) % 4 == 0) 586 printf("\n"); 587 } 588 if ((ip - (int *)&U.u_pcb) % 4 != 0) 589 printf("\n"); 590 printf("arg"); 591 for (i=0; i<sizeof(U.u_arg)/sizeof(U.u_arg[0]); i++) { 592 if (i%5==0) 593 printf("\t"); 594 printf(" %.1x", U.u_arg[i]); 595 if (i%5==4) 596 printf("\n"); 597 } 598 if (i%5) 599 printf("\n"); 600 printf("segflg\t%d\nerror %d\n", nd->ni_segflg, U.u_error); 601 printf("uids\t%d,%d,%d,%d\n", U.u_uid,U.u_gid,U.u_ruid,U.u_rgid); 602 printf("procp\t%.1x\n", U.u_procp); 603 printf("ap\t%.1x\n", U.u_ap); 604 printf("r_val?\t%.1x %.1x\n", U.u_r.r_val1, U.u_r.r_val2); 605 printf("base, count, offset %.1x %.1x %ld\n", nd->ni_base, 606 nd->ni_count, nd->ni_offset); 607 printf("cdir rdir %.1x %.1x\n", U.u_cdir, U.u_rdir); 608 printf("dirp %.1x\n", nd->ni_dirp); 609 printf("dent %d %.14s\n", nd->ni_dent.d_ino, nd->ni_dent.d_name); 610 printf("pdir %.1o\n", nd->ni_pdir); 611 printf("file"); 612 for (i=0; i<NOFILE; i++) { 613 if (i % 8 == 0) 614 printf("\t"); 615 printf("%9.1x", U.u_ofile[i]); 616 if (i % 8 == 7) 617 printf("\n"); 618 } 619 if (i % 8) 620 printf("\n"); 621 printf("pofile"); 622 for (i=0; i<NOFILE; i++) { 623 if (i % 8 == 0) 624 printf("\t"); 625 printf("%9.1x", U.u_pofile[i]); 626 if (i % 8 == 7) 627 printf("\n"); 628 } 629 if (i % 8) 630 printf("\n"); 631 printf("ssave"); 632 for (i=0; i<sizeof(label_t)/sizeof(int); i++) { 633 if (i%5==0) 634 printf("\t"); 635 printf("%9.1x", U.u_ssave.val[i]); 636 if (i%5==4) 637 printf("\n"); 638 } 639 if (i%5) 640 printf("\n"); 641 printf("sigs"); 642 for (i=0; i<NSIG; i++) { 643 if (i % 8 == 0) 644 printf("\t"); 645 printf("%.1x ", U.u_signal[i]); 646 if (i % 8 == 7) 647 printf("\n"); 648 } 649 if (i % 8) 650 printf("\n"); 651 printf("code\t%.1x\n", U.u_code); 652 printf("ar0\t%.1x\n", U.u_ar0); 653 printf("prof\t%X %X %X %X\n", U.u_prof.pr_base, U.u_prof.pr_size, 654 U.u_prof.pr_off, U.u_prof.pr_scale); 655 printf("\neosys\t%d\n", U.u_eosys); 656 printf("ttyp\t%.1x\n", U.u_ttyp); 657 printf("ttyd\t%d,%d\n", major(U.u_ttyd), minor(U.u_ttyd)); 658 printf("comm %.14s\n", U.u_comm); 659 printf("start\t%D\n", U.u_start); 660 printf("acflag\t%D\n", U.u_acflag); 661 printf("cmask\t%D\n", U.u_cmask); 662 printf("sizes\t%.1x %.1x %.1x\n", U.u_tsize, U.u_dsize, U.u_ssize); 663 printf("ru\t"); 664 ip = (int *)&U.u_ru; 665 for (i = 0; i < sizeof(U.u_ru)/sizeof(int); i++) 666 printf("%D ", ip[i]); 667 printf("\n"); 668 ip = (int *)&U.u_cru; 669 printf("cru\t"); 670 for (i = 0; i < sizeof(U.u_cru)/sizeof(int); i++) 671 printf("%D ", ip[i]); 672 printf("\n"); 673 /* 674 i = U.u_stack - &U; 675 while (U[++i] == 0); 676 i &= ~07; 677 while (i < 512) { 678 printf("%x ", 0140000+2*i); 679 for (j=0; j<8; j++) 680 printf("%9x", U[i++]); 681 printf("\n"); 682 } 683 */ 684 } 685 686 oatoi(s) 687 char *s; 688 { 689 register v; 690 691 v = 0; 692 while (*s) 693 v = (v<<3) + *s++ - '0'; 694 return(v); 695 } 696 697 dofile() 698 { 699 int nfile; 700 struct file *xfile, *afile; 701 register struct file *fp; 702 register nf; 703 int loc; 704 static char *dtypes[] = { "???", "inode", "socket" }; 705 706 nf = 0; 707 nfile = getw(nl[SNFILE].n_value); 708 xfile = (struct file *)calloc(nfile, sizeof (struct file)); 709 lseek(fc, (int)(afile = (struct file *)getw(nl[SFIL].n_value)), 0); 710 read(fc, xfile, nfile * sizeof (struct file)); 711 for (fp=xfile; fp < &xfile[nfile]; fp++) 712 if (fp->f_count) 713 nf++; 714 if (totflg) { 715 printf("%3d/%3d files\n", nf, nfile); 716 return; 717 } 718 printf("%d/%d open files\n", nf, nfile); 719 printf(" LOC TYPE FLG CNT MSG DATA OFFSET\n"); 720 for (fp=xfile,loc=(int)afile; fp < &xfile[nfile]; fp++,loc+=sizeof(xfile[0])) { 721 if (fp->f_count==0) 722 continue; 723 printf("%8x ", loc); 724 if (fp->f_type <= DTYPE_SOCKET) 725 printf("%-8.8s", dtypes[fp->f_type]); 726 else 727 printf("8d", fp->f_type); 728 putf(fp->f_flag&FREAD, 'R'); 729 putf(fp->f_flag&FWRITE, 'W'); 730 putf(fp->f_flag&FAPPEND, 'A'); 731 putf(fp->f_flag&FSHLOCK, 'S'); 732 putf(fp->f_flag&FEXLOCK, 'X'); 733 putf(fp->f_flag&FASYNC, 'I'); 734 printf(" %3d", mask(fp->f_count)); 735 printf(" %3d", mask(fp->f_msgcount)); 736 printf(" %8.1x", fp->f_data); 737 if (fp->f_offset < 0) 738 printf(" %x\n", fp->f_offset); 739 else 740 printf(" %ld\n", fp->f_offset); 741 } 742 } 743 744 int dmmin, dmmax, nswdev; 745 746 doswap() 747 { 748 struct proc *proc; 749 int nproc; 750 struct text *xtext; 751 int ntext; 752 struct map *swapmap; 753 int nswapmap; 754 struct swdevt *swdevt, *sw; 755 register struct proc *pp; 756 int nswap, used, tused, free, waste; 757 int db, sb; 758 register struct mapent *me; 759 register struct text *xp; 760 int i, j; 761 762 nproc = getw(nl[SNPROC].n_value); 763 proc = (struct proc *)calloc(nproc, sizeof (struct proc)); 764 ntext = getw(nl[SNTEXT].n_value); 765 xtext = (struct text *)calloc(ntext, sizeof (struct text)); 766 nswapmap = getw(nl[SNSWAPMAP].n_value); 767 swapmap = (struct map *)calloc(nswapmap, sizeof (struct map)); 768 nswdev = getw(nl[SNSWDEV].n_value); 769 swdevt = (struct swdevt *)calloc(nswdev, sizeof (struct swdevt)); 770 lseek(fc, nl[SSWDEVT].n_value, L_SET); 771 read(fc, swdevt, nswdev * sizeof (struct swdevt)); 772 lseek(fc, getw(nl[SPROC].n_value), 0); 773 read(fc, proc, nproc * sizeof (struct proc)); 774 lseek(fc, getw(nl[STEXT].n_value), 0); 775 read(fc, xtext, ntext * sizeof (struct text)); 776 lseek(fc, getw(nl[SWAPMAP].n_value), 0); 777 read(fc, swapmap, nswapmap * sizeof (struct map)); 778 swapmap->m_name = "swap"; 779 swapmap->m_limit = (struct mapent *)&swapmap[nswapmap]; 780 dmmin = getw(nl[SDMMIN].n_value); 781 dmmax = getw(nl[SDMMAX].n_value); 782 nswap = 0; 783 for (sw = swdevt; sw < &swdevt[nswdev]; sw++) 784 nswap += sw->sw_nblks, 785 free = 0; 786 for (me = (struct mapent *)(swapmap+1); 787 me < (struct mapent *)&swapmap[nswapmap]; me++) 788 free += me->m_size; 789 tused = 0; 790 for (xp = xtext; xp < &xtext[ntext]; xp++) 791 if (xp->x_iptr!=NULL) { 792 tused += ctod(clrnd(xp->x_size)); 793 if (xp->x_flag & XPAGI) 794 tused += ctod(clrnd(ctopt(xp->x_size))); 795 } 796 used = tused; 797 waste = 0; 798 for (pp = proc; pp < &proc[nproc]; pp++) { 799 if (pp->p_stat == 0 || pp->p_stat == SZOMB) 800 continue; 801 if (pp->p_flag & SSYS) 802 continue; 803 db = ctod(pp->p_dsize), sb = up(db); 804 used += sb; 805 waste += sb - db; 806 db = ctod(pp->p_ssize), sb = up(db); 807 used += sb; 808 waste += sb - db; 809 if ((pp->p_flag&SLOAD) == 0) 810 used += ctod(vusize(pp)); 811 } 812 if (totflg) { 813 #define btok(x) ((x) / (1024 / DEV_BSIZE)) 814 printf("%3d/%3d 00k swap\n", 815 btok(used/100), btok((used+free)/100)); 816 return; 817 } 818 printf("%dk used (%dk text), %dk free, %dk wasted, %dk missing\n", 819 btok(used), btok(tused), btok(free), btok(waste), 820 /* a dmmax/2 block goes to argmap */ 821 btok(nswap - dmmax/2 - (used + free))); 822 printf("avail: "); 823 for (i = dmmax; i >= dmmin; i /= 2) { 824 j = 0; 825 while (rmalloc(swapmap, i) != 0) 826 j++; 827 if (j) printf("%d*%dk ", j, btok(i)); 828 } 829 free = 0; 830 for (me = (struct mapent *)(swapmap+1); 831 me < (struct mapent *)&swapmap[nswapmap]; me++) 832 free += me->m_size; 833 printf("%d*1k\n", btok(free)); 834 } 835 836 up(size) 837 register int size; 838 { 839 register int i, block; 840 841 i = 0; 842 block = dmmin; 843 while (i < size) { 844 i += block; 845 if (block < dmmax) 846 block *= 2; 847 } 848 return (i); 849 } 850 851 /* 852 * Compute number of pages to be allocated to the u. area 853 * and data and stack area page tables, which are stored on the 854 * disk immediately after the u. area. 855 */ 856 vusize(p) 857 register struct proc *p; 858 { 859 register int tsz = p->p_tsize / NPTEPG; 860 861 /* 862 * We do not need page table space on the disk for page 863 * table pages wholly containing text. 864 */ 865 return (clrnd(UPAGES + 866 clrnd(ctopt(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES)) - tsz)); 867 } 868 869 /* 870 * Allocate 'size' units from the given 871 * map. Return the base of the allocated space. 872 * In a map, the addresses are increasing and the 873 * list is terminated by a 0 size. 874 * 875 * Algorithm is first-fit. 876 * 877 * This routine knows about the interleaving of the swapmap 878 * and handles that. 879 */ 880 long 881 rmalloc(mp, size) 882 register struct map *mp; 883 long size; 884 { 885 register struct mapent *ep = (struct mapent *)(mp+1); 886 register int addr; 887 register struct mapent *bp; 888 swblk_t first, rest; 889 890 if (size <= 0 || size > dmmax) 891 return (0); 892 /* 893 * Search for a piece of the resource map which has enough 894 * free space to accomodate the request. 895 */ 896 for (bp = ep; bp->m_size; bp++) { 897 if (bp->m_size >= size) { 898 /* 899 * If allocating from swapmap, 900 * then have to respect interleaving 901 * boundaries. 902 */ 903 if (nswdev > 1 && 904 (first = dmmax - bp->m_addr%dmmax) < bp->m_size) { 905 if (bp->m_size - first < size) 906 continue; 907 addr = bp->m_addr + first; 908 rest = bp->m_size - first - size; 909 bp->m_size = first; 910 if (rest) 911 rmfree(mp, rest, addr+size); 912 return (addr); 913 } 914 /* 915 * Allocate from the map. 916 * If there is no space left of the piece 917 * we allocated from, move the rest of 918 * the pieces to the left. 919 */ 920 addr = bp->m_addr; 921 bp->m_addr += size; 922 if ((bp->m_size -= size) == 0) { 923 do { 924 bp++; 925 (bp-1)->m_addr = bp->m_addr; 926 } while ((bp-1)->m_size = bp->m_size); 927 } 928 if (addr % CLSIZE) 929 return (0); 930 return (addr); 931 } 932 } 933 return (0); 934 } 935 936 /* 937 * Free the previously allocated space at addr 938 * of size units into the specified map. 939 * Sort addr into map and combine on 940 * one or both ends if possible. 941 */ 942 rmfree(mp, size, addr) 943 struct map *mp; 944 long size, addr; 945 { 946 struct mapent *firstbp; 947 register struct mapent *bp; 948 register int t; 949 950 /* 951 * Both address and size must be 952 * positive, or the protocol has broken down. 953 */ 954 if (addr <= 0 || size <= 0) 955 goto badrmfree; 956 /* 957 * Locate the piece of the map which starts after the 958 * returned space (or the end of the map). 959 */ 960 firstbp = bp = (struct mapent *)(mp + 1); 961 for (; bp->m_addr <= addr && bp->m_size != 0; bp++) 962 continue; 963 /* 964 * If the piece on the left abuts us, 965 * then we should combine with it. 966 */ 967 if (bp > firstbp && (bp-1)->m_addr+(bp-1)->m_size >= addr) { 968 /* 969 * Check no overlap (internal error). 970 */ 971 if ((bp-1)->m_addr+(bp-1)->m_size > addr) 972 goto badrmfree; 973 /* 974 * Add into piece on the left by increasing its size. 975 */ 976 (bp-1)->m_size += size; 977 /* 978 * If the combined piece abuts the piece on 979 * the right now, compress it in also, 980 * by shifting the remaining pieces of the map over. 981 */ 982 if (bp->m_addr && addr+size >= bp->m_addr) { 983 if (addr+size > bp->m_addr) 984 goto badrmfree; 985 (bp-1)->m_size += bp->m_size; 986 while (bp->m_size) { 987 bp++; 988 (bp-1)->m_addr = bp->m_addr; 989 (bp-1)->m_size = bp->m_size; 990 } 991 } 992 goto done; 993 } 994 /* 995 * Don't abut on the left, check for abutting on 996 * the right. 997 */ 998 if (addr+size >= bp->m_addr && bp->m_size) { 999 if (addr+size > bp->m_addr) 1000 goto badrmfree; 1001 bp->m_addr -= size; 1002 bp->m_size += size; 1003 goto done; 1004 } 1005 /* 1006 * Don't abut at all. Make a new entry 1007 * and check for map overflow. 1008 */ 1009 do { 1010 t = bp->m_addr; 1011 bp->m_addr = addr; 1012 addr = t; 1013 t = bp->m_size; 1014 bp->m_size = size; 1015 bp++; 1016 } while (size = t); 1017 /* 1018 * Segment at bp is to be the delimiter; 1019 * If there is not room for it 1020 * then the table is too full 1021 * and we must discard something. 1022 */ 1023 if (bp+1 > mp->m_limit) { 1024 /* 1025 * Back bp up to last available segment. 1026 * which contains a segment already and must 1027 * be made into the delimiter. 1028 * Discard second to last entry, 1029 * since it is presumably smaller than the last 1030 * and move the last entry back one. 1031 */ 1032 bp--; 1033 printf("%s: rmap ovflo, lost [%d,%d)\n", mp->m_name, 1034 (bp-1)->m_addr, (bp-1)->m_addr+(bp-1)->m_size); 1035 bp[-1] = bp[0]; 1036 bp[0].m_size = bp[0].m_addr = 0; 1037 } 1038 done: 1039 return; 1040 badrmfree: 1041 printf("bad rmfree\n"); 1042 } 1043