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