xref: /csrg-svn/usr.bin/pascal/pxp/pmon.c (revision 62191)
148112Sbostic /*-
2*62191Sbostic  * Copyright (c) 1980, 1993
3*62191Sbostic  *	The Regents of the University of California.  All rights reserved.
448112Sbostic  *
548112Sbostic  * %sccs.include.redist.c%
622233Sdist  */
722233Sdist 
822233Sdist #ifndef lint
9*62191Sbostic static char sccsid[] = "@(#)pmon.c	8.1 (Berkeley) 06/06/93";
1048112Sbostic #endif /* not lint */
1122233Sdist 
1222233Sdist /*
132860Speter  * pxp - Pascal execution profiler
142860Speter  *
152860Speter  * Bill Joy UCB
162860Speter  * Version 1.2 January 1979
172860Speter  */
182860Speter 
192860Speter #include "0.h"
202860Speter 
212860Speter /*
222860Speter  * Profile counter processing cluster
232860Speter  *
242860Speter  * This file contains all routines which do the hard work in profiling.
252860Speter  *
262860Speter  * The first group of routines (getit, getpmon, getcore, and pmread)
272860Speter  * deal with extracting data from the pmon.out and (with more difficulty)
282860Speter  * core files.
292860Speter  *
302860Speter  * The routines cnttab and prttab collect counters for
312860Speter  * and print the summary table respectively.
322860Speter  *
332860Speter  * The routines "*cnt*" deal with manipulation of counters,
342860Speter  * especially the "current" counter px.
352860Speter  */
362860Speter STATIC	struct pxcnt px;
372860Speter 
382860Speter /*
392860Speter  * Table to record info
402860Speter  * for procedure/function summary
412860Speter  */
422860Speter STATIC	struct pftab {
432860Speter 	long	pfcnt;
442860Speter 	short	pfline;
452860Speter 	char	*pfname;
462860Speter 	short	pflev;
472860Speter } *zpf;
482860Speter 
492860Speter /*
502860Speter  * Global variables
512860Speter  */
522860Speter STATIC	long *zbuf; 	/* Count buffer */
532860Speter STATIC	short zcnt;	/* Number of counts */
542860Speter STATIC	short zpfcnt;	/* Number of proc/funcs's */
552860Speter STATIC	short gcountr;	/* Unique name generator */
562860Speter STATIC	short zfil;	/* I/o unit for count data reads */
572860Speter STATIC	short lastpf;	/* Total # of procs and funcs for consistency chk */
582860Speter 
getit(fp)592860Speter getit(fp)
602860Speter 	register char *fp;
612860Speter {
622860Speter 
632860Speter 	if (core)
642860Speter 		getcore(fp);
652860Speter 	else
662860Speter 		getpmon(fp);
672860Speter }
682860Speter 
692860Speter /*
702860Speter  * Setup monitor data buffer from pmon.out
712860Speter  * style file whose name is fp.
722860Speter  */
getpmon(fp)732860Speter getpmon(fp)
742860Speter 	char *fp;
752860Speter {
762860Speter 	register char *cp;
772860Speter 	short garbage;
782860Speter 
792860Speter 	zfil = open(fp, 0);
802860Speter 	if (zfil < 0) {
812860Speter 		perror(fp);
822860Speter 		pexit(NOSTART);
832860Speter 	}
842860Speter 	if (pmread() < 0 || read(zfil, &garbage, 1) == 1) {
852860Speter 		Perror(fp, "Bad format for pmon.out style file");
862860Speter 		exit(1);
872860Speter 	}
882860Speter 	close(zfil);
892860Speter 	return;
902860Speter }
912860Speter 
923051Smckusic STATIC	char nospcm[]	= "Not enough memory for count buffers\n";
932860Speter 
pmnospac()942860Speter pmnospac()
952860Speter {
962860Speter 
972860Speter 	write(2, nospcm, sizeof nospcm);
982860Speter 	pexit(NOSTART);
992860Speter }
1002860Speter 
1012860Speter /*
1022860Speter  * Structure of the first few
1032860Speter  * items of a px core dump.
1042860Speter  */
1052860Speter STATIC	struct info {
1062860Speter 	char	*off;		/* Self-reference for pure text */
1072860Speter 	short	type;		/* 0 = non-pure text, 1 = pure text */
1082860Speter 	char	*bp;		/* Core address of pxps struct */
1092860Speter } inf;
1102860Speter 
1112860Speter /*
1122860Speter  * First few words of the px
1132860Speter  * information structure.
1142860Speter  */
1152860Speter STATIC	struct pxps {
1162860Speter 	char	*buf;
1172860Speter 	short	cnt;
1182860Speter } pxp;
1192860Speter 
getcore(fp)1202860Speter getcore(fp)
1212860Speter 	char *fp;
1222860Speter {
1232860Speter 
1242860Speter 	write(2, "-c: option not supported\n", sizeof("-c: option not supported\n"));
1252860Speter 	pexit(ERRS);
1262860Speter /*
1272860Speter 	short pm;
1282860Speter 
1292860Speter 	zfil = open(fp, 0);
1302860Speter 	if (zfil < 0) {
1312860Speter 		perror(fp);
1322860Speter 		pexit(NOSTART);
1332860Speter 	}
1342860Speter 	if (lseek(zfil, 02000, 0) < 0)
1352860Speter 		goto format;
1362860Speter 	if (read(zfil, &inf, sizeof inf) < 0)
1372860Speter 		goto format;
1382860Speter 	if (inf.type != 0 && inf.type != 1)
1392860Speter 		goto format;
1402860Speter 	if (inf.type)
14132763Sbostic 		inf.bp -= inf.off;
1422860Speter 	if (lseek(zfil, inf.bp + 02000, 0) < 0)
1432860Speter 		goto format;
1442860Speter 	if (read(zfil, &pxp, sizeof pxp) != sizeof pxp)
1452860Speter 		goto format;
1462860Speter 	if (pxp.buf == NIL) {
1472860Speter 		Perror(fp, "No profile data in file");
1482860Speter 		exit(1);
1492860Speter 	}
1502860Speter 	if (inf.type)
15132763Sbostic 		pxp.buf -= inf.off;
1522860Speter 	if (lseek(zfil, pxp.buf + 02000, 0) < 0)
1532860Speter 		goto format;
1542860Speter 	if (pmread() < 0)
1552860Speter 		goto format;
1562860Speter 	close(zfil);
1572860Speter 	return;
1582860Speter format:
1592860Speter 	Perror(fp, "Not a Pascal system core file");
1602860Speter 	exit(1);
1612860Speter */
1622860Speter }
1632860Speter 
pmread()1642860Speter pmread()
1652860Speter {
1662860Speter 	register i;
1672860Speter 	register char *cp;
1682860Speter 	struct {
1692860Speter 		long	no;
1702860Speter 		long	tim;
1712860Speter 		long	cntrs;
1722860Speter 		long	rtns;
1732860Speter 	} zmagic;
1742860Speter 
1752860Speter 	if (read(zfil, &zmagic, sizeof zmagic) != sizeof zmagic)
1762860Speter 		return (-1);
1772860Speter 	if (zmagic.no != 0426)
1782860Speter 		return (-1);
1792860Speter 	ptvec = zmagic.tim;
1802860Speter 	zcnt = zmagic.cntrs;
1812860Speter 	zpfcnt = zmagic.rtns;
18217685Smckusick 	cp = zbuf = pcalloc(i = (zcnt + 1) * sizeof *zbuf, 1);
18333240Sbostic 	if (cp == NULL)
1842860Speter 		pmnospac();
18517685Smckusick 	cp = zpf = pcalloc(zpfcnt * sizeof *zpf, 1);
18633240Sbostic 	if (cp == NULL)
1872860Speter 		pmnospac();
1882860Speter 	i -= sizeof(zmagic);
1893051Smckusic 	if (read(zfil, zbuf + (sizeof(zmagic) / sizeof(*zbuf)), i) != i)
1902860Speter 		return (-1);
1912860Speter 	zbuf++;
1922860Speter 	return (0);
1932860Speter }
1942860Speter 
cnttab(s,no)1952860Speter cnttab(s, no)
1962860Speter 	char *s;
1972860Speter 	short no;
1982860Speter {
1992860Speter 	register struct pftab *pp;
2002860Speter 
2012860Speter 	lastpf++;
2022860Speter 	if (table == 0)
2032860Speter 		return;
2042860Speter 	if (no == zpfcnt)
2052860Speter 		cPANIC();
2062860Speter 	pp = &zpf[no];
2072860Speter 	pp->pfname = s;
2082860Speter 	pp->pfline = line;
2092860Speter 	pp->pfcnt = nowcnt();
2102860Speter 	pp->pflev = cbn;
2112860Speter }
2122860Speter 
prttab()2132860Speter prttab()
2142860Speter {
2152860Speter 	register i, j;
2162860Speter 	register struct pftab *zpfp;
2172860Speter 
2182860Speter 	if (profile == 0 && table == 0)
2192860Speter 		return;
2202860Speter 	if (cnts != zcnt || lastpf != zpfcnt)
2212860Speter 		cPANIC();
2222860Speter 	if (table == 0)
2232860Speter 		return;
2242860Speter 	if (profile)
2252860Speter 		printf("\f\n");
2262860Speter 	header();
2272860Speter 	printf("\n\tLine\t   Count\n\n");
2282860Speter 	zpfp = zpf;
2292860Speter 	for (i = 0; i < zpfcnt; i++) {
2302860Speter 		printf("\t%4d\t%8ld\t", zpfp->pfline, zpfp->pfcnt);
2312860Speter 		if (!justify)
2322860Speter 			for (j = zpfp->pflev * unit; j > 1; j--)
2332860Speter 				putchar(' ');
2342860Speter 		printf("%s\n", zpfp->pfname);
2352860Speter 		zpfp++;
2362860Speter 	}
2372860Speter }
2382860Speter 
nowcntr()2392860Speter nowcntr()
2402860Speter {
2412860Speter 
2422860Speter 	return (px.counter);
2432860Speter }
2442860Speter 
nowcnt()2452860Speter long nowcnt()
2462860Speter {
2472860Speter 
2482860Speter 	return (px.ntimes);
2492860Speter }
2502860Speter 
cntof(pxc)2512860Speter long cntof(pxc)
2522860Speter 	struct pxcnt *pxc;
2532860Speter {
2542860Speter 
2552860Speter 	if (profile == 0 && table == 0)
2562860Speter 		return;
2572860Speter 	return (pxc->ntimes);
2582860Speter }
2592860Speter 
setcnt(l)2602860Speter setcnt(l)
2612860Speter 	long l;
2622860Speter {
2632860Speter 
2642860Speter 	if (profile == 0 && table == 0)
2652860Speter 		return;
2662860Speter 	px.counter = --gcountr;
2672860Speter 	px.ntimes = l;
2682860Speter 	px.gos = gocnt;
2692860Speter 	px.printed = 0;
2702860Speter }
2712860Speter 
savecnt(pxc)2722860Speter savecnt(pxc)
2732860Speter 	register struct pxcnt *pxc;
2742860Speter {
2752860Speter 
2762860Speter 	if (profile == 0 && table == 0)
2772860Speter 		return;
2782860Speter 	pxc->ntimes = px.ntimes;
2792860Speter 	pxc->counter = px.counter;
2802860Speter 	pxc->gos = px.gos;
2812860Speter 	pxc->printed = 1;
2822860Speter }
2832860Speter 
rescnt(pxc)2842860Speter rescnt(pxc)
2852860Speter 	register struct pxcnt *pxc;
2862860Speter {
2872860Speter 
2882860Speter 	if (profile == 0 && table == 0)
2892860Speter 		return;
2902860Speter 	px.ntimes = pxc->ntimes;
2912860Speter 	px.counter = pxc->counter;
2922860Speter 	px.gos = gocnt;
2932860Speter 	px.printed = pxc->printed;
2942860Speter 	return (gocnt != pxc->gos);
2952860Speter }
2962860Speter 
getcnt()2972860Speter getcnt()
2982860Speter {
2992860Speter 
3002860Speter 	if (profile == 0 && table == 0)
3012860Speter 		return;
3022860Speter 	if (cnts == zcnt)
3032860Speter 		cPANIC();
3042860Speter 	px.counter = cnts;
3052860Speter 	px.ntimes = zbuf[cnts];
3062860Speter 	px.gos = gocnt;
3072860Speter 	px.printed = 0;
3082860Speter 	++cnts;
3092860Speter }
3102860Speter 
unprint()3112860Speter unprint()
3122860Speter {
3132860Speter 
3142860Speter 	px.printed = 0;
3152860Speter }
3162860Speter 
3172860Speter /*
3182860Speter  * Control printing of '|'
3192860Speter  * when profiling.
3202860Speter  */
3212860Speter STATIC	char	nobar;
3222860Speter 
baroff()3232860Speter baroff()
3242860Speter {
3252860Speter 
3262860Speter 	nobar = 1;
3272860Speter }
3282860Speter 
baron()3292860Speter baron()
3302860Speter {
3312860Speter 
3322860Speter 	nobar = 0;
3332860Speter }
3342860Speter 
3352860Speter /*
3362860Speter  * Do we want cnt and/or '|' on this line ?
3372860Speter  *	1 = count and '|'
3382860Speter  *	0 = only '|'
3392860Speter  *     -1 = spaces only
3402860Speter  */
shudpcnt()3412860Speter shudpcnt()
3422860Speter {
3432860Speter 
3442860Speter 	register i;
3452860Speter 
3462860Speter 	if (nobar)
3472860Speter 		return (-1);
3482860Speter 	i = px.printed;
3492860Speter 	px.printed = 1;
3502860Speter 	return (i == 0);
3512860Speter }
3522860Speter 
3533051Smckusic STATIC	char mism[]	= "Program and counter data do not correspond\n";
3542860Speter 
cPANIC()3552860Speter cPANIC()
3562860Speter {
3572860Speter 
3582860Speter 	printf("cnts %d zcnt %d, lastpf %d zpfcnt %d\n",
3592860Speter 		cnts, zcnt, lastpf, zpfcnt);
3602860Speter 	flush();
3612860Speter 	write(2, mism, sizeof mism);
3622860Speter 	pexit(ERRS);
3632860Speter }
364