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

  1. /*-
  2.  * Copyright (c) 1983 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.8 (Berkeley) 5/27/91";
  36. #endif /* not lint */
  37.  
  38. #include <unistd.h>
  39.  
  40. #ifdef DEBUG
  41. #include <stdio.h>
  42. #endif
  43.  
  44. #include "gmon.h"
  45.  
  46. extern mcount() asm ("mcount");
  47. extern mcount2() asm ("mcount2");
  48. extern char *minbrk asm ("minbrk");
  49.  
  50.     /*
  51.      *    froms is actually a bunch of unsigned shorts indexing tos
  52.      */
  53. static int        profiling = 3;
  54. static unsigned short    *froms;
  55. static struct tostruct    *tos = 0;
  56. static long        tolimit = 0;
  57. static char        *s_lowpc = 0;
  58. static char        *s_highpc = 0;
  59. static unsigned long    s_textsize = 0;
  60.  
  61. static int    ssiz;
  62. static char    *sbuf;
  63. static int    s_scale;
  64.     /* see profil(2) where this is describe (incorrectly) */
  65. #define        SCALE_1_TO_1    0x10000L
  66.  
  67. #define    MSG "No space for profiling buffer(s)\n"
  68.  
  69. monstartup(lowpc, highpc)
  70.     char    *lowpc;
  71.     char    *highpc;
  72. {
  73.     int            monsize;
  74.     char        *buffer;
  75.     register int    o;
  76.  
  77.     /*
  78.      *    round lowpc and highpc to multiples of the density we're using
  79.      *    so the rest of the scaling (here and in gprof) stays in ints.
  80.      */
  81.     lowpc = (char *)
  82.         ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
  83.     s_lowpc = lowpc;
  84.     highpc = (char *)
  85.         ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
  86.     s_highpc = highpc;
  87.     s_textsize = highpc - lowpc;
  88.     monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
  89.     buffer = sbrk( monsize );
  90.     if ( buffer == (char *) -1 ) {
  91.     write( 2 , MSG , sizeof(MSG) - 1 );
  92.     return;
  93.     }
  94.     froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION );
  95.     if ( froms == (unsigned short *) -1 ) {
  96.     write( 2 , MSG , sizeof(MSG) - 1 );
  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.     }
  106.     tos = (struct tostruct *) sbrk( tolimit * sizeof( struct tostruct ) );
  107.     if ( tos == (struct tostruct *) -1 ) {
  108.     write( 2 , MSG , sizeof(MSG) - 1 );
  109.     froms = 0;
  110.     tos = 0;
  111.     return;
  112.     }
  113.     minbrk = sbrk(0);
  114.     tos[0].link = 0;
  115.     sbuf = buffer;
  116.     ssiz = monsize;
  117.     ( (struct phdr *) buffer ) -> lpc = lowpc;
  118.     ( (struct phdr *) buffer ) -> hpc = highpc;
  119.     ( (struct phdr *) buffer ) -> 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. #   ifdef DEBUG
  147.     fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
  148. #   endif DEBUG
  149.     write( fd , sbuf , ssiz );
  150.     endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
  151.     for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) {
  152.     if ( froms[fromindex] == 0 ) {
  153.         continue;
  154.     }
  155.     frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms));
  156.     for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {
  157. #        ifdef DEBUG
  158.         fprintf( stderr ,
  159.             "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
  160.             frompc , tos[toindex].selfpc , tos[toindex].count );
  161. #        endif DEBUG
  162.         rawarc.raw_frompc = (unsigned long) frompc;
  163.         rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
  164.         rawarc.raw_count = tos[toindex].count;
  165.         write( fd , &rawarc , sizeof rawarc );
  166.     }
  167.     }
  168.     close( fd );
  169. }
  170.  
  171. asm(".text; .globl mcount; mcount: pushl 16(fp); calls $1,mcount2; rsb");
  172.  
  173. mcount2(frompcindex, selfpc)
  174.     register unsigned short        *frompcindex;
  175.     register char            *selfpc;
  176. {
  177.     register struct tostruct    *top;
  178.     register struct tostruct    *prevtop;
  179.     register long            toindex;
  180.  
  181.     /*
  182.      *    check that we are profiling
  183.      *    and that we aren't recursively invoked.
  184.      */
  185.     if (profiling)
  186.         return;
  187.     profiling++;
  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.     }
  197.     frompcindex =
  198.         &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
  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.             goto overflow;
  207.         }
  208.         *frompcindex = toindex;
  209.         top = &tos[toindex];
  210.         top->selfpc = selfpc;
  211.         top->count = 1;
  212.         top->link = 0;
  213.         goto done;
  214.     }
  215.     top = &tos[toindex];
  216.     if (top->selfpc == selfpc) {
  217.         /*
  218.          *    arc at front of chain; usual case.
  219.          */
  220.         top->count++;
  221.         goto done;
  222.     }
  223.     /*
  224.      *    have to go looking down chain for it.
  225.      *    top points to what we are looking at,
  226.      *    prevtop points to previous top.
  227.      *    we know it is not at the head of the chain.
  228.      */
  229.     for (; /* goto done */; ) {
  230.         if (top->link == 0) {
  231.             /*
  232.              *    top is end of the chain and none of the chain
  233.              *    had top->selfpc == selfpc.
  234.              *    so we allocate a new tostruct
  235.              *    and link it to the head of the chain.
  236.              */
  237.             toindex = ++tos[0].link;
  238.             if (toindex >= tolimit) {
  239.                 goto overflow;
  240.             }
  241.             top = &tos[toindex];
  242.             top->selfpc = selfpc;
  243.             top->count = 1;
  244.             top->link = *frompcindex;
  245.             *frompcindex = toindex;
  246.             goto done;
  247.         }
  248.         /*
  249.          *    otherwise, check the next arc on the chain.
  250.          */
  251.         prevtop = top;
  252.         top = &tos[top->link];
  253.         if (top->selfpc == selfpc) {
  254.             /*
  255.              *    there it is.
  256.              *    increment its count
  257.              *    move it to the head of the chain.
  258.              */
  259.             top->count++;
  260.             toindex = prevtop->link;
  261.             prevtop->link = top->link;
  262.             top->link = *frompcindex;
  263.             *frompcindex = toindex;
  264.             goto done;
  265.         }
  266.  
  267.     }
  268. done:
  269.     profiling--;
  270.     return;
  271.  
  272. overflow:
  273.     profiling++; /* halt further profiling */
  274. #   define    TOLIMIT    "mcount: tos overflow\n"
  275.     write(2, TOLIMIT, sizeof(TOLIMIT) - 1);
  276.     return;
  277. }
  278.  
  279. /*
  280.  * Control profiling
  281.  *    profiling is what mcount checks to see if
  282.  *    all the data structures are ready.
  283.  */
  284. moncontrol(mode)
  285.     int mode;
  286. {
  287.     if (mode) {
  288.     /* start */
  289.     profil(sbuf + sizeof(struct phdr), ssiz - sizeof(struct phdr),
  290.         (int)s_lowpc, s_scale);
  291.     profiling = 0;
  292.     } else {
  293.     /* stop */
  294.     profil((char *)0, 0, 0, 0);
  295.     profiling = 3;
  296.     }
  297. }
  298.