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