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