|
|
1.1 root 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.1 (Berkeley) 6/5/85";
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 == -1)
183: pmnospac();
184: cp = zpf = pcalloc(zpfcnt * sizeof *zpf, 1);
185: if (cp == -1)
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.