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