home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / D / LIBC / LIBC-4.6 / LIBC-4 / libc-linux / sysdeps / linux / i386 / gmon / gmon.c next >
Encoding:
C/C++ Source or Header  |  1992-10-18  |  8.9 KB  |  340 lines

  1. /*-
  2.  * Copyright (c) 1991 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. #if 0
  35. #ifndef lint
  36. static char sccsid[] = "@(#)gmon.c    5.3 (Berkeley) 5/22/91";
  37. #endif /* not lint */
  38. #endif
  39.  
  40. #include <unistd.h>
  41. #include <fcntl.h>
  42. #include <errno.h>
  43.  
  44. #ifdef DEBUG
  45. #include <stdio.h>
  46. #endif
  47.  
  48. #include "gmon.h"
  49.  
  50. extern void mcount(); /* asm ("mcount"); */
  51. /* extern */ char *minbrk; /* asm ("_minbrk"); */
  52.  
  53. /*
  54.  *    froms is actually a bunch of unsigned shorts indexing tos
  55.  */
  56. static int        profiling = 3;
  57. static unsigned short    *froms;
  58. static struct tostruct    *tos = 0;
  59. static long        tolimit = 0;
  60. static char        *s_lowpc = 0;
  61. static char        *s_highpc = 0;
  62. static unsigned long    s_textsize = 0;
  63.  
  64. static int    ssiz;
  65. static char    *sbuf;
  66. static int    s_scale;
  67.     /* see profil(2) where this is describe (incorrectly) */
  68. #define        SCALE_1_TO_1    0x10000L
  69.  
  70. /*
  71.  * Control profiling
  72.  *    profiling is what mcount checks to see if
  73.  *    all the data structures are ready.
  74.  */
  75. void
  76. moncontrol(mode)
  77.     int mode;
  78. {
  79.     int ret;
  80.     static int warned = 0;
  81.  
  82.     if (mode) {
  83.     /* start */
  84.     ret = profil(sbuf + sizeof(struct phdr), ssiz - sizeof(struct phdr),
  85.         (int)s_lowpc, s_scale);
  86.     if (ret < 0 && errno == ENOSYS && !warned) {
  87. #   define    PROFIL_WARN    "warning: kernel does not support profiling\n"
  88.         write(2, PROFIL_WARN, sizeof(PROFIL_WARN));
  89.         warned = 1;
  90.     }
  91.     profiling = 0;
  92.     } else {
  93.     /* stop */
  94.     profil((char *)0, 0, 0, 0);
  95.     profiling = 3;
  96.     }
  97. }
  98.  
  99. #define    MSG "No space for profiling buffer(s)\n"
  100.  
  101. void
  102. monstartup(lowpc, highpc)
  103.     char    *lowpc;
  104.     char    *highpc;
  105. {
  106.     int            monsize;
  107.     char        *buffer;
  108.     register int    o;
  109.  
  110.     /*
  111.      *    round lowpc and highpc to multiples of the density we're using
  112.      *    so the rest of the scaling (here and in gprof) stays in ints.
  113.      */
  114.     lowpc = (char *)
  115.         ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
  116.     s_lowpc = lowpc;
  117.     highpc = (char *)
  118.         ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
  119.     s_highpc = highpc;
  120.     s_textsize = highpc - lowpc;
  121.     monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
  122.     buffer = (char *) sbrk( monsize );
  123.     if ( buffer == (char *) -1 ) {
  124.     write( 2 , MSG , sizeof(MSG) );
  125.     return;
  126.     }
  127.     froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION );
  128.     if ( froms == (unsigned short *) -1 ) {
  129.     write( 2 , MSG , sizeof(MSG) );
  130.     froms = 0;
  131.     return;
  132.     }
  133.     tolimit = s_textsize * ARCDENSITY / 100;
  134.     if ( tolimit < MINARCS ) {
  135.     tolimit = MINARCS;
  136.     } else if ( tolimit > 65534 ) {
  137.     tolimit = 65534;
  138.     }
  139.     tos = (struct tostruct *) sbrk( tolimit * sizeof( struct tostruct ) );
  140.     if ( tos == (struct tostruct *) -1 ) {
  141.     write( 2 , MSG , sizeof(MSG) );
  142.     froms = 0;
  143.     tos = 0;
  144.     return;
  145.     }
  146.     minbrk = (char *) sbrk(0);
  147.     tos[0].link = 0;
  148.     sbuf = buffer;
  149.     ssiz = monsize;
  150.     ( (struct phdr *) buffer ) -> lpc = lowpc;
  151.     ( (struct phdr *) buffer ) -> hpc = highpc;
  152.     ( (struct phdr *) buffer ) -> ncnt = ssiz;
  153.     monsize -= sizeof(struct phdr);
  154.     if ( monsize <= 0 )
  155.     return;
  156.     o = highpc - lowpc;
  157.     if( monsize < o )
  158. #ifndef hp300
  159.     s_scale = ( (float) monsize / o ) * SCALE_1_TO_1;
  160. #else /* avoid floating point */
  161.     {
  162.     int quot = o / monsize;
  163.  
  164.     if (quot >= 0x10000)
  165.         s_scale = 1;
  166.     else if (quot >= 0x100)
  167.         s_scale = 0x10000 / quot;
  168.     else if (o >= 0x800000)
  169.         s_scale = 0x1000000 / (o / (monsize >> 8));
  170.     else
  171.         s_scale = 0x1000000 / ((o << 8) / monsize);
  172.     }
  173. #endif
  174.     else
  175.     s_scale = SCALE_1_TO_1;
  176.     moncontrol(1);
  177. }
  178.  
  179. void
  180. _mcleanup()
  181. {
  182.     int            fd;
  183.     int            fromindex;
  184.     int            endfrom;
  185.     char        *frompc;
  186.     int            toindex;
  187.     struct rawarc    rawarc;
  188.  
  189.     moncontrol(0);
  190.     fd = creat( "gmon.out" , 0666 );
  191.     if ( fd < 0 ) {
  192.     perror( "mcount: gmon.out" );
  193.     return;
  194.     }
  195. #   ifdef DEBUG
  196.     fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
  197. #   endif DEBUG
  198.     write( fd , sbuf , ssiz );
  199.     endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
  200.     for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) {
  201.     if ( froms[fromindex] == 0 ) {
  202.         continue;
  203.     }
  204.     frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms));
  205.     for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {
  206. #        ifdef DEBUG
  207.         fprintf( stderr ,
  208.             "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
  209.             frompc , tos[toindex].selfpc , tos[toindex].count );
  210. #        endif DEBUG
  211.         rawarc.raw_frompc = (unsigned long) frompc;
  212.         rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
  213.         rawarc.raw_count = tos[toindex].count;
  214.         write( fd , (char *) &rawarc , sizeof rawarc );
  215.     }
  216.     }
  217.     close( fd );
  218. }
  219.  
  220. void
  221. mcount()
  222. {
  223.     register char            *selfpc;
  224.     register unsigned short        *frompcindex;
  225.     register struct tostruct    *top;
  226.     register struct tostruct    *prevtop;
  227.     register long            toindex;
  228.  
  229.     /*
  230.      *    find the return address for mcount,
  231.      *    and the return address for mcount's caller.
  232.      */
  233.  
  234.     /* selfpc = pc pushed by mcount call.
  235.        This identifies the function that was just entered.  */
  236.     selfpc = (void *) __builtin_return_address (0);
  237.     /* frompcindex = pc in preceding frame.
  238.        This identifies the caller of the function just entered.  */
  239.     frompcindex = (void *) __builtin_return_address (1);
  240.     /*
  241.      *    check that we are profiling
  242.      *    and that we aren't recursively invoked.
  243.      */
  244.     if (profiling) {
  245.         goto out;
  246.     }
  247.     profiling++;
  248.     /*
  249.      *    check that frompcindex is a reasonable pc value.
  250.      *    for example:    signal catchers get called from the stack,
  251.      *            not from text space.  too bad.
  252.      */
  253.     frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
  254.     if ((unsigned long)frompcindex > s_textsize) {
  255.         goto done;
  256.     }
  257.     frompcindex =
  258.         &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
  259.     toindex = *frompcindex;
  260.     if (toindex == 0) {
  261.         /*
  262.          *    first time traversing this arc
  263.          */
  264.         toindex = ++tos[0].link;
  265.         if (toindex >= tolimit) {
  266.             goto overflow;
  267.         }
  268.         *frompcindex = toindex;
  269.         top = &tos[toindex];
  270.         top->selfpc = selfpc;
  271.         top->count = 1;
  272.         top->link = 0;
  273.         goto done;
  274.     }
  275.     top = &tos[toindex];
  276.     if (top->selfpc == selfpc) {
  277.         /*
  278.          *    arc at front of chain; usual case.
  279.          */
  280.         top->count++;
  281.         goto done;
  282.     }
  283.     /*
  284.      *    have to go looking down chain for it.
  285.      *    top points to what we are looking at,
  286.      *    prevtop points to previous top.
  287.      *    we know it is not at the head of the chain.
  288.      */
  289.     for (; /* goto done */; ) {
  290.         if (top->link == 0) {
  291.             /*
  292.              *    top is end of the chain and none of the chain
  293.              *    had top->selfpc == selfpc.
  294.              *    so we allocate a new tostruct
  295.              *    and link it to the head of the chain.
  296.              */
  297.             toindex = ++tos[0].link;
  298.             if (toindex >= tolimit) {
  299.                 goto overflow;
  300.             }
  301.             top = &tos[toindex];
  302.             top->selfpc = selfpc;
  303.             top->count = 1;
  304.             top->link = *frompcindex;
  305.             *frompcindex = toindex;
  306.             goto done;
  307.         }
  308.         /*
  309.          *    otherwise, check the next arc on the chain.
  310.          */
  311.         prevtop = top;
  312.         top = &tos[top->link];
  313.         if (top->selfpc == selfpc) {
  314.             /*
  315.              *    there it is.
  316.              *    increment its count
  317.              *    move it to the head of the chain.
  318.              */
  319.             top->count++;
  320.             toindex = prevtop->link;
  321.             prevtop->link = top->link;
  322.             top->link = *frompcindex;
  323.             *frompcindex = toindex;
  324.             goto done;
  325.         }
  326.  
  327.     }
  328. done:
  329.     profiling--;
  330.     /* and fall through */
  331. out:
  332.     return;        /* normal return restores saved registers */
  333.  
  334. overflow:
  335.     profiling++; /* halt further profiling */
  336. #   define    TOLIMIT    "mcount: tos overflow\n"
  337.     write(2, TOLIMIT, sizeof(TOLIMIT));
  338.     goto out;
  339. }
  340.