|
|
1.1 root 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: */
27: STATIC struct pxcnt px;
28:
29: /*
30: * Table to record info
31: * for procedure/function summary
32: */
33: STATIC struct pftab {
34: long pfcnt;
35: short pfline;
36: char *pfname;
37: short pflev;
38: } *zpf;
39:
40: /*
41: * Global variables
42: */
43: STATIC long *zbuf; /* Count buffer */
44: STATIC short zcnt; /* Number of counts */
45: STATIC short zpfcnt; /* Number of proc/funcs's */
46: STATIC short gcountr; /* Unique name generator */
47: STATIC short zfil; /* I/o unit for count data reads */
48: STATIC short lastpf; /* Total # of procs and funcs for consistency chk */
49:
50: getit(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: */
64: getpmon(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:
83: STATIC char nospcm[] "Not enough memory for count buffers\n";
84:
85: pmnospac()
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: */
96: STATIC 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: */
106: STATIC struct pxps {
107: char *buf;
108: short cnt;
109: } pxp;
110:
111: getcore(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;
149: format:
150: Perror(fp, "Not a Pascal system core file");
151: exit(1);
152: */
153: }
154:
155: pmread()
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:
186: cnttab(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:
204: prttab()
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:
230: nowcntr()
231: {
232:
233: return (px.counter);
234: }
235:
236: long nowcnt()
237: {
238:
239: return (px.ntimes);
240: }
241:
242: long cntof(pxc)
243: struct pxcnt *pxc;
244: {
245:
246: if (profile == 0 && table == 0)
247: return;
248: return (pxc->ntimes);
249: }
250:
251: setcnt(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:
263: savecnt(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:
275: rescnt(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:
288: getcnt()
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:
302: unprint()
303: {
304:
305: px.printed = 0;
306: }
307:
308: /*
309: * Control printing of '|'
310: * when profiling.
311: */
312: STATIC char nobar;
313:
314: baroff()
315: {
316:
317: nobar = 1;
318: }
319:
320: baron()
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: */
332: shudpcnt()
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:
344: STATIC char mism[] "Program and counter data do not correspond\n";
345:
346: cPANIC()
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.