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