BSD 4_3_Net_2 release
[unix-history] / usr / src / lib / csu.tahoe / gmon.c
index 471b72d..775cef0 100644 (file)
@@ -1,15 +1,46 @@
-/*
- * Copyright (c) 1980 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+/*-
+ * Copyright (c) 1987 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
  */
 
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)gmon.c     5.1 (Berkeley) 8/27/87";
-#endif LIBC_SCCS and not lint
+#ifndef lint
+static char sccsid[] = "@(#)gmon.c     5.5 (Berkeley) 5/22/91";
+#endif /* not lint */
 
 
+#include <unistd.h>
 #include "gmon.h"
 
 #include "gmon.h"
 
+extern mcount() asm ("mcount");
+extern char *minbrk asm ("minbrk");
+
     /*
      * froms is actually a bunch of unsigned shorts indexing tos
      */
     /*
      * froms is actually a bunch of unsigned shorts indexing tos
      */
@@ -27,96 +58,107 @@ static int s_scale;
     /* see profil(2) where this is describe (incorrectly) */
 #define                SCALE_1_TO_1    0x10000L
 
     /* see profil(2) where this is describe (incorrectly) */
 #define                SCALE_1_TO_1    0x10000L
 
-#define        MSG "No space for monitor buffer(s)\n"
+char nospace_msg[] = "No space for profiling buffer(s)\n";
+#define NOSPACE() (void) write(2, nospace_msg, sizeof nospace_msg - 1)
+
+char overflow_msg[] = "mcount: tos overflow\n";
+#define OVERFLOW() (void) write(2, overflow_msg, sizeof overflow_msg - 1)
 
 monstartup(lowpc, highpc)
 
 monstartup(lowpc, highpc)
-    char       *lowpc;
-    char       *highpc;
+       char    *lowpc;
+       char    *highpc;
 {
 {
-    int                        monsize;
-    char               *buffer;
-    char               *sbrk();
-    extern char                *minbrk;
+       int     monsize;
+       char    *buffer;
+       int     o;
+       struct  phdr *p;
 
        /*
 
        /*
-        *      round lowpc and highpc to multiples of the density we're using
-        *      so the rest of the scaling (here and in gprof) stays in ints.
+        * Round lowpc and highpc to multiples of the density we're using
+        * so the rest of the scaling (here and in gprof) stays in ints.
         */
         */
-    lowpc = (char *)
+       lowpc = (char *)
            ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
            ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
-    s_lowpc = lowpc;
-    highpc = (char *)
+       s_lowpc = lowpc;
+       highpc = (char *)
            ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
            ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
-    s_highpc = highpc;
-    s_textsize = highpc - lowpc;
-    monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
-    monsize = (monsize + 3) & ~3;
-    buffer = sbrk( monsize );
-    if ( buffer == (char *) -1 ) {
-       write( 2 , MSG , sizeof(MSG) - 1 );
-       return;
-    }
-    froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION );
-    if ( froms == (unsigned short *) -1 ) {
-       write( 2 , MSG , sizeof(MSG) - 1 );
-       froms = 0;
-       return;
-    }
-    tolimit = s_textsize * ARCDENSITY / 100;
-    if ( tolimit < MINARCS ) {
-       tolimit = MINARCS;
-    } else if ( tolimit > 65534 ) {
-       tolimit = 65534;
-    }
-    tos = (struct tostruct *) sbrk( (tolimit*sizeof(struct tostruct)+3)&~3 );
-    if ( tos == (struct tostruct *) -1 ) {
-       write( 2 , MSG , sizeof(MSG) - 1 );
-       froms = 0;
-       tos = 0;
-       return;
-    }
-    minbrk = sbrk(0);
-    tos[0].link = 0;
-    monitor( lowpc , highpc , buffer , monsize , tolimit );
+       s_highpc = highpc;
+       s_textsize = highpc - lowpc;
+       monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
+       monsize = (monsize + 3) & ~3;
+       buffer = sbrk(monsize);
+       if (buffer == (char *) -1) {
+               NOSPACE();
+               return;
+       }
+       froms = (unsigned short *) sbrk(s_textsize / HASHFRACTION);
+       if (froms == (unsigned short *) -1) {
+               NOSPACE();
+               froms = 0;
+               return;
+       }
+       tolimit = s_textsize * ARCDENSITY / 100;
+       if (tolimit < MINARCS)
+               tolimit = MINARCS;
+       else if (tolimit > 65534)
+               tolimit = 65534;
+       tos = (struct tostruct *) sbrk((tolimit*sizeof(struct tostruct)+3)&~3);
+       if (tos == (struct tostruct *) -1) {
+               NOSPACE();
+               froms = 0;
+               tos = 0;
+               return;
+       }
+       minbrk = sbrk(0);
+       tos[0].link = 0;
+       sbuf = buffer;
+       ssiz = monsize;
+       p = (struct phdr *) buffer;
+       p->lpc = lowpc;
+       p->hpc = highpc;
+       p->ncnt = ssiz;
+       monsize -= sizeof(struct phdr);
+       if (monsize <= 0)
+               return;
+       o = highpc - lowpc;
+       if(monsize < o)
+               s_scale = ((float) monsize / o) * SCALE_1_TO_1;
+       else
+               s_scale = SCALE_1_TO_1;
+       moncontrol(1);
 }
 
 _mcleanup()
 {
 }
 
 _mcleanup()
 {
-    int                        fd;
-    int                        fromindex;
-    int                        endfrom;
-    char               *frompc;
-    int                        toindex;
-    struct rawarc      rawarc;
+       int             fd;
+       int             fromindex;
+       int             endfrom;
+       char            *frompc;
+       int             toindex;
+       struct rawarc   rawarc;
 
 
-    fd = creat( "gmon.out" , 0666 );
-    if ( fd < 0 ) {
-       perror( "mcount: gmon.out" );
-       return;
-    }
-#   ifdef DEBUG
-       fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
-#   endif DEBUG
-    write( fd , sbuf , ssiz );
-    endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
-    for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) {
-       if ( froms[fromindex] == 0 ) {
-           continue;
+       moncontrol(0);
+       fd = creat("gmon.out", 0666);
+       if (fd < 0) {
+               perror("mcount: gmon.out");
+               return;
        }
        }
-       frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms));
-       for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {
-#          ifdef DEBUG
-               fprintf( stderr ,
-                       "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
-                       frompc , tos[toindex].selfpc , tos[toindex].count );
-#          endif DEBUG
-           rawarc.raw_frompc = (unsigned long) frompc;
-           rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
-           rawarc.raw_count = tos[toindex].count;
-           write( fd , &rawarc , sizeof rawarc );
+       (void) write(fd, sbuf, ssiz);
+       endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
+       for (fromindex = 0; fromindex < endfrom; fromindex++) {
+               if (froms[fromindex] == 0)
+                       continue;
+               frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms));
+               for (toindex = froms[fromindex];
+                    toindex != 0;
+                    toindex = tos[toindex].link) {
+                       rawarc.raw_frompc = (unsigned long) frompc;
+                       rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
+                       rawarc.raw_count = tos[toindex].count;
+                       (void) write(fd, &rawarc, sizeof rawarc);
+               }
        }
        }
-    }
-    close( fd );
+       close(fd);
 }
 
 mcount(cntpa)
 }
 
 mcount(cntpa)
@@ -129,38 +171,41 @@ mcount(cntpa)
        register long                   toindex;
 
        /*
        register long                   toindex;
 
        /*
-        *      find the return address for mcount,
-        *      and address of counter pointer
+        * Find the return address for mcount,
+        * and address of counter pointer.
         */
        selfpc = *((char **)&cntpa-3);  /* -8(fp) */
        frompcindex = (unsigned short *)(*((((long *)*((char **)&cntpa-1)))-2));
         */
        selfpc = *((char **)&cntpa-3);  /* -8(fp) */
        frompcindex = (unsigned short *)(*((((long *)*((char **)&cntpa-1)))-2));
+
        /*
        /*
-        *      check that we are profiling
-        *      and that we aren't recursively invoked.
+        * Check that we are profiling
+        * and that we aren't recursively invoked.
         */
         */
-       if (profiling) {
-               goto out;
-       }
+       if (profiling)
+               return;
        profiling++;
        profiling++;
+
        /*
        /*
-        *      check that frompcindex is a reasonable pc value.
-        *      for example:    signal catchers get called from the stack,
-        *                      not from text space.  too bad.
+        * Check that frompcindex is a reasonable pc value.
+        * for example: signal catchers get called from the stack,
+        *              not from text space.  too bad.
         */
        frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
         */
        frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
-       if ((unsigned long)frompcindex > s_textsize) {
+       if ((unsigned long)frompcindex > s_textsize)
                goto done;
                goto done;
-       }
        frompcindex =
            &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
        frompcindex =
            &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
+
        toindex = *frompcindex;
        if (toindex == 0) {
                /*
        toindex = *frompcindex;
        if (toindex == 0) {
                /*
-                *      first time traversing this arc
+                * First time traversing this arc
                 */
                toindex = ++tos[0].link;
                if (toindex >= tolimit) {
                 */
                toindex = ++tos[0].link;
                if (toindex >= tolimit) {
-                       goto overflow;
+                       profiling++;    /* stop profiling */
+                       OVERFLOW();
+                       return;
                }
                *frompcindex = toindex;
                top = &tos[toindex];
                }
                *frompcindex = toindex;
                top = &tos[toindex];
@@ -172,28 +217,31 @@ mcount(cntpa)
        top = &tos[toindex];
        if (top->selfpc == selfpc) {
                /*
        top = &tos[toindex];
        if (top->selfpc == selfpc) {
                /*
-                *      arc at front of chain; usual case.
+                * Arc at front of chain; usual case.
                 */
                top->count++;
                goto done;
        }
                 */
                top->count++;
                goto done;
        }
+
        /*
        /*
-        *      have to go looking down chain for it.
-        *      top points to what we are looking at,
-        *      prevtop points to previous top.
-        *      we know it is not at the head of the chain.
+        * Have to go looking down chain for it.
+        * top points to what we are looking at,
+        * prevtop points to previous top.
+        * We know it is not at the head of the chain.
         */
         */
-       for (; /* goto done */; ) {
+       for (;;) {
                if (top->link == 0) {
                        /*
                if (top->link == 0) {
                        /*
-                        *      top is end of the chain and none of the chain
-                        *      had top->selfpc == selfpc.
-                        *      so we allocate a new tostruct
-                        *      and link it to the head of the chain.
+                        * top is end of the chain and none of the chain
+                        * had top->selfpc == selfpc,
+                        * so we allocate a new tostruct
+                        * and link it to the head of the chain.
                         */
                        toindex = ++tos[0].link;
                        if (toindex >= tolimit) {
                         */
                        toindex = ++tos[0].link;
                        if (toindex >= tolimit) {
-                               goto overflow;
+                               profiling++;    /* stop profiling */
+                               OVERFLOW();
+                               return;
                        }
                        top = &tos[toindex];
                        top->selfpc = selfpc;
                        }
                        top = &tos[toindex];
                        top->selfpc = selfpc;
@@ -203,15 +251,15 @@ mcount(cntpa)
                        goto done;
                }
                /*
                        goto done;
                }
                /*
-                *      otherwise, check the next arc on the chain.
+                * Otherwise, check the next arc on the chain.
                 */
                prevtop = top;
                top = &tos[top->link];
                if (top->selfpc == selfpc) {
                        /*
                 */
                prevtop = top;
                top = &tos[top->link];
                if (top->selfpc == selfpc) {
                        /*
-                        *      there it is.
-                        *      increment its count
-                        *      move it to the head of the chain.
+                        * There it is.
+                        * Increment its count and
+                        * move it to the head of the chain.
                         */
                        top->count++;
                        toindex = prevtop->link;
                         */
                        top->count++;
                        toindex = prevtop->link;
@@ -224,62 +272,24 @@ mcount(cntpa)
        }
 done:
        profiling--;
        }
 done:
        profiling--;
-out:
        return;
        return;
-
-overflow:
-#   define     TOLIMIT "mcount: tos overflow\n"
-       write(2, TOLIMIT, sizeof(TOLIMIT) - 1);
-       goto out;
-}
-
-/*VARARGS1*/
-monitor( lowpc , highpc , buf , bufsiz , nfunc )
-    char       *lowpc;
-    char       *highpc;
-    char       *buf;   /* declared ``short buffer[]'' in monitor(3) */
-    int                bufsiz;
-    int                nfunc;  /* not used, available for compatability only */
-{
-    register o;
-
-    if ( lowpc == 0 ) {
-       moncontrol(0);
-       _mcleanup();
-       return;
-    }
-    sbuf = buf;
-    ssiz = bufsiz;
-    ( (struct phdr *) buf ) -> lpc = lowpc;
-    ( (struct phdr *) buf ) -> hpc = highpc;
-    ( (struct phdr *) buf ) -> ncnt = ssiz;
-    bufsiz -= sizeof(struct phdr);
-    if ( bufsiz <= 0 )
-       return;
-    o = highpc - lowpc;
-    if( bufsiz < o )
-       s_scale = ( (float) bufsiz / o ) * SCALE_1_TO_1;
-    else
-       s_scale = SCALE_1_TO_1;
-    moncontrol(1);
 }
 
 /*
 }
 
 /*
- * Control profiling
- *     profiling is what mcount checks to see if
- *     all the data structures are ready.
+ * While profiling is enabled, we set the variable 'profiling' to indicate
+ * that all the data structures are ready.
  */
 moncontrol(mode)
  */
 moncontrol(mode)
-    int mode;
+       int mode;
 {
 {
-    if (mode) {
-       /* start */
-       profil(sbuf + sizeof(struct phdr), ssiz - sizeof(struct phdr),
-               s_lowpc, s_scale);
-       profiling = 0;
-    } else {
-       /* stop */
-       profil((char *)0, 0, 0, 0);
-       profiling = 3;
-    }
+       if (mode) {
+               /* start */
+               profil(sbuf + sizeof(struct phdr), ssiz - sizeof(struct phdr),
+                       (int)s_lowpc, s_scale);
+               profiling = 0;
+       } else {
+               /* stop */
+               profil((char *)0, 0, 0, 0);
+               profiling = 3;
+       }
 }
 }