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