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: int tvec[2]; 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[0] = zmagic.tvec[0]; 164: ptvec[1] = zmagic.tvec[1]; 165: if (read(zfil, &zcnt, 2) != 2) 166: return (-1); 167: if (read(zfil, &zpfcnt, 2) != 2) 168: return (-1); 169: cp = zbuf = alloc(i = zcnt * sizeof *zbuf); 170: if (cp == -1) 171: pmnospac(); 172: cp = zpf = alloc(zpfcnt * sizeof *zpf); 173: if (cp == -1) 174: pmnospac(); 175: if (read(zfil, zbuf, i) != i) 176: return (-1); 177: zbuf =- 2; 178: return (0); 179: } 180: 181: cnttab(s, no) 182: char *s; 183: int no; 184: { 185: register struct pftab *pp; 186: 187: lastpf++; 188: if (table == 0) 189: return; 190: if (no == zpfcnt) 191: cPANIC(); 192: pp = &zpf[no]; 193: pp->pfname = s; 194: pp->pfline = line; 195: pp->pfcnt = nowcnt(); 196: pp->pflev = cbn; 197: } 198: 199: prttab() 200: { 201: register i, j; 202: register struct pftab *zpfp; 203: 204: if (profile == 0 && table == 0) 205: return; 206: if (cnts != zcnt || lastpf != zpfcnt) 207: cPANIC(); 208: if (table == 0) 209: return; 210: if (profile) 211: printf("\f\n"); 212: header(); 213: printf("\n\tLine\t Count\n\n"); 214: zpfp = zpf; 215: for (i = 0; i < zpfcnt; i++) { 216: printf("\t%4d\t%8ld\t", zpfp->pfline, zpfp->pfcnt); 217: if (!justify) 218: for (j = zpfp->pflev * unit; j > 1; j--) 219: putchar(' '); 220: printf("%s\n", zpfp->pfname); 221: zpfp++; 222: } 223: } 224: 225: nowcntr() 226: { 227: 228: return (px.counter); 229: } 230: 231: long nowcnt() 232: { 233: 234: return (px.ntimes); 235: } 236: 237: long cntof(pxc) 238: struct pxcnt *pxc; 239: { 240: 241: if (profile == 0 && table == 0) 242: return; 243: return (pxc->ntimes); 244: } 245: 246: setcnt(l) 247: long l; 248: { 249: 250: if (profile == 0 && table == 0) 251: return; 252: px.counter = --gcountr; 253: px.ntimes = l; 254: px.gos = gocnt; 255: px.printed = 0; 256: } 257: 258: savecnt(pxc) 259: register struct pxcnt *pxc; 260: { 261: 262: if (profile == 0 && table == 0) 263: return; 264: pxc->ntimes = px.ntimes; 265: pxc->counter = px.counter; 266: pxc->gos = px.gos; 267: pxc->printed = 1; 268: } 269: 270: rescnt(pxc) 271: register struct pxcnt *pxc; 272: { 273: 274: if (profile == 0 && table == 0) 275: return; 276: px.ntimes = pxc->ntimes; 277: px.counter = pxc->counter; 278: px.gos = gocnt; 279: px.printed = pxc->printed; 280: return (gocnt != pxc->gos); 281: } 282: 283: getcnt() 284: { 285: 286: if (profile == 0 && table == 0) 287: return; 288: if (cnts == zcnt) 289: cPANIC(); 290: px.counter = cnts; 291: px.ntimes = zbuf[cnts]; 292: px.gos = gocnt; 293: px.printed = 0; 294: ++cnts; 295: } 296: 297: unprint() 298: { 299: 300: px.printed = 0; 301: } 302: 303: /* 304: * Control printing of '|' 305: * when profiling. 306: */ 307: STATIC char nobar; 308: 309: baroff() 310: { 311: 312: nobar = 1; 313: } 314: 315: baron() 316: { 317: 318: nobar = 0; 319: } 320: 321: /* 322: * Do we want cnt and/or '|' on this line ? 323: * 1 = count and '|' 324: * 0 = only '|' 325: * -1 = spaces only 326: */ 327: shudpcnt() 328: { 329: 330: register i; 331: 332: if (nobar) 333: return (-1); 334: i = px.printed; 335: px.printed = 1; 336: return (i == 0); 337: } 338: 339: STATIC char mism[] "Program and counter data do not correspond\n"; 340: 341: cPANIC() 342: { 343: 344: printf("cnts %d zcnt %d, lastpf %d zpfcnt %d\n", 345: cnts, zcnt, lastpf, zpfcnt); 346: flush(); 347: write(2, mism, sizeof mism); 348: pexit(ERRS); 349: }