home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / lib / csu.tahoe / gmon.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-27  |  7.6 KB  |  296 lines

  1. /*-
  2.  * Copyright (c) 1987 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)gmon.c    5.5 (Berkeley) 5/22/91";
  36. #endif /* not lint */
  37.  
  38. #include <unistd.h>
  39. #include "gmon.h"
  40.  
  41. extern mcount() asm ("mcount");
  42. extern char *minbrk asm ("minbrk");
  43.  
  44.     /*
  45.      *    froms is actually a bunch of unsigned shorts indexing tos
  46.      */
  47. static int        profiling = 3;
  48. static unsigned short    *froms;
  49. static struct tostruct    *tos = 0;
  50. static long        tolimit = 0;
  51. static char        *s_lowpc = 0;
  52. static char        *s_highpc = 0;
  53. static unsigned long    s_textsize = 0;
  54.  
  55. static int    ssiz;
  56. static char    *sbuf;
  57. static int    s_scale;
  58.     /* see profil(2) where this is describe (incorrectly) */
  59. #define        SCALE_1_TO_1    0x10000L
  60.  
  61. char nospace_msg[] = "No space for profiling buffer(s)\n";
  62. #define NOSPACE() (void) write(2, nospace_msg, sizeof nospace_msg - 1)
  63.  
  64. char overflow_msg[] = "mcount: tos overflow\n";
  65. #define OVERFLOW() (void) write(2, overflow_msg, sizeof overflow_msg - 1)
  66.  
  67. monstartup(lowpc, highpc)
  68.     char    *lowpc;
  69.     char    *highpc;
  70. {
  71.     int    monsize;
  72.     char    *buffer;
  73.     int    o;
  74.     struct    phdr *p;
  75.  
  76.     /*
  77.      * Round lowpc and highpc to multiples of the density we're using
  78.      * so the rest of the scaling (here and in gprof) stays in ints.
  79.      */
  80.     lowpc = (char *)
  81.         ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
  82.     s_lowpc = lowpc;
  83.     highpc = (char *)
  84.         ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
  85.     s_highpc = highpc;
  86.     s_textsize = highpc - lowpc;
  87.     monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
  88.     monsize = (monsize + 3) & ~3;
  89.     buffer = sbrk(monsize);
  90.     if (buffer == (char *) -1) {
  91.         NOSPACE();
  92.         return;
  93.     }
  94.     froms = (unsigned short *) sbrk(s_textsize / HASHFRACTION);
  95.     if (froms == (unsigned short *) -1) {
  96.         NOSPACE();
  97.         froms = 0;
  98.         return;
  99.     }
  100.     tolimit = s_textsize * ARCDENSITY / 100;
  101.     if (tolimit < MINARCS)
  102.         tolimit = MINARCS;
  103.     else if (tolimit > 65534)
  104.         tolimit = 65534;
  105.     tos = (struct tostruct *) sbrk((tolimit*sizeof(struct tostruct)+3)&~3);
  106.     if (tos == (struct tostruct *) -1) {
  107.         NOSPACE();
  108.         froms = 0;
  109.         tos = 0;
  110.         return;
  111.     }
  112.     minbrk = sbrk(0);
  113.     tos[0].link = 0;
  114.     sbuf = buffer;
  115.     ssiz = monsize;
  116.     p = (struct phdr *) buffer;
  117.     p->lpc = lowpc;
  118.     p->hpc = highpc;
  119.     p->ncnt = ssiz;
  120.     monsize -= sizeof(struct phdr);
  121.     if (monsize <= 0)
  122.         return;
  123.     o = highpc - lowpc;
  124.     if(monsize < o)
  125.         s_scale = ((float) monsize / o) * SCALE_1_TO_1;
  126.     else
  127.         s_scale = SCALE_1_TO_1;
  128.     moncontrol(1);
  129. }
  130.  
  131. _mcleanup()
  132. {
  133.     int        fd;
  134.     int        fromindex;
  135.     int        endfrom;
  136.     char        *frompc;
  137.     int        toindex;
  138.     struct rawarc    rawarc;
  139.  
  140.     moncontrol(0);
  141.     fd = creat("gmon.out", 0666);
  142.     if (fd < 0) {
  143.         perror("mcount: gmon.out");
  144.         return;
  145.     }
  146.     (void) write(fd, sbuf, ssiz);
  147.     endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
  148.     for (fromindex = 0; fromindex < endfrom; fromindex++) {
  149.         if (froms[fromindex] == 0)
  150.             continue;
  151.         frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms));
  152.         for (toindex = froms[fromindex];
  153.              toindex != 0;
  154.              toindex = tos[toindex].link) {
  155.             rawarc.raw_frompc = (unsigned long) frompc;
  156.             rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
  157.             rawarc.raw_count = tos[toindex].count;
  158.             (void) write(fd, &rawarc, sizeof rawarc);
  159.         }
  160.     }
  161.     close(fd);
  162. }
  163.  
  164. mcount(cntpa)
  165.     long **cntpa;
  166. {
  167.     register char            *selfpc;
  168.     register unsigned short        *frompcindex;
  169.     register struct tostruct    *top;
  170.     register struct tostruct    *prevtop;
  171.     register long            toindex;
  172.  
  173.     /*
  174.      * Find the return address for mcount,
  175.      * and address of counter pointer.
  176.      */
  177.     selfpc = *((char **)&cntpa-3);    /* -8(fp) */
  178.     frompcindex = (unsigned short *)(*((((long *)*((char **)&cntpa-1)))-2));
  179.  
  180.     /*
  181.      * Check that we are profiling
  182.      * and that we aren't recursively invoked.
  183.      */
  184.     if (profiling)
  185.         return;
  186.     profiling++;
  187.  
  188.     /*
  189.      * Check that frompcindex is a reasonable pc value.
  190.      * for example:    signal catchers get called from the stack,
  191.      *        not from text space.  too bad.
  192.      */
  193.     frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
  194.     if ((unsigned long)frompcindex > s_textsize)
  195.         goto done;
  196.     frompcindex =
  197.         &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
  198.  
  199.     toindex = *frompcindex;
  200.     if (toindex == 0) {
  201.         /*
  202.          * First time traversing this arc
  203.          */
  204.         toindex = ++tos[0].link;
  205.         if (toindex >= tolimit) {
  206.             profiling++;    /* stop profiling */
  207.             OVERFLOW();
  208.             return;
  209.         }
  210.         *frompcindex = toindex;
  211.         top = &tos[toindex];
  212.         top->selfpc = selfpc;
  213.         top->count = 1;
  214.         top->link = 0;
  215.         goto done;
  216.     }
  217.     top = &tos[toindex];
  218.     if (top->selfpc == selfpc) {
  219.         /*
  220.          * Arc at front of chain; usual case.
  221.          */
  222.         top->count++;
  223.         goto done;
  224.     }
  225.  
  226.     /*
  227.      * Have to go looking down chain for it.
  228.      * top points to what we are looking at,
  229.      * prevtop points to previous top.
  230.      * We know it is not at the head of the chain.
  231.      */
  232.     for (;;) {
  233.         if (top->link == 0) {
  234.             /*
  235.              * top is end of the chain and none of the chain
  236.              * had top->selfpc == selfpc,
  237.              * so we allocate a new tostruct
  238.              * and link it to the head of the chain.
  239.              */
  240.             toindex = ++tos[0].link;
  241.             if (toindex >= tolimit) {
  242.                 profiling++;    /* stop profiling */
  243.                 OVERFLOW();
  244.                 return;
  245.             }
  246.             top = &tos[toindex];
  247.             top->selfpc = selfpc;
  248.             top->count = 1;
  249.             top->link = *frompcindex;
  250.             *frompcindex = toindex;
  251.             goto done;
  252.         }
  253.         /*
  254.          * Otherwise, check the next arc on the chain.
  255.          */
  256.         prevtop = top;
  257.         top = &tos[top->link];
  258.         if (top->selfpc == selfpc) {
  259.             /*
  260.              * There it is.
  261.              * Increment its count and
  262.              * move it to the head of the chain.
  263.              */
  264.             top->count++;
  265.             toindex = prevtop->link;
  266.             prevtop->link = top->link;
  267.             top->link = *frompcindex;
  268.             *frompcindex = toindex;
  269.             goto done;
  270.         }
  271.  
  272.     }
  273. done:
  274.     profiling--;
  275.     return;
  276. }
  277.  
  278. /*
  279.  * While profiling is enabled, we set the variable 'profiling' to indicate
  280.  * that all the data structures are ready.
  281.  */
  282. moncontrol(mode)
  283.     int mode;
  284. {
  285.     if (mode) {
  286.         /* start */
  287.         profil(sbuf + sizeof(struct phdr), ssiz - sizeof(struct phdr),
  288.             (int)s_lowpc, s_scale);
  289.         profiling = 0;
  290.     } else {
  291.         /* stop */
  292.         profil((char *)0, 0, 0, 0);
  293.         profiling = 3;
  294.     }
  295. }
  296.