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