1 static char *sccsid = "@(#)pmon.c 1.2 (Berkeley) 03/07/81"; 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 84 STATIC char nospcm[] = "Not enough memory for count buffers\n"; 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); 181 if (read(zfil, zbuf + (sizeof(zmagic) / sizeof(*zbuf)), i) != i) 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 345 STATIC char mism[] = "Program and counter data do not correspond\n"; 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 } 356