148112Sbostic /*-
2*62191Sbostic * Copyright (c) 1980, 1993
3*62191Sbostic * The Regents of the University of California. All rights reserved.
448112Sbostic *
548112Sbostic * %sccs.include.redist.c%
622233Sdist */
722233Sdist
822233Sdist #ifndef lint
9*62191Sbostic static char sccsid[] = "@(#)pmon.c 8.1 (Berkeley) 06/06/93";
1048112Sbostic #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
getit(fp)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 */
getpmon(fp)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
pmnospac()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
getcore(fp)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
pmread()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
cnttab(s,no)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
prttab()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
nowcntr()2392860Speter nowcntr()
2402860Speter {
2412860Speter
2422860Speter return (px.counter);
2432860Speter }
2442860Speter
nowcnt()2452860Speter long nowcnt()
2462860Speter {
2472860Speter
2482860Speter return (px.ntimes);
2492860Speter }
2502860Speter
cntof(pxc)2512860Speter long cntof(pxc)
2522860Speter struct pxcnt *pxc;
2532860Speter {
2542860Speter
2552860Speter if (profile == 0 && table == 0)
2562860Speter return;
2572860Speter return (pxc->ntimes);
2582860Speter }
2592860Speter
setcnt(l)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
savecnt(pxc)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
rescnt(pxc)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
getcnt()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
unprint()3112860Speter unprint()
3122860Speter {
3132860Speter
3142860Speter px.printed = 0;
3152860Speter }
3162860Speter
3172860Speter /*
3182860Speter * Control printing of '|'
3192860Speter * when profiling.
3202860Speter */
3212860Speter STATIC char nobar;
3222860Speter
baroff()3232860Speter baroff()
3242860Speter {
3252860Speter
3262860Speter nobar = 1;
3272860Speter }
3282860Speter
baron()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 */
shudpcnt()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
cPANIC()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