File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / usr / src / ucb / vmstat.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Sun Jul 28 12:29:18 2019 UTC (7 years ago) by root
Branches: bsd, MAIN
CVS tags: v121, HEAD
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);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.