xref: /csrg-svn/usr.bin/pascal/pxp/pmon.c (revision 2860)
1*2860Speter static	char *sccsid = "@(#)pmon.c	1.1 (Berkeley) 03/02/81";
2*2860Speter /* Copyright (c) 1979 Regents of the University of California */
3*2860Speter #
4*2860Speter /*
5*2860Speter  * pxp - Pascal execution profiler
6*2860Speter  *
7*2860Speter  * Bill Joy UCB
8*2860Speter  * Version 1.2 January 1979
9*2860Speter  */
10*2860Speter 
11*2860Speter #include "0.h"
12*2860Speter 
13*2860Speter /*
14*2860Speter  * Profile counter processing cluster
15*2860Speter  *
16*2860Speter  * This file contains all routines which do the hard work in profiling.
17*2860Speter  *
18*2860Speter  * The first group of routines (getit, getpmon, getcore, and pmread)
19*2860Speter  * deal with extracting data from the pmon.out and (with more difficulty)
20*2860Speter  * core files.
21*2860Speter  *
22*2860Speter  * The routines cnttab and prttab collect counters for
23*2860Speter  * and print the summary table respectively.
24*2860Speter  *
25*2860Speter  * The routines "*cnt*" deal with manipulation of counters,
26*2860Speter  * especially the "current" counter px.
27*2860Speter  */
28*2860Speter STATIC	struct pxcnt px;
29*2860Speter 
30*2860Speter /*
31*2860Speter  * Table to record info
32*2860Speter  * for procedure/function summary
33*2860Speter  */
34*2860Speter STATIC	struct pftab {
35*2860Speter 	long	pfcnt;
36*2860Speter 	short	pfline;
37*2860Speter 	char	*pfname;
38*2860Speter 	short	pflev;
39*2860Speter } *zpf;
40*2860Speter 
41*2860Speter /*
42*2860Speter  * Global variables
43*2860Speter  */
44*2860Speter STATIC	long *zbuf; 	/* Count buffer */
45*2860Speter STATIC	short zcnt;	/* Number of counts */
46*2860Speter STATIC	short zpfcnt;	/* Number of proc/funcs's */
47*2860Speter STATIC	short gcountr;	/* Unique name generator */
48*2860Speter STATIC	short zfil;	/* I/o unit for count data reads */
49*2860Speter STATIC	short lastpf;	/* Total # of procs and funcs for consistency chk */
50*2860Speter 
51*2860Speter getit(fp)
52*2860Speter 	register char *fp;
53*2860Speter {
54*2860Speter 
55*2860Speter 	if (core)
56*2860Speter 		getcore(fp);
57*2860Speter 	else
58*2860Speter 		getpmon(fp);
59*2860Speter }
60*2860Speter 
61*2860Speter /*
62*2860Speter  * Setup monitor data buffer from pmon.out
63*2860Speter  * style file whose name is fp.
64*2860Speter  */
65*2860Speter getpmon(fp)
66*2860Speter 	char *fp;
67*2860Speter {
68*2860Speter 	register char *cp;
69*2860Speter 	short garbage;
70*2860Speter 
71*2860Speter 	zfil = open(fp, 0);
72*2860Speter 	if (zfil < 0) {
73*2860Speter 		perror(fp);
74*2860Speter 		pexit(NOSTART);
75*2860Speter 	}
76*2860Speter 	if (pmread() < 0 || read(zfil, &garbage, 1) == 1) {
77*2860Speter 		Perror(fp, "Bad format for pmon.out style file");
78*2860Speter 		exit(1);
79*2860Speter 	}
80*2860Speter 	close(zfil);
81*2860Speter 	return;
82*2860Speter }
83*2860Speter 
84*2860Speter STATIC	char nospcm[]	"Not enough memory for count buffers\n";
85*2860Speter 
86*2860Speter pmnospac()
87*2860Speter {
88*2860Speter 
89*2860Speter 	write(2, nospcm, sizeof nospcm);
90*2860Speter 	pexit(NOSTART);
91*2860Speter }
92*2860Speter 
93*2860Speter /*
94*2860Speter  * Structure of the first few
95*2860Speter  * items of a px core dump.
96*2860Speter  */
97*2860Speter STATIC	struct info {
98*2860Speter 	char	*off;		/* Self-reference for pure text */
99*2860Speter 	short	type;		/* 0 = non-pure text, 1 = pure text */
100*2860Speter 	char	*bp;		/* Core address of pxps struct */
101*2860Speter } inf;
102*2860Speter 
103*2860Speter /*
104*2860Speter  * First few words of the px
105*2860Speter  * information structure.
106*2860Speter  */
107*2860Speter STATIC	struct pxps {
108*2860Speter 	char	*buf;
109*2860Speter 	short	cnt;
110*2860Speter } pxp;
111*2860Speter 
112*2860Speter getcore(fp)
113*2860Speter 	char *fp;
114*2860Speter {
115*2860Speter 
116*2860Speter 	write(2, "-c: option not supported\n", sizeof("-c: option not supported\n"));
117*2860Speter 	pexit(ERRS);
118*2860Speter /*
119*2860Speter 	short pm;
120*2860Speter 
121*2860Speter 	zfil = open(fp, 0);
122*2860Speter 	if (zfil < 0) {
123*2860Speter 		perror(fp);
124*2860Speter 		pexit(NOSTART);
125*2860Speter 	}
126*2860Speter 	if (lseek(zfil, 02000, 0) < 0)
127*2860Speter 		goto format;
128*2860Speter 	if (read(zfil, &inf, sizeof inf) < 0)
129*2860Speter 		goto format;
130*2860Speter 	if (inf.type != 0 && inf.type != 1)
131*2860Speter 		goto format;
132*2860Speter 	if (inf.type)
133*2860Speter 		inf.bp =- inf.off;
134*2860Speter 	if (lseek(zfil, inf.bp + 02000, 0) < 0)
135*2860Speter 		goto format;
136*2860Speter 	if (read(zfil, &pxp, sizeof pxp) != sizeof pxp)
137*2860Speter 		goto format;
138*2860Speter 	if (pxp.buf == NIL) {
139*2860Speter 		Perror(fp, "No profile data in file");
140*2860Speter 		exit(1);
141*2860Speter 	}
142*2860Speter 	if (inf.type)
143*2860Speter 		pxp.buf =- inf.off;
144*2860Speter 	if (lseek(zfil, pxp.buf + 02000, 0) < 0)
145*2860Speter 		goto format;
146*2860Speter 	if (pmread() < 0)
147*2860Speter 		goto format;
148*2860Speter 	close(zfil);
149*2860Speter 	return;
150*2860Speter format:
151*2860Speter 	Perror(fp, "Not a Pascal system core file");
152*2860Speter 	exit(1);
153*2860Speter */
154*2860Speter }
155*2860Speter 
156*2860Speter pmread()
157*2860Speter {
158*2860Speter 	register i;
159*2860Speter 	register char *cp;
160*2860Speter 	struct {
161*2860Speter 		long	no;
162*2860Speter 		long	tim;
163*2860Speter 		long	cntrs;
164*2860Speter 		long	rtns;
165*2860Speter 	} zmagic;
166*2860Speter 
167*2860Speter 	if (read(zfil, &zmagic, sizeof zmagic) != sizeof zmagic)
168*2860Speter 		return (-1);
169*2860Speter 	if (zmagic.no != 0426)
170*2860Speter 		return (-1);
171*2860Speter 	ptvec = zmagic.tim;
172*2860Speter 	zcnt = zmagic.cntrs;
173*2860Speter 	zpfcnt = zmagic.rtns;
174*2860Speter 	cp = zbuf = alloc(i = (zcnt + 1) * sizeof *zbuf);
175*2860Speter 	if (cp == -1)
176*2860Speter 		pmnospac();
177*2860Speter 	cp = zpf = alloc(zpfcnt * sizeof *zpf);
178*2860Speter 	if (cp == -1)
179*2860Speter 		pmnospac();
180*2860Speter 	i -= sizeof(zmagic);
181*2860Speter 	if (read(zfil, zbuf + (sizeof(zmagic) / sizeof(zbuf)), i) != i)
182*2860Speter 		return (-1);
183*2860Speter 	zbuf++;
184*2860Speter 	return (0);
185*2860Speter }
186*2860Speter 
187*2860Speter cnttab(s, no)
188*2860Speter 	char *s;
189*2860Speter 	short no;
190*2860Speter {
191*2860Speter 	register struct pftab *pp;
192*2860Speter 
193*2860Speter 	lastpf++;
194*2860Speter 	if (table == 0)
195*2860Speter 		return;
196*2860Speter 	if (no == zpfcnt)
197*2860Speter 		cPANIC();
198*2860Speter 	pp = &zpf[no];
199*2860Speter 	pp->pfname = s;
200*2860Speter 	pp->pfline = line;
201*2860Speter 	pp->pfcnt = nowcnt();
202*2860Speter 	pp->pflev = cbn;
203*2860Speter }
204*2860Speter 
205*2860Speter prttab()
206*2860Speter {
207*2860Speter 	register i, j;
208*2860Speter 	register struct pftab *zpfp;
209*2860Speter 
210*2860Speter 	if (profile == 0 && table == 0)
211*2860Speter 		return;
212*2860Speter 	if (cnts != zcnt || lastpf != zpfcnt)
213*2860Speter 		cPANIC();
214*2860Speter 	if (table == 0)
215*2860Speter 		return;
216*2860Speter 	if (profile)
217*2860Speter 		printf("\f\n");
218*2860Speter 	header();
219*2860Speter 	printf("\n\tLine\t   Count\n\n");
220*2860Speter 	zpfp = zpf;
221*2860Speter 	for (i = 0; i < zpfcnt; i++) {
222*2860Speter 		printf("\t%4d\t%8ld\t", zpfp->pfline, zpfp->pfcnt);
223*2860Speter 		if (!justify)
224*2860Speter 			for (j = zpfp->pflev * unit; j > 1; j--)
225*2860Speter 				putchar(' ');
226*2860Speter 		printf("%s\n", zpfp->pfname);
227*2860Speter 		zpfp++;
228*2860Speter 	}
229*2860Speter }
230*2860Speter 
231*2860Speter nowcntr()
232*2860Speter {
233*2860Speter 
234*2860Speter 	return (px.counter);
235*2860Speter }
236*2860Speter 
237*2860Speter long nowcnt()
238*2860Speter {
239*2860Speter 
240*2860Speter 	return (px.ntimes);
241*2860Speter }
242*2860Speter 
243*2860Speter long cntof(pxc)
244*2860Speter 	struct pxcnt *pxc;
245*2860Speter {
246*2860Speter 
247*2860Speter 	if (profile == 0 && table == 0)
248*2860Speter 		return;
249*2860Speter 	return (pxc->ntimes);
250*2860Speter }
251*2860Speter 
252*2860Speter setcnt(l)
253*2860Speter 	long l;
254*2860Speter {
255*2860Speter 
256*2860Speter 	if (profile == 0 && table == 0)
257*2860Speter 		return;
258*2860Speter 	px.counter = --gcountr;
259*2860Speter 	px.ntimes = l;
260*2860Speter 	px.gos = gocnt;
261*2860Speter 	px.printed = 0;
262*2860Speter }
263*2860Speter 
264*2860Speter savecnt(pxc)
265*2860Speter 	register struct pxcnt *pxc;
266*2860Speter {
267*2860Speter 
268*2860Speter 	if (profile == 0 && table == 0)
269*2860Speter 		return;
270*2860Speter 	pxc->ntimes = px.ntimes;
271*2860Speter 	pxc->counter = px.counter;
272*2860Speter 	pxc->gos = px.gos;
273*2860Speter 	pxc->printed = 1;
274*2860Speter }
275*2860Speter 
276*2860Speter rescnt(pxc)
277*2860Speter 	register struct pxcnt *pxc;
278*2860Speter {
279*2860Speter 
280*2860Speter 	if (profile == 0 && table == 0)
281*2860Speter 		return;
282*2860Speter 	px.ntimes = pxc->ntimes;
283*2860Speter 	px.counter = pxc->counter;
284*2860Speter 	px.gos = gocnt;
285*2860Speter 	px.printed = pxc->printed;
286*2860Speter 	return (gocnt != pxc->gos);
287*2860Speter }
288*2860Speter 
289*2860Speter getcnt()
290*2860Speter {
291*2860Speter 
292*2860Speter 	if (profile == 0 && table == 0)
293*2860Speter 		return;
294*2860Speter 	if (cnts == zcnt)
295*2860Speter 		cPANIC();
296*2860Speter 	px.counter = cnts;
297*2860Speter 	px.ntimes = zbuf[cnts];
298*2860Speter 	px.gos = gocnt;
299*2860Speter 	px.printed = 0;
300*2860Speter 	++cnts;
301*2860Speter }
302*2860Speter 
303*2860Speter unprint()
304*2860Speter {
305*2860Speter 
306*2860Speter 	px.printed = 0;
307*2860Speter }
308*2860Speter 
309*2860Speter /*
310*2860Speter  * Control printing of '|'
311*2860Speter  * when profiling.
312*2860Speter  */
313*2860Speter STATIC	char	nobar;
314*2860Speter 
315*2860Speter baroff()
316*2860Speter {
317*2860Speter 
318*2860Speter 	nobar = 1;
319*2860Speter }
320*2860Speter 
321*2860Speter baron()
322*2860Speter {
323*2860Speter 
324*2860Speter 	nobar = 0;
325*2860Speter }
326*2860Speter 
327*2860Speter /*
328*2860Speter  * Do we want cnt and/or '|' on this line ?
329*2860Speter  *	1 = count and '|'
330*2860Speter  *	0 = only '|'
331*2860Speter  *     -1 = spaces only
332*2860Speter  */
333*2860Speter shudpcnt()
334*2860Speter {
335*2860Speter 
336*2860Speter 	register i;
337*2860Speter 
338*2860Speter 	if (nobar)
339*2860Speter 		return (-1);
340*2860Speter 	i = px.printed;
341*2860Speter 	px.printed = 1;
342*2860Speter 	return (i == 0);
343*2860Speter }
344*2860Speter 
345*2860Speter STATIC	char mism[]	"Program and counter data do not correspond\n";
346*2860Speter 
347*2860Speter cPANIC()
348*2860Speter {
349*2860Speter 
350*2860Speter 	printf("cnts %d zcnt %d, lastpf %d zpfcnt %d\n",
351*2860Speter 		cnts, zcnt, lastpf, zpfcnt);
352*2860Speter 	flush();
353*2860Speter 	write(2, mism, sizeof mism);
354*2860Speter 	pexit(ERRS);
355*2860Speter }
356