static char *sccsid
= "@(#)pstat.c 4.24 (Berkeley) 10/15/83";
#define clear(x) ((int)x&0x7fffffff)
char *fcore
= "/dev/kmem";
char *fnlist
= "/vmunix";
while (argc
> 0 && **argv
== '-') {
sscanf( *argv
++, "%x", &ubase
);
if ((fc
= open(fcore
, 0)) < 0) {
printf("Can't find %s\n", fcore
);
usrpt
= (struct pte
*)nl
[USRPT
].n_value
;
Usrptma
= (struct pte
*)nl
[USRPTMA
].n_value
;
allflags
= filf
| totflg
| inof
| prcf
| txtf
| ttyf
| usrf
| swpf
;
printf("pstat: one or more of -[aixptfsu] is required\n");
printf("usage: pstat -[aixptfs] [-u [ubase]] [system] [core]\n");
register struct inode
*ip
;
struct inode
*xinode
, *ainode
;
ninode
= getw(nl
[SNINODE
].n_value
);
xinode
= (struct inode
*)calloc(ninode
, sizeof (struct inode
));
lseek(fc
, (int)(ainode
= (struct inode
*)getw(nl
[SINODE
].n_value
)), 0);
read(fc
, xinode
, ninode
* sizeof(struct inode
));
for (ip
= xinode
; ip
< &xinode
[ninode
]; ip
++)
printf("%3d/%3d inodes\n", nin
, ninode
);
printf("%d/%d active inodes\n", nin
, ninode
);
printf(" LOC FLAGS CNT DEVICE RDC WRC INO MODE NLK UID SIZE/DEV\n");
for (ip
= xinode
; ip
< &xinode
[ninode
]; ip
++) {
printf("%8.1x ", ainode
+ (ip
- xinode
));
putf(ip
->i_flag
&ILOCKED
, 'L');
putf(ip
->i_flag
&IUPD
, 'U');
putf(ip
->i_flag
&IACC
, 'A');
putf(ip
->i_flag
&IMOUNT
, 'M');
putf(ip
->i_flag
&IWANT
, 'W');
putf(ip
->i_flag
&ITEXT
, 'T');
putf(ip
->i_flag
&ICHG
, 'C');
putf(ip
->i_flag
&ISHLOCK
, 'S');
putf(ip
->i_flag
&IEXLOCK
, 'E');
putf(ip
->i_flag
&ILWAIT
, 'Z');
printf("%4d", ip
->i_count
&0377);
printf("%4d,%3d", major(ip
->i_dev
), minor(ip
->i_dev
));
printf("%4d", ip
->i_shlockc
&0377);
printf("%4d", ip
->i_exlockc
&0377);
printf("%6d", ip
->i_number
);
printf("%6x", ip
->i_mode
& 0xffff);
printf("%4d", ip
->i_nlink
);
printf("%4d", ip
->i_uid
);
if ((ip
->i_mode
&IFMT
)==IFBLK
|| (ip
->i_mode
&IFMT
)==IFCHR
)
printf("%6d,%3d", major(ip
->i_rdev
), minor(ip
->i_rdev
));
printf("%10ld", ip
->i_size
);
read(fc
, &word
, sizeof (word
));
register struct text
*xp
;
struct text
*xtext
, *atext
;
ntext
= getw(nl
[SNTEXT
].n_value
);
xtext
= (struct text
*)calloc(ntext
, sizeof (struct text
));
lseek(fc
, (int)(atext
= (struct text
*)getw(nl
[STEXT
].n_value
)), 0);
read(fc
, xtext
, ntext
* sizeof (struct text
));
for (xp
= xtext
; xp
< &xtext
[ntext
]; xp
++)
printf("%3d/%3d texts\n", ntx
, ntext
);
printf("%d/%d active texts\n", ntx
, ntext
);
printf(" LOC FLAGS DADDR CADDR RSS SIZE IPTR CNT CCNT\n");
for (xp
= xtext
; xp
< &xtext
[ntext
]; xp
++) {
printf("%8.1x", atext
+ (xp
- xtext
));
putf(xp
->x_flag
&XPAGI
, 'P');
putf(xp
->x_flag
&XTRC
, 'T');
putf(xp
->x_flag
&XWRIT
, 'W');
putf(xp
->x_flag
&XLOAD
, 'L');
putf(xp
->x_flag
&XLOCK
, 'K');
putf(xp
->x_flag
&XWANT
, 'w');
printf("%5x", xp
->x_daddr
[0]);
printf("%11x", xp
->x_caddr
);
printf("%5d", xp
->x_rssize
);
printf("%5d", xp
->x_size
);
printf("%10.1x", xp
->x_iptr
);
printf("%5d", xp
->x_count
&0377);
printf("%5d", xp
->x_ccount
);
struct proc
*xproc
, *aproc
;
register struct proc
*pp
;
nproc
= getw(nl
[SNPROC
].n_value
);
xproc
= (struct proc
*)calloc(nproc
, sizeof (struct proc
));
lseek(fc
, (int)(aproc
= (struct proc
*)getw(nl
[SPROC
].n_value
)), 0);
read(fc
, xproc
, nproc
* sizeof (struct proc
));
for (pp
=xproc
; pp
< &xproc
[nproc
]; pp
++)
printf("%3d/%3d processes\n", np
, nproc
);
printf("%d/%d processes\n", np
, nproc
);
printf(" LOC S F POIP PRI SIG UID SLP TIM CPU NI PGRP PID PPID ADDR RSS SRSS SIZE WCHAN LINK TEXTP CLKT\n");
for (pp
=xproc
; pp
<&xproc
[nproc
]; pp
++) {
if (pp
->p_stat
==0 && allflg
==0)
printf("%8x", aproc
+ (pp
- xproc
));
printf(" %2d", pp
->p_stat
);
printf(" %4x", pp
->p_flag
& 0xffff);
printf(" %4d", pp
->p_poip
);
printf(" %3d", pp
->p_pri
);
printf(" %8x", pp
->p_sig
);
printf(" %4d", pp
->p_uid
);
printf(" %3d", pp
->p_slptime
);
printf(" %3d", pp
->p_time
);
printf(" %4d", pp
->p_cpu
&0377);
printf(" %3d", pp
->p_nice
);
printf(" %6d", pp
->p_pgrp
);
printf(" %6d", pp
->p_pid
);
printf(" %6d", pp
->p_ppid
);
pp
->p_addr
= (struct pte
*)clear((int)pp
->p_addr
);
lseek(fc
, (long)(Usrptma
+btokmx(pp
->p_addr
)), 0);
read(fc
, &apte
, sizeof(apte
));
printf(" %8x", ctob(apte
.pg_pfnum
+1) - sizeof(struct pte
) * UPAGES
);
printf(" %4x", pp
->p_rssize
);
printf(" %4x", pp
->p_swrss
);
printf(" %5x", pp
->p_dsize
+pp
->p_ssize
);
printf(" %7x", clear(pp
->p_wchan
));
printf(" %7x", clear(pp
->p_link
));
printf(" %7x", clear(pp
->p_textp
));
nl
[SKL
].n_value
= clear(nl
[SKL
].n_value
);
lseek(fc
, (long)nl
[SKL
].n_value
, 0);
read(fc
, dz_tty
, sizeof(dz_tty
[0]));
mesg
= " # RAW CAN OUT MODE ADDR DEL COL STATE PGRP DISC\n";
if (nl
[SNDZ
].n_type
== 0)
nl
[SNDZ
].n_value
= clear(nl
[SNDZ
].n_value
);
nl
[SDZ
].n_value
= clear(nl
[SDZ
].n_value
);
lseek(fc
, (long)nl
[SNDZ
].n_value
, 0);
read(fc
, &ndz
, sizeof(ndz
));
printf("%d dz lines\n", ndz
);
lseek(fc
, (long)nl
[SDZ
].n_value
, 0);
read(fc
, dz_tty
, ndz
* sizeof (struct tty
));
for (tp
= dz_tty
; tp
< &dz_tty
[ndz
]; tp
++)
if (nl
[SNDH
].n_type
== 0)
nl
[SNDH
].n_value
= clear(nl
[SNDH
].n_value
);
nl
[SDH
].n_value
= clear(nl
[SDH
].n_value
);
lseek(fc
, (long)nl
[SNDH
].n_value
, 0);
read(fc
, &ndz
, sizeof(ndz
));
printf("%d dh lines\n", ndz
);
lseek(fc
, (long)nl
[SDH
].n_value
, 0);
read(fc
, dz_tty
, ndz
* sizeof(struct tty
));
for (tp
= dz_tty
; tp
< &dz_tty
[ndz
]; tp
++)
if (nl
[SPTY
].n_type
== 0)
nl
[SPTY
].n_value
= clear(nl
[SPTY
].n_value
);
printf("32 pty lines\n");
lseek(fc
, (long)nl
[SPTY
].n_value
, 0);
read(fc
, dz_tty
, 32*sizeof(struct tty
));
for (tp
= dz_tty
; tp
< &dz_tty
[32]; tp
++)
printf("%4d%4d", 0, tp->t_inbuf);
printf("%4d%4d", tp->t_inbuf, 0);
printf("%4d", tp
->t_rawq
.c_cc
);
printf("%4d", tp
->t_canq
.c_cc
);
printf("%4d", tp
->t_outq
.c_cc
);
printf("%8.1x", tp
->t_flags
);
printf(" %8.1x", tp
->t_addr
);
printf("%3d", tp
->t_delct
);
printf("%4d ", tp
->t_col
);
putf(tp
->t_state
&TS_TIMEOUT
, 'T');
putf(tp
->t_state
&TS_WOPEN
, 'W');
putf(tp
->t_state
&TS_ISOPEN
, 'O');
putf(tp
->t_state
&TS_CARR_ON
, 'C');
putf(tp
->t_state
&TS_BUSY
, 'B');
putf(tp
->t_state
&TS_ASLEEP
, 'A');
putf(tp
->t_state
&TS_XCLUDE
, 'X');
putf(tp
->t_state
&TS_HUPCLS
, 'H');
printf("%6d", tp
->t_pgrp
);
/* This wins only if PAGSIZ > sizeof (struct user) */
lseek(fc
, ubase
* NBPG
, 0);
while (ip
< &U
.u_arg
[0]) {
if ((ip
- (int *)&U
.u_pcb
) % 4 == 0)
if ((ip
- (int *)&U
.u_pcb
) % 4 == 0)
if ((ip
- (int *)&U
.u_pcb
) % 4 != 0)
printf(" %.1x", U
.u_arg
[i
]);
for (i
=0; i
<sizeof(label_t
)/sizeof(int); i
++) {
printf("%9.1x", U
.u_ssave
.val
[i
]);
printf("segflg\t%d\nerror %d\n", U
.u_segflg
, U
.u_error
);
printf("uids\t%d,%d,%d,%d\n", U
.u_uid
,U
.u_gid
,U
.u_ruid
,U
.u_rgid
);
printf("procp\t%.1x\n", U
.u_procp
);
printf("ap\t%.1x\n", U
.u_ap
);
printf("r_val?\t%.1x %.1x\n", U
.u_r
.r_val1
, U
.u_r
.r_val2
);
printf("base, count, offset %.1x %.1x %ld\n", U
.u_base
,
printf("cdir rdir %.1x %.1x\n", U
.u_cdir
, U
.u_rdir
);
printf("dirp %.1x\n", U
.u_dirp
);
printf("dent %d %.14s\n", U
.u_dent
.d_ino
, U
.u_dent
.d_name
);
printf("pdir %.1o\n", U
.u_pdir
);
printf("%9.1x", U
.u_ofile
[i
]);
for (i
=10; i
<NOFILE
; i
++)
printf("%9.1x", U
.u_ofile
[i
]);
printf("%9.1x", U
.u_pofile
[i
]);
for (i
=10; i
<NOFILE
; i
++)
printf("%9.1x", U
.u_pofile
[i
]);
for (i
=0; i
<sizeof(label_t
)/sizeof(int); i
++) {
printf("%9.1x", U
.u_ssave
.val
[i
]);
printf("%.1x ", U
.u_signal
[i
]);
printf("code\t%.1x\n", U
.u_code
);
printf("ar0\t%.1x\n", U
.u_ar0
);
printf("prof\t%X %X %X %X\n", U
.u_prof
.pr_base
, U
.u_prof
.pr_size
,
U
.u_prof
.pr_off
, U
.u_prof
.pr_scale
);
printf("\neosys\t%d\n", U
.u_eosys
);
printf("ttyp\t%.1x\n", U
.u_ttyp
);
printf("ttyd\t%d,%d\n", major(U
.u_ttyd
), minor(U
.u_ttyd
));
printf("comm %.14s\n", U
.u_comm
);
printf("start\t%D\n", U
.u_start
);
printf("acflag\t%D\n", U
.u_acflag
);
printf("cmask\t%D\n", U
.u_cmask
);
printf("sizes\t%.1x %.1x %.1x\n", U
.u_tsize
, U
.u_dsize
, U
.u_ssize
);
for (i
= 0; i
< sizeof(U
.u_ru
)/sizeof(int); i
++)
for (i
= 0; i
< sizeof(U
.u_cru
)/sizeof(int); i
++)
printf("%x ", 0140000+2*i);
struct file
*xfile
, *afile
;
register struct file
*fp
;
static char *dtypes
[] = { "???", "inode", "socket" };
nfile
= getw(nl
[SNFILE
].n_value
);
xfile
= (struct file
*)calloc(nfile
, sizeof (struct file
));
lseek(fc
, (int)(afile
= (struct file
*)getw(nl
[SFIL
].n_value
)), 0);
read(fc
, xfile
, nfile
* sizeof (struct file
));
for (fp
=xfile
; fp
< &xfile
[nfile
]; fp
++)
printf("%3d/%3d files\n", nf
, nfile
);
printf("%d/%d open files\n", nf
, nfile
);
printf(" LOC TYPE FLG CNT MSG DATA OFFSET\n");
for (fp
=xfile
,loc
=(int)afile
; fp
< &xfile
[nfile
]; fp
++,loc
+=sizeof(xfile
[0])) {
if (fp
->f_type
<= DTYPE_SOCKET
)
printf("%-8.8s", dtypes
[fp
->f_type
]);
printf("8d", fp
->f_type
);
putf(fp
->f_flag
&FREAD
, 'R');
putf(fp
->f_flag
&FWRITE
, 'W');
putf(fp
->f_flag
&FAPPEND
, 'A');
putf(fp
->f_flag
&FSHLOCK
, 'S');
putf(fp
->f_flag
&FEXLOCK
, 'X');
putf(fp
->f_flag
&FASYNC
, 'I');
printf(" %3d", mask(fp
->f_count
));
printf(" %3d", mask(fp
->f_msgcount
));
printf(" %8.1x", fp
->f_data
);
printf(" %x\n", fp
->f_offset
);
printf(" %ld\n", fp
->f_offset
);
int dmmin
, dmmax
, nswdev
;
struct swdevt
*swdevt
, *sw
;
register struct proc
*pp
;
int nswap
, used
, tused
, free
, waste
;
register struct mapent
*me
;
register struct text
*xp
;
nproc
= getw(nl
[SNPROC
].n_value
);
proc
= (struct proc
*)calloc(nproc
, sizeof (struct proc
));
ntext
= getw(nl
[SNTEXT
].n_value
);
xtext
= (struct text
*)calloc(ntext
, sizeof (struct text
));
nswapmap
= getw(nl
[SNSWAPMAP
].n_value
);
swapmap
= (struct map
*)calloc(nswapmap
, sizeof (struct map
));
nswdev
= getw(nl
[SNSWDEV
].n_value
);
swdevt
= (struct swdevt
*)calloc(nswdev
, sizeof (struct swdevt
));
lseek(fc
, nl
[SSWDEVT
].n_value
, L_SET
);
read(fc
, swdevt
, nswdev
* sizeof (struct swdevt
));
lseek(fc
, getw(nl
[SPROC
].n_value
), 0);
read(fc
, proc
, nproc
* sizeof (struct proc
));
lseek(fc
, getw(nl
[STEXT
].n_value
), 0);
read(fc
, xtext
, ntext
* sizeof (struct text
));
lseek(fc
, getw(nl
[SWAPMAP
].n_value
), 0);
read(fc
, swapmap
, nswapmap
* sizeof (struct map
));
swapmap
->m_name
= "swap";
swapmap
->m_limit
= (struct mapent
*)&swapmap
[nswapmap
];
dmmin
= getw(nl
[SDMMIN
].n_value
);
dmmax
= getw(nl
[SDMMAX
].n_value
);
for (sw
= swdevt
; sw
< &swdevt
[nswdev
]; sw
++)
for (me
= (struct mapent
*)(swapmap
+1);
me
< (struct mapent
*)&swapmap
[nswapmap
]; me
++)
for (xp
= xtext
; xp
< &xtext
[ntext
]; xp
++)
tused
+= ctod(xp
->x_size
);
tused
+= ctod(ctopt(xp
->x_size
));
for (pp
= proc
; pp
< &proc
[nproc
]; pp
++) {
if (pp
->p_stat
== 0 || pp
->p_stat
== SZOMB
)
db
= ctod(pp
->p_dsize
), sb
= up(db
);
db
= ctod(pp
->p_ssize
), sb
= up(db
);
if ((pp
->p_flag
&SLOAD
) == 0)
#define btok(x) ((x) / (1024 / DEV_BSIZE))
printf("%3d/%3d 00k swap\n",
btok(used
/100), btok((used
+free
)/100));
printf("%dk used (%dk text), %dk free, %dk wasted, %dk missing\n",
btok(used
), btok(tused
), btok(free
), btok(waste
),
/* a dmmax/2 block goes to argmap */
btok(nswap
- dmmax
/2 - (used
+ free
)));
for (i
= dmmax
; i
>= dmmin
; i
/= 2) {
while (rmalloc(swapmap
, i
) != 0)
if (j
) printf("%d*%dk ", j
, btok(i
));
for (me
= (struct mapent
*)(swapmap
+1);
me
< (struct mapent
*)&swapmap
[nswapmap
]; me
++)
printf("%d*1k\n", btok(free
));
* Compute number of pages to be allocated to the u. area
* and data and stack area page tables, which are stored on the
* disk immediately after the u. area.
register int tsz
= p
->p_tsize
/ NPTEPG
;
* We do not need page table space on the disk for page
* table pages wholly containing text.
clrnd(ctopt(p
->p_tsize
+p
->p_dsize
+p
->p_ssize
+UPAGES
)) - tsz
));
* Allocate 'size' units from the given
* map. Return the base of the allocated space.
* In a map, the addresses are increasing and the
* list is terminated by a 0 size.
* Algorithm is first-fit.
* This routine knows about the interleaving of the swapmap
register struct mapent
*ep
= (struct mapent
*)(mp
+1);
register struct mapent
*bp
;
if (size
<= 0 || size
> dmmax
)
* Search for a piece of the resource map which has enough
* free space to accomodate the request.
for (bp
= ep
; bp
->m_size
; bp
++) {
if (bp
->m_size
>= size
) {
* If allocating from swapmap,
* then have to respect interleaving
(first
= dmmax
- bp
->m_addr
%dmmax
) < bp
->m_size
) {
if (bp
->m_size
- first
< size
)
addr
= bp
->m_addr
+ first
;
rest
= bp
->m_size
- first
- size
;
rmfree(mp
, rest
, addr
+size
);
* If there is no space left of the piece
* we allocated from, move the rest of
* the pieces to the left.
if ((bp
->m_size
-= size
) == 0) {
(bp
-1)->m_addr
= bp
->m_addr
;
} while ((bp
-1)->m_size
= bp
->m_size
);
* Free the previously allocated space at addr
* of size units into the specified map.
* Sort addr into map and combine on
* one or both ends if possible.
register struct mapent
*bp
;
* Both address and size must be
* positive, or the protocol has broken down.
if (addr
<= 0 || size
<= 0)
* Locate the piece of the map which starts after the
* returned space (or the end of the map).
firstbp
= bp
= (struct mapent
*)(mp
+ 1);
for (; bp
->m_addr
<= addr
&& bp
->m_size
!= 0; bp
++)
* If the piece on the left abuts us,
* then we should combine with it.
if (bp
> firstbp
&& (bp
-1)->m_addr
+(bp
-1)->m_size
>= addr
) {
* Check no overlap (internal error).
if ((bp
-1)->m_addr
+(bp
-1)->m_size
> addr
)
* Add into piece on the left by increasing its size.
* If the combined piece abuts the piece on
* the right now, compress it in also,
* by shifting the remaining pieces of the map over.
if (bp
->m_addr
&& addr
+size
>= bp
->m_addr
) {
if (addr
+size
> bp
->m_addr
)
(bp
-1)->m_size
+= bp
->m_size
;
(bp
-1)->m_addr
= bp
->m_addr
;
(bp
-1)->m_size
= bp
->m_size
;
* Don't abut on the left, check for abutting on
if (addr
+size
>= bp
->m_addr
&& bp
->m_size
) {
if (addr
+size
> bp
->m_addr
)
* Don't abut at all. Make a new entry
* and check for map overflow.
* Segment at bp is to be the delimiter;
* If there is not room for it
* then the table is too full
* and we must discard something.
if (bp
+1 > mp
->m_limit
) {
* Back bp up to last available segment.
* which contains a segment already and must
* be made into the delimiter.
* Discard second to last entry,
* since it is presumably smaller than the last
* and move the last entry back one.
printf("%s: rmap ovflo, lost [%d,%d)\n", mp
->m_name
,
(bp
-1)->m_addr
, (bp
-1)->m_addr
+(bp
-1)->m_size
);
bp
[0].m_size
= bp
[0].m_addr
= 0;