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