1*48112Sbostic /*- 2*48112Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48112Sbostic * All rights reserved. 4*48112Sbostic * 5*48112Sbostic * %sccs.include.redist.c% 622233Sdist */ 722233Sdist 822233Sdist #ifndef lint 9*48112Sbostic static char sccsid[] = "@(#)pmon.c 5.4 (Berkeley) 04/16/91"; 10*48112Sbostic #endif /* not lint */ 1122233Sdist 1222233Sdist /* 132860Speter * pxp - Pascal execution profiler 142860Speter * 152860Speter * Bill Joy UCB 162860Speter * Version 1.2 January 1979 172860Speter */ 182860Speter 192860Speter #include "0.h" 202860Speter 212860Speter /* 222860Speter * Profile counter processing cluster 232860Speter * 242860Speter * This file contains all routines which do the hard work in profiling. 252860Speter * 262860Speter * The first group of routines (getit, getpmon, getcore, and pmread) 272860Speter * deal with extracting data from the pmon.out and (with more difficulty) 282860Speter * core files. 292860Speter * 302860Speter * The routines cnttab and prttab collect counters for 312860Speter * and print the summary table respectively. 322860Speter * 332860Speter * The routines "*cnt*" deal with manipulation of counters, 342860Speter * especially the "current" counter px. 352860Speter */ 362860Speter STATIC struct pxcnt px; 372860Speter 382860Speter /* 392860Speter * Table to record info 402860Speter * for procedure/function summary 412860Speter */ 422860Speter STATIC struct pftab { 432860Speter long pfcnt; 442860Speter short pfline; 452860Speter char *pfname; 462860Speter short pflev; 472860Speter } *zpf; 482860Speter 492860Speter /* 502860Speter * Global variables 512860Speter */ 522860Speter STATIC long *zbuf; /* Count buffer */ 532860Speter STATIC short zcnt; /* Number of counts */ 542860Speter STATIC short zpfcnt; /* Number of proc/funcs's */ 552860Speter STATIC short gcountr; /* Unique name generator */ 562860Speter STATIC short zfil; /* I/o unit for count data reads */ 572860Speter STATIC short lastpf; /* Total # of procs and funcs for consistency chk */ 582860Speter 592860Speter getit(fp) 602860Speter register char *fp; 612860Speter { 622860Speter 632860Speter if (core) 642860Speter getcore(fp); 652860Speter else 662860Speter getpmon(fp); 672860Speter } 682860Speter 692860Speter /* 702860Speter * Setup monitor data buffer from pmon.out 712860Speter * style file whose name is fp. 722860Speter */ 732860Speter getpmon(fp) 742860Speter char *fp; 752860Speter { 762860Speter register char *cp; 772860Speter short garbage; 782860Speter 792860Speter zfil = open(fp, 0); 802860Speter if (zfil < 0) { 812860Speter perror(fp); 822860Speter pexit(NOSTART); 832860Speter } 842860Speter if (pmread() < 0 || read(zfil, &garbage, 1) == 1) { 852860Speter Perror(fp, "Bad format for pmon.out style file"); 862860Speter exit(1); 872860Speter } 882860Speter close(zfil); 892860Speter return; 902860Speter } 912860Speter 923051Smckusic STATIC char nospcm[] = "Not enough memory for count buffers\n"; 932860Speter 942860Speter pmnospac() 952860Speter { 962860Speter 972860Speter write(2, nospcm, sizeof nospcm); 982860Speter pexit(NOSTART); 992860Speter } 1002860Speter 1012860Speter /* 1022860Speter * Structure of the first few 1032860Speter * items of a px core dump. 1042860Speter */ 1052860Speter STATIC struct info { 1062860Speter char *off; /* Self-reference for pure text */ 1072860Speter short type; /* 0 = non-pure text, 1 = pure text */ 1082860Speter char *bp; /* Core address of pxps struct */ 1092860Speter } inf; 1102860Speter 1112860Speter /* 1122860Speter * First few words of the px 1132860Speter * information structure. 1142860Speter */ 1152860Speter STATIC struct pxps { 1162860Speter char *buf; 1172860Speter short cnt; 1182860Speter } pxp; 1192860Speter 1202860Speter getcore(fp) 1212860Speter char *fp; 1222860Speter { 1232860Speter 1242860Speter write(2, "-c: option not supported\n", sizeof("-c: option not supported\n")); 1252860Speter pexit(ERRS); 1262860Speter /* 1272860Speter short pm; 1282860Speter 1292860Speter zfil = open(fp, 0); 1302860Speter if (zfil < 0) { 1312860Speter perror(fp); 1322860Speter pexit(NOSTART); 1332860Speter } 1342860Speter if (lseek(zfil, 02000, 0) < 0) 1352860Speter goto format; 1362860Speter if (read(zfil, &inf, sizeof inf) < 0) 1372860Speter goto format; 1382860Speter if (inf.type != 0 && inf.type != 1) 1392860Speter goto format; 1402860Speter if (inf.type) 14132763Sbostic inf.bp -= inf.off; 1422860Speter if (lseek(zfil, inf.bp + 02000, 0) < 0) 1432860Speter goto format; 1442860Speter if (read(zfil, &pxp, sizeof pxp) != sizeof pxp) 1452860Speter goto format; 1462860Speter if (pxp.buf == NIL) { 1472860Speter Perror(fp, "No profile data in file"); 1482860Speter exit(1); 1492860Speter } 1502860Speter if (inf.type) 15132763Sbostic pxp.buf -= inf.off; 1522860Speter if (lseek(zfil, pxp.buf + 02000, 0) < 0) 1532860Speter goto format; 1542860Speter if (pmread() < 0) 1552860Speter goto format; 1562860Speter close(zfil); 1572860Speter return; 1582860Speter format: 1592860Speter Perror(fp, "Not a Pascal system core file"); 1602860Speter exit(1); 1612860Speter */ 1622860Speter } 1632860Speter 1642860Speter pmread() 1652860Speter { 1662860Speter register i; 1672860Speter register char *cp; 1682860Speter struct { 1692860Speter long no; 1702860Speter long tim; 1712860Speter long cntrs; 1722860Speter long rtns; 1732860Speter } zmagic; 1742860Speter 1752860Speter if (read(zfil, &zmagic, sizeof zmagic) != sizeof zmagic) 1762860Speter return (-1); 1772860Speter if (zmagic.no != 0426) 1782860Speter return (-1); 1792860Speter ptvec = zmagic.tim; 1802860Speter zcnt = zmagic.cntrs; 1812860Speter zpfcnt = zmagic.rtns; 18217685Smckusick cp = zbuf = pcalloc(i = (zcnt + 1) * sizeof *zbuf, 1); 18333240Sbostic if (cp == NULL) 1842860Speter pmnospac(); 18517685Smckusick cp = zpf = pcalloc(zpfcnt * sizeof *zpf, 1); 18633240Sbostic if (cp == NULL) 1872860Speter pmnospac(); 1882860Speter i -= sizeof(zmagic); 1893051Smckusic if (read(zfil, zbuf + (sizeof(zmagic) / sizeof(*zbuf)), i) != i) 1902860Speter return (-1); 1912860Speter zbuf++; 1922860Speter return (0); 1932860Speter } 1942860Speter 1952860Speter cnttab(s, no) 1962860Speter char *s; 1972860Speter short no; 1982860Speter { 1992860Speter register struct pftab *pp; 2002860Speter 2012860Speter lastpf++; 2022860Speter if (table == 0) 2032860Speter return; 2042860Speter if (no == zpfcnt) 2052860Speter cPANIC(); 2062860Speter pp = &zpf[no]; 2072860Speter pp->pfname = s; 2082860Speter pp->pfline = line; 2092860Speter pp->pfcnt = nowcnt(); 2102860Speter pp->pflev = cbn; 2112860Speter } 2122860Speter 2132860Speter prttab() 2142860Speter { 2152860Speter register i, j; 2162860Speter register struct pftab *zpfp; 2172860Speter 2182860Speter if (profile == 0 && table == 0) 2192860Speter return; 2202860Speter if (cnts != zcnt || lastpf != zpfcnt) 2212860Speter cPANIC(); 2222860Speter if (table == 0) 2232860Speter return; 2242860Speter if (profile) 2252860Speter printf("\f\n"); 2262860Speter header(); 2272860Speter printf("\n\tLine\t Count\n\n"); 2282860Speter zpfp = zpf; 2292860Speter for (i = 0; i < zpfcnt; i++) { 2302860Speter printf("\t%4d\t%8ld\t", zpfp->pfline, zpfp->pfcnt); 2312860Speter if (!justify) 2322860Speter for (j = zpfp->pflev * unit; j > 1; j--) 2332860Speter putchar(' '); 2342860Speter printf("%s\n", zpfp->pfname); 2352860Speter zpfp++; 2362860Speter } 2372860Speter } 2382860Speter 2392860Speter nowcntr() 2402860Speter { 2412860Speter 2422860Speter return (px.counter); 2432860Speter } 2442860Speter 2452860Speter long nowcnt() 2462860Speter { 2472860Speter 2482860Speter return (px.ntimes); 2492860Speter } 2502860Speter 2512860Speter long cntof(pxc) 2522860Speter struct pxcnt *pxc; 2532860Speter { 2542860Speter 2552860Speter if (profile == 0 && table == 0) 2562860Speter return; 2572860Speter return (pxc->ntimes); 2582860Speter } 2592860Speter 2602860Speter setcnt(l) 2612860Speter long l; 2622860Speter { 2632860Speter 2642860Speter if (profile == 0 && table == 0) 2652860Speter return; 2662860Speter px.counter = --gcountr; 2672860Speter px.ntimes = l; 2682860Speter px.gos = gocnt; 2692860Speter px.printed = 0; 2702860Speter } 2712860Speter 2722860Speter savecnt(pxc) 2732860Speter register struct pxcnt *pxc; 2742860Speter { 2752860Speter 2762860Speter if (profile == 0 && table == 0) 2772860Speter return; 2782860Speter pxc->ntimes = px.ntimes; 2792860Speter pxc->counter = px.counter; 2802860Speter pxc->gos = px.gos; 2812860Speter pxc->printed = 1; 2822860Speter } 2832860Speter 2842860Speter rescnt(pxc) 2852860Speter register struct pxcnt *pxc; 2862860Speter { 2872860Speter 2882860Speter if (profile == 0 && table == 0) 2892860Speter return; 2902860Speter px.ntimes = pxc->ntimes; 2912860Speter px.counter = pxc->counter; 2922860Speter px.gos = gocnt; 2932860Speter px.printed = pxc->printed; 2942860Speter return (gocnt != pxc->gos); 2952860Speter } 2962860Speter 2972860Speter getcnt() 2982860Speter { 2992860Speter 3002860Speter if (profile == 0 && table == 0) 3012860Speter return; 3022860Speter if (cnts == zcnt) 3032860Speter cPANIC(); 3042860Speter px.counter = cnts; 3052860Speter px.ntimes = zbuf[cnts]; 3062860Speter px.gos = gocnt; 3072860Speter px.printed = 0; 3082860Speter ++cnts; 3092860Speter } 3102860Speter 3112860Speter unprint() 3122860Speter { 3132860Speter 3142860Speter px.printed = 0; 3152860Speter } 3162860Speter 3172860Speter /* 3182860Speter * Control printing of '|' 3192860Speter * when profiling. 3202860Speter */ 3212860Speter STATIC char nobar; 3222860Speter 3232860Speter baroff() 3242860Speter { 3252860Speter 3262860Speter nobar = 1; 3272860Speter } 3282860Speter 3292860Speter baron() 3302860Speter { 3312860Speter 3322860Speter nobar = 0; 3332860Speter } 3342860Speter 3352860Speter /* 3362860Speter * Do we want cnt and/or '|' on this line ? 3372860Speter * 1 = count and '|' 3382860Speter * 0 = only '|' 3392860Speter * -1 = spaces only 3402860Speter */ 3412860Speter shudpcnt() 3422860Speter { 3432860Speter 3442860Speter register i; 3452860Speter 3462860Speter if (nobar) 3472860Speter return (-1); 3482860Speter i = px.printed; 3492860Speter px.printed = 1; 3502860Speter return (i == 0); 3512860Speter } 3522860Speter 3533051Smckusic STATIC char mism[] = "Program and counter data do not correspond\n"; 3542860Speter 3552860Speter cPANIC() 3562860Speter { 3572860Speter 3582860Speter printf("cnts %d zcnt %d, lastpf %d zpfcnt %d\n", 3592860Speter cnts, zcnt, lastpf, zpfcnt); 3602860Speter flush(); 3612860Speter write(2, mism, sizeof mism); 3622860Speter pexit(ERRS); 3632860Speter } 364