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