|
|
Power 6/32 Unix version 1.21
#ifndef lint
static char *sccsid = "@(#)vmstat.c 4.11 (Berkeley) 9/25/83";
#endif
#include <curses.h>
#include <signal.h>
#include <stdio.h>
#include <sys/param.h>
#include <sys/vm.h>
#include <sys/dk.h>
#include <nlist.h>
#include <sys/buf.h>
#include <vba/vbavar.h>
#include <setjmp.h>
#include <vba/vddc.h>
#define PART 16 /* 16 drives displayed in one mounted set */
#define MAX_PART ((int)((DK_NDRIVE+(PART-1))/PART))
struct nlist nli[] = {
#define X_CPTIME 0
{ "_cp_time" },
#define X_RATE 1
{ "_rate" },
#define X_TOTAL 2
{ "_total" },
#define X_DEFICIT 3
{ "_deficit" },
#define X_FORKSTAT 4
{ "_forkstat" },
#define X_SUM 5
{ "_sum" },
#define X_FIRSTFREE 6
{ "_firstfree" },
#define X_MAXFREE 7
{ "_maxfree" },
#define X_BOOTTIME 8
{ "_boottime" },
#define X_DKXFER 9
{ "_dk_xfer" },
#define X_VBDINIT 10
{ "_vbdinit" },
#define X_REC 11
{ "_rectime" },
#define X_PGIN 12
{ "_pgintime" },
#define X_HZ 13
{ "_hz" },
#define X_NVDDRV 14
{ "_nvddrv" },
#define X_VDST 15
{ "_vdst" },
{ "" },
};
#define UNIX "/vmunix"
char dr_name[DK_NDRIVE][10];
int dr_win[DK_NDRIVE];
double stat1();
int firstfree, maxfree;
int hz;
int nodktyp;
struct
{
int busy;
long time[CPUSTATES];
long xfer[DK_NDRIVE];
struct vmmeter Rate;
struct vmtotal Total;
struct vmmeter Sum;
struct forkstat Forkstat;
unsigned rectime;
unsigned pgintime;
} s, s1, z;
#define rate s.Rate
#define total s.Total
#define sum s.Sum
#define forkstat s.Forkstat
#define MAXRPT 10
#define NCOLS 80
#define NLINES 24
struct vmmeter osum;
int zero;
int deficit;
double etime;
int mf;
int swflag;
float f;
int iter,count,repcnt;
fs_tab *vdinfo, *vdinfo_save;
long name;
struct
{
int r;
int b;
int w;
int avm;
int fre;
int pgre;
int pgat;
int pi;
int po;
int fr;
int de;
int sr;
float dk[DK_NDRIVE];
int in;
int sy;
int cs;
float syste[(CPUSTATES-1)];
/*
int us;
int sy;
int id;
*/
} rec[MAXRPT];
int wno;
extern char *malloc();
jmp_buf jb;
int recurflg;
int max_win;
main(argc, argv)
int argc;
char **argv;
{
extern char *ctime();
register i,j;
int nintv;
int totrep;
time_t boottime;
double f1, f2;
long t;
extern char _sobuf[];
int die();
int ptoutput();
int shiftarray();
int dietty();
int timer();
int TERM;
time_t now;
/* addition variables for windowing implementation */
WINDOW *win[MAX_PART], *window, *newwin();
register w;
int w_sv;
int deft=0;
int wsleep, wrnd;
int sleeptime;
char ch;
TERM = isatty(1);
setbuf(stdout, _sobuf);
nlist(UNIX, nli);
if(nli[0].n_value == 0) {
printf("no %s namelist\n",UNIX);
exit(1);
}
mf = open("/dev/kmem", 0);
if(mf < 0) {
printf("cannot open /dev/kmem\n");
exit(1);
}
lseek(mf, (long)nli[X_NVDDRV].n_value, 0);
read(mf, &nodktyp, sizeof nodktyp);
vdinfo = (fs_tab *)malloc(nodktyp*sizeof(fs_tab));
lseek(mf, (long)nli[X_VDST].n_value, 0);
read(mf, (char *)vdinfo, nodktyp*sizeof(fs_tab));
vdinfo_save = vdinfo;
for (i = 0; i < nodktyp; vdinfo++, i++) {
name = (long)vdinfo->type_name;
vdinfo->type_name = malloc(3);
lseek(mf, (long)name, 0);
read(mf, vdinfo->type_name, 3);
}
vdinfo = vdinfo_save;
for (i = 0; i < DK_NDRIVE; i++){
sprintf(dr_name[i],"?%x",i);
dr_win[i] = -1;
}
read_names();
max_win=wno+1;
iter = 0;
argc--, argv++;
while (argc>0 && argv[0][0]=='-') {
char *cp = *argv++;
argc--;
while (*++cp) switch (*cp) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (TERM)
deft=(*cp)-'0';
if (deft >= max_win) deft =0;
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
if (TERM)
deft=(*cp) -'A' +10;
if (deft >= max_win) deft =0;
break;
case 'f':
doforkst();
exit(0);
case 'r':
if(TERM)
if(max_win > 1) recurflg++;
break;
case 's':
dosum();
exit(0);
case 'S':
swflag = 1 - swflag;
break;
case 't':
dotimes();
exit(0);
case 'z':
close(mf);
mf = open("/dev/kmem", 2);
lseek(mf, (long)nli[X_SUM].n_value, 0);
write(mf, &z.Sum, sizeof z.Sum);
exit(0);
default:
fprintf(stderr,"usage:vmstat ");
if(max_win > 0 )
if(max_win <10)
fprintf(stderr,"[-[0-%x][r",max_win);
else if (max_win >=10 && max_win < 16)
fprintf(stderr,"[-[0-9A-%x][r",max_win);
else;
fprintf(stderr," fs] [interval] [count] \n");
exit(1);
}
}
totrep = 1;
if(argc > 1)
totrep = atoi(argv[1]);
if(argc ==1)
totrep = -1;
iter = 0;
if ((totrep <0 ) || (totrep > MAXRPT))
repcnt = MAXRPT;
else
repcnt = totrep;
lseek(mf, (long)nli[X_FIRSTFREE].n_value, 0);
read(mf, &firstfree, sizeof firstfree);
lseek(mf, (long)nli[X_MAXFREE].n_value, 0);
read(mf, &maxfree, sizeof maxfree);
lseek(mf, (long)nli[X_BOOTTIME].n_value, 0);
read(mf, &boottime, sizeof boottime);
lseek(mf, (long)nli[X_HZ].n_value, 0);
read(mf, &hz, sizeof hz);
time(&now);
nintv = now - boottime;
if (nintv <= 0 || nintv > 60*60*24*365*10) {
printf("Time makes no sense... namelist must be wrong.\n");
exit(1);
}
if (TERM){
initscr();
signal(SIGINT,dietty);
signal(SIGBUS,dietty);
signal(SIGALRM, timer);
nonl();
crmode();
noecho();
leaveok(stdscr,TRUE);
scrollok(stdscr,FALSE);
for(w=0; w < max_win; w++){
win[w]=newwin(NLINES,NCOLS,0,0);
wmove(win[w],0,0);
}
}
else
signal(SIGINT,die);
reprint:
loop:
lseek(mf, (long)nli[X_CPTIME].n_value, 0);
read(mf, s.time, sizeof s.time);
lseek(mf, (long)nli[X_DKXFER].n_value, 0);
read(mf, s.xfer, sizeof s.xfer);
if (nintv != 1) {
lseek(mf, (long)nli[X_SUM].n_value, 0);
read(mf, &rate, sizeof rate);
} else {
lseek(mf, (long)nli[X_RATE].n_value, 0);
read(mf, &rate, sizeof rate);
}
lseek(mf, (long)nli[X_TOTAL].n_value, 0);
read(mf, &total, sizeof total);
osum = sum;
lseek(mf, (long)nli[X_SUM].n_value, 0);
read(mf, &sum, sizeof sum);
lseek(mf, (long)nli[X_DEFICIT].n_value, 0);
read(mf, &deficit, sizeof deficit);
etime = 0;
for (i=0; i < DK_NDRIVE; i++) {
t = s.xfer[i];
s.xfer[i] -= s1.xfer[i];
s1.xfer[i] = t;
}
for (i=0; i < CPUSTATES; i++) {
t = s.time[i];
s.time[i] -= s1.time[i];
s1.time[i] = t;
etime += s.time[i];
}
if(etime == 0.)
etime = 1.;
rec[iter].r = total.t_rq;
rec[iter].b = total.t_dw+total.t_pw;
rec[iter].w = total.t_sw;
rec[iter].avm= total.t_avm;
rec[iter].fre = total.t_free;
if(swflag){
rec[iter].pgre= sum.v_swpin-osum.v_swpin ;
rec[iter].pgat = sum.v_swpout-osum.v_swpout ;
}
else {
rec[iter].pgre = (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv;
rec[iter].pgat = (rate.v_xsfrec+rate.v_xifrec)/nintv;
}
rec[iter].pi = rate.v_pgpgin/nintv;
rec[iter].po= rate.v_pgpgout/nintv;
rec[iter].fr= rate.v_dfree/nintv;
rec[iter].de = deficit;
rec[iter].sr = rate.v_scan/nintv;
etime /= (float) hz;
for(i=0; i < DK_NDRIVE; i++){
rec[iter].dk[i] = s.xfer[i]/etime;
}
rec[iter].in= (rate.v_intr/nintv) - hz;
rec[iter].sy = rate.v_syscall/nintv;
rec[iter].cs = rate.v_swtch/nintv;
for(i=0; i<CPUSTATES; i++) {
f = stat1(i);
if (i == 0) { /* US+NI */
i++;
f += stat1(i);
}
rec[iter].syste[i-1] = f;
}
nintv = 1;
count++;
if (count >= MAXRPT)
if ( (count % MAXRPT) == 0)
if(TERM == 0)
ptoutput(iter+1);
if(TERM)
{
for(w=0; w <max_win; w++){
wprintw(win[w],"mem[avm fre] pag[%5s pi po fr de sr] flt[in sy cs] cpu[us sy id]\n",
swflag ? "si so" : "re at");
for(i=0; i < (iter+1); i++){
wprintw(win[w],"%7d%7d %4d%3d%4d%4d%4d%4d%4d %5d %4d %4d ",
rec[i].avm,rec[i].fre, rec[i].pgre,rec[i].pgat,
rec[i].pi,rec[i].po,rec[i].fr, rec[i].de,rec[i].sr,
rec[i].in,rec[i].sy,rec[i].cs);
for(j=0; j<( CPUSTATES -1); j++)
wprintw(win[w],"%3.0f",rec[i].syste[j]);
wprintw(win[w],"\n");
}
for(i=(iter+1); i<repcnt; i++)
wprintw(win[w],"\n");
wprintw(win[w],"pro[r b w]Dsk[");
}
for (i=0; i < DK_NDRIVE; i++){
if(dr_name[i][0] !='?')
wprintw(win[dr_win[i]]," %3.3s",dr_name[i]);
}
for(w=0; w < max_win; w++)
wprintw(win[w],"]");
for(i=0; i < (iter+1); i++){
for(w=0; w < max_win; w++){
wprintw(win[w],"\n");
wprintw(win[w]," %2d%2d%2d ",rec[i].r,rec[i].b,rec[i].w);
}
for(j=0; j<DK_NDRIVE; j++){
if(dr_name[j][0] !='?')
wprintw(win[dr_win[j]]," %3.0f",rec[i].dk[j]);
}
}
for (i=(iter+1); i< repcnt+1; i++) /* add 1 more linefeed */
for(w=0; w < max_win; w++){
wprintw(win[w],"\n");
}
for(w =0; w < max_win; w++){
if (max_win > 1 ){
wmove(win[w],NLINES-1,0);
wprintw(win[w],"More mounted disk set display: type [0-%x] to select or [r] to rotate" ,(max_win-1));
}
wmove(win[w],0,0);
}
window=win[deft];
touchwin(window);
wrefresh(window);
}
if (totrep > 0)
totrep--;
iter++;
if (count >= MAXRPT ){
for(i=0; i < (MAXRPT -1); i++){
shiftarray(i,1);
}
iter = MAXRPT-1;
}
if (totrep != 0 ){
if(argc > 0) {
w_sv=deft;
sleeptime=atoi(argv[0]);
if (TERM){
if (recurflg){
wrnd=(max_win-deft);
wsleep=(int)(sleeptime/(wrnd+1));
if(wsleep < 1) recurflg=0;
else{
for(w=0; w< wrnd; w++){
w_sv=wtimed_ch(window,wsleep);
window=win[w+deft];
touchwin(window);
wrefresh(window);
}
}
w_sv=wtimed_ch(window,sleeptime-(wrnd*wsleep));
}
else {
w_sv=wtimed_ch(window,sleeptime);
}
if(w_sv >= 0 && w_sv < max_win) deft=w_sv;
if(recurflg && deft == max_win-1) recurflg=0;
}
else
sleep(sleeptime);
goto loop;
}
}
if(TERM)
dietty();
else {
die();
}
}
dotimes()
{
lseek(mf, (long)nli[X_REC].n_value, 0);
read(mf, &s.rectime, sizeof s.rectime);
lseek(mf, (long)nli[X_PGIN].n_value, 0);
read(mf, &s.pgintime, sizeof s.pgintime);
lseek(mf, (long)nli[X_SUM].n_value, 0);
read(mf, &sum, sizeof sum);
printf("%d reclaims, %d total time (usec)\n", sum.v_pgrec, s.rectime);
printf("average: %d usec / reclaim\n", s.rectime/sum.v_pgrec);
printf("\n");
printf("%d page ins, %d total time (msec)\n",sum.v_pgin, s.pgintime/10);
printf("average: %8.1f msec / page in\n", s.pgintime/(sum.v_pgin*10.0));
}
dosum()
{
lseek(mf, (long)nli[X_SUM].n_value, 0);
read(mf, &sum, sizeof sum);
printf("%9d swap ins\n", sum.v_swpin);
printf("%9d swap outs\n", sum.v_swpout);
printf("%9d pages swapped in\n", sum.v_pswpin / CLSIZE);
printf("%9d pages swapped out\n", sum.v_pswpout / CLSIZE);
printf("%9d total address trans. faults taken\n", sum.v_faults);
printf("%9d page ins\n", sum.v_pgin);
printf("%9d page outs\n", sum.v_pgout);
printf("%9d pages paged in\n", sum.v_pgpgin);
printf("%9d pages paged out\n", sum.v_pgpgout);
printf("%9d sequential process pages freed\n", sum.v_seqfree);
printf("%9d total reclaims (%d%% fast)\n", sum.v_pgrec,
(sum.v_fastpgrec * 100) / (sum.v_pgrec == 0 ? 1 : sum.v_pgrec));
printf("%9d reclaims from free list\n", sum.v_pgfrec);
printf("%9d intransit blocking page faults\n", sum.v_intrans);
printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE);
printf("%9d zero fill page faults\n", sum.v_zfod / CLSIZE);
printf("%9d executable fill pages created\n", sum.v_nexfod / CLSIZE);
printf("%9d executable fill page faults\n", sum.v_exfod / CLSIZE);
printf("%9d swap text pages found in free list\n", sum.v_xsfrec);
printf("%9d inode text pages found in free list\n", sum.v_xifrec);
printf("%9d file fill pages created\n", sum.v_nvrfod / CLSIZE);
printf("%9d file fill page faults\n", sum.v_vrfod / CLSIZE);
printf("%9d pages examined by the clock daemon\n", sum.v_scan);
printf("%9d revolutions of the clock hand\n", sum.v_rev);
printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE);
printf("%9d cpu context switches\n", sum.v_swtch);
printf("%9d device interrupts\n", sum.v_intr);
printf("%9d pseduo-dma dz interrupts\n", sum.v_pdma);
printf("%9d traps\n", sum.v_trap);
printf("%9d system calls\n", sum.v_syscall);
}
doforkst()
{
lseek(mf, (long)nli[X_FORKSTAT].n_value, 0);
read(mf, &forkstat, sizeof forkstat);
printf("%d forks, %d pages, average=%.2f\n",
forkstat.cntfork, forkstat.sizfork,
(float) forkstat.sizfork / forkstat.cntfork);
printf("%d vforks, %d pages, average=%.2f\n",
forkstat.cntvfork, forkstat.sizvfork,
(float)forkstat.sizvfork / forkstat.cntvfork);
}
stats(dn)
{
if (dn >= DK_NDRIVE) {
printf(" 0");
return;
}
printf("%3.0f", s.xfer[dn]/etime);
}
double
stat1(row)
{
double t;
register i;
t = 0;
for(i=0; i<CPUSTATES; i++)
t += s.time[i];
if(t == 0.)
t = 1.;
return(s.time[row]*100./t);
}
pct(top, bot)
{
if (bot == 0)
return (0);
return ((top * 100) / bot);
}
#define steal(where, var) lseek(mf, where, 0); read(mf, &var, sizeof var);
read_names()
{
struct vba_device udev, *up;
struct vba_driver udrv;
int unit, i;
int wcnt;
up = (struct vba_device *) nli[X_VBDINIT].n_value;
if (up == 0)
{
fprintf(stderr, "vmstat: Disk init info not in namelist\n");
exit(1);
}
vdinfo_save = vdinfo;
wno=0;
wcnt=0;
for (;;) {
steal(up++, udev);
unit = (udev.ui_ctlr * 4) + udev.ui_slave;
if (udev.ui_driver == 0)
break;
if (udev.ui_dk <= 0 || udev.ui_alive == 0)
continue;
if(udev.ui_type >= nodktyp){
fprintf(stderr,"vmstat : disk type in unit %d not supported \n",unit);
exit(1);
}
if (wcnt >=PART){
wcnt=0;
wno++;
}
if(wno > MAX_PART){
fprintf(stderr, "vmstat : maximum partition of display exceeded \n");
exit(1);
}
vdinfo = vdinfo_save;
for(i=0; i < udev.ui_type; i++)
vdinfo++;
dr_name[unit][0] = vdinfo->type_name[0];
/* dr_name[unit][1] = vdinfo->type_name[1]; */
dr_win[unit]=wno;
wcnt++;
}
}
die()
{
int i,j,k;
iter--;
signal(SIGINT,SIG_IGN);
i = count % MAXRPT;
if (count >= MAXRPT){
k = MAXRPT - i;
for (j=0; j <i; j++)
shiftarray(0,k);
}
ptoutput(i);
exit(0);
}
dietty()
{
signal(SIGINT,SIG_IGN);
signal(SIGBUS,SIG_IGN);
signal(SIGSEGV,SIG_IGN);
mvcur(0,NCOLS-1, NLINES-1,0);
endwin();
exit(0);
}
ptoutput(reptot)
int reptot;
{
register i,j;
printf("mem[avm fre] pag[%5s pi po fr de sr] fault[in sy cs] cpu[us sy id]\n", swflag ? "si so" : "re at");
for(i=0; i < (reptot); i++){
printf(" %6d%5d %4d%3d%4d%4d%4d%4d%4d %4d%4d%4d ",
rec[i].avm,rec[i].fre, rec[i].pgre,rec[i].pgat,
rec[i].pi,rec[i].po,rec[i].fr, rec[i].de,rec[i].sr,
rec[i].in,rec[i].sy,rec[i].cs);
for(j=0; j<( CPUSTATES -1); j++)
printf("%3.0f",rec[i].syste[j]);
printf("\n");
}
for(i=(reptot); i<repcnt; i++)
printf("\n");
printf("proc[r b w]Dsk[");
for (i=0; i < DK_NDRIVE; i++)
if(dr_name[i][0] !='?')
printf("%3.3s ",dr_name[i]);
printf("]\n");
for(i=0; i < (reptot); i++){
printf(" %2d%2d%2d ",rec[i].r,rec[i].b,rec[i].w);
for(j=0; j<DK_NDRIVE; j++)
if(dr_name[j][0] !='?')
printf("%3.0f ",rec[i].dk[j]);
printf("\n");
}
for (i=(reptot); i< repcnt; i++)
printf("\n");
}
shiftarray(srtary,offset)
int srtary; /* starting array to be shifted */
int offset; /* offset to be skip in shifting array */
{
register j;
rec[srtary].r = rec[srtary+offset].r;
rec[srtary].b = rec[srtary+offset].b;
rec[srtary].w = rec[srtary+offset].w;
rec[srtary].avm = rec[srtary+offset].avm;
rec[srtary].fre = rec[srtary+offset].fre;
rec[srtary].pgre = rec[srtary+offset].pgre;
rec[srtary].pgat = rec[srtary+offset].pgat;
rec[srtary].pi = rec[srtary+offset].pi;
rec[srtary].po = rec[srtary+offset].po;
rec[srtary].fr = rec[srtary+offset].fr;
rec[srtary].de = rec[srtary+offset].de;
rec[srtary].sr = rec[srtary+offset].sr;
for(j=0; j < DK_NDRIVE; j++)
rec[srtary].dk[j] = rec[srtary+offset].dk[j];
rec[srtary].in = rec[srtary+offset].in;
rec[srtary].sy = rec[srtary+offset].sy;
rec[srtary].cs = rec[srtary+offset].cs;
for(j=0; j < (CPUSTATES-1); j++)
rec[srtary].syste[j] = rec[srtary+offset].syste[j];
}
timer()
{
signal(SIGALRM, timer);
longjmp(jb,1);
}
int wtimed_ch(win, seconds)
WINDOW *win;
int seconds;
{
int ch = '\0';
int w;
int deft = -1;
if(setjmp(jb) == 0)
{
do{
alarm(seconds);
ch = wgetch(win);
if(ch == 'r') {
deft= -2;
recurflg=1;
}
w=ch-'0';
if (w < max_win && w >=0) {
recurflg=0;
deft=w;
}
w=ch -'A' +10;
if (w < max_win && w >= 10){
recurflg=0;
deft=w;
}
else ;
seconds = alarm(0);
} while (ch != 'r'|| deft <0 );
}
return(deft);
}
terminate() /* SIGINT handler */
{
endwin();
exit(0);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.