try to make display narrower
[unix-history] / usr / src / lib / libc / gmon / gmon.c
index 3b63685..76a6d61 100644 (file)
@@ -1,4 +1,12 @@
-static char *sccsid = "@(#)gmon.c      4.6 (Berkeley) %G%";
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gmon.c     5.4 (Berkeley) %G%";
+#endif LIBC_SCCS and not lint
 
 #ifdef DEBUG
 #include <stdio.h>
 
 #ifdef DEBUG
 #include <stdio.h>
@@ -9,16 +17,19 @@ static       char *sccsid = "@(#)gmon.c      4.6 (Berkeley) %G%";
     /*
      * froms is actually a bunch of unsigned shorts indexing tos
      */
     /*
      * froms is actually a bunch of unsigned shorts indexing tos
      */
+static int             profiling = 3;
 static unsigned short  *froms;
 static struct tostruct *tos = 0;
 static unsigned short  *froms;
 static struct tostruct *tos = 0;
-static unsigned short  tolimit = 0;
+static long            tolimit = 0;
 static char            *s_lowpc = 0;
 static char            *s_highpc = 0;
 static unsigned long   s_textsize = 0;
 static char            *s_lowpc = 0;
 static char            *s_highpc = 0;
 static unsigned long   s_textsize = 0;
-static char            *minsbrk = 0;
 
 static int     ssiz;
 
 static int     ssiz;
-static int     *sbuf;
+static char    *sbuf;
+static int     s_scale;
+    /* see profil(2) where this is describe (incorrectly) */
+#define                SCALE_1_TO_1    0x10000L
 
 #define        MSG "No space for monitor buffer(s)\n"
 
 
 #define        MSG "No space for monitor buffer(s)\n"
 
@@ -29,43 +40,46 @@ monstartup(lowpc, highpc)
     int                        monsize;
     char               *buffer;
     char               *sbrk();
     int                        monsize;
     char               *buffer;
     char               *sbrk();
-    unsigned long      limit;
+    extern char                *minbrk;
 
 
+       /*
+        *      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 *)
+           ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
     s_lowpc = lowpc;
     s_lowpc = lowpc;
+    highpc = (char *)
+           ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
     s_highpc = highpc;
     s_textsize = highpc - lowpc;
     s_highpc = highpc;
     s_textsize = highpc - lowpc;
-    monsize = s_textsize + sizeof(struct phdr);
+    monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
     buffer = sbrk( monsize );
     if ( buffer == (char *) -1 ) {
     buffer = sbrk( monsize );
     if ( buffer == (char *) -1 ) {
-       write( 2 , MSG , sizeof(MSG) );
+       write( 2 , MSG , sizeof(MSG) - 1 );
        return;
     }
        return;
     }
-    froms = (unsigned short *) sbrk( s_textsize );
+    froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION );
     if ( froms == (unsigned short *) -1 ) {
     if ( froms == (unsigned short *) -1 ) {
-       write( 2 , MSG , sizeof(MSG) );
+       write( 2 , MSG , sizeof(MSG) - 1 );
        froms = 0;
        return;
     }
        froms = 0;
        return;
     }
-    limit = s_textsize * DENSITY / 100;
-    if ( limit < MINCNT ) {
-       limit = MINCNT;
-    } else if ( limit > 65534 ) {
-       limit = 65534;
+    tolimit = s_textsize * ARCDENSITY / 100;
+    if ( tolimit < MINARCS ) {
+       tolimit = MINARCS;
+    } else if ( tolimit > 65534 ) {
+       tolimit = 65534;
     }
     }
-    tos = (struct tostruct *) sbrk( limit * sizeof( struct tostruct ) );
+    tos = (struct tostruct *) sbrk( tolimit * sizeof( struct tostruct ) );
     if ( tos == (struct tostruct *) -1 ) {
     if ( tos == (struct tostruct *) -1 ) {
-       write( 2 , MSG , sizeof(MSG) );
+       write( 2 , MSG , sizeof(MSG) - 1 );
        froms = 0;
        tos = 0;
        return;
     }
        froms = 0;
        tos = 0;
        return;
     }
+    minbrk = sbrk(0);
     tos[0].link = 0;
     tos[0].link = 0;
-       /*
-        *      tolimit is what mcount checks to see if
-        *      all the data structures are ready!!!
-        *      make sure it won't overflow.
-        */
-    tolimit = limit;
     monitor( lowpc , highpc , buffer , monsize , tolimit );
 }
 
     monitor( lowpc , highpc , buffer , monsize , tolimit );
 }
 
@@ -73,6 +87,7 @@ _mcleanup()
 {
     int                        fd;
     int                        fromindex;
 {
     int                        fd;
     int                        fromindex;
+    int                        endfrom;
     char               *frompc;
     int                        toindex;
     struct rawarc      rawarc;
     char               *frompc;
     int                        toindex;
     struct rawarc      rawarc;
@@ -86,11 +101,12 @@ _mcleanup()
        fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
 #   endif DEBUG
     write( fd , sbuf , ssiz );
        fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
 #   endif DEBUG
     write( fd , sbuf , ssiz );
-    for ( fromindex = 0 ; fromindex < s_textsize>>1 ; fromindex++ ) {
+    endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
+    for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) {
        if ( froms[fromindex] == 0 ) {
            continue;
        }
        if ( froms[fromindex] == 0 ) {
            continue;
        }
-       frompc = s_lowpc + (fromindex<<1);
+       frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms));
        for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {
 #          ifdef DEBUG
                fprintf( stderr ,
        for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {
 #          ifdef DEBUG
                fprintf( stderr ,
@@ -106,109 +122,141 @@ _mcleanup()
     close( fd );
 }
 
     close( fd );
 }
 
-    /*
-     * This routine is massaged so that it may be jsb'ed to
-     */
-asm("#define _mcount mcount");
+asm(".text");
+asm(".align 2");
+asm("#the beginning of mcount()");
+asm(".data");
 mcount()
 {
 mcount()
 {
-    register char              *selfpc;        /* r11 */
-    register unsigned short    *frompcindex;   /* r10 */
-    register struct tostruct   *top;           /* r9 */
-    static int                 profiling = 0;
-
-    asm( "     forgot to run ex script on gcrt0.s" );
-    asm( "#define r11 r5" );
-    asm( "#define r10 r4" );
-    asm( "#define r9 r3" );
-#ifdef lint
-    selfpc = (char *) 0;
-    frompcindex = 0;
-#else not lint
+       register char                   *selfpc;        /* r11 => r5 */
+       register unsigned short         *frompcindex;   /* r10 => r4 */
+       register struct tostruct        *top;           /* r9  => r3 */
+       register struct tostruct        *prevtop;       /* r8  => r2 */
+       register long                   toindex;        /* r7  => r1 */
+
        /*
         *      find the return address for mcount,
         *      and the return address for mcount's caller.
         */
        /*
         *      find the return address for mcount,
         *      and the return address for mcount's caller.
         */
-    asm("      movl (sp), r11");       /* selfpc = ... (jsb frame) */
-    asm("      movl 16(fp), r10");     /* frompcindex =     (calls frame) */
-#endif not lint
+       asm("   .text");                /* make sure we're in text space */
+       asm("   movl (sp), r11");       /* selfpc = ... (jsb frame) */
+       asm("   movl 16(fp), r10");     /* frompcindex =     (calls frame) */
        /*
         *      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 ( tolimit == 0 ) {
-       goto out;
-    }
-    if ( profiling ) {
-       goto out;
-    }
-    profiling = 1;
+       if (profiling) {
+               goto out;
+       }
+       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 );
-    if ( (unsigned long) frompcindex > s_textsize ) {
-       goto done;
-    }
-    frompcindex = &froms[ ( (long) frompcindex ) >> 1 ];
-    if ( *frompcindex == 0 ) {
-       *frompcindex = ++tos[0].link;
-       if ( *frompcindex >= tolimit ) {
-           goto overflow;
+       frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
+       if ((unsigned long)frompcindex > s_textsize) {
+               goto done;
        }
        }
-       top = &tos[ *frompcindex ];
-       top->selfpc = selfpc;
-       top->count = 0;
-       top->link = 0;
-    } else {
-       top = &tos[ *frompcindex ];
-    }
-    for ( ; /* goto done */ ; top = &tos[ top -> link ] ) {
-       if ( top -> selfpc == selfpc ) {
-           top -> count++;
-           goto done;
+       frompcindex =
+           &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
+       toindex = *frompcindex;
+       if (toindex == 0) {
+               /*
+                *      first time traversing this arc
+                */
+               toindex = ++tos[0].link;
+               if (toindex >= tolimit) {
+                       goto overflow;
+               }
+               *frompcindex = toindex;
+               top = &tos[toindex];
+               top->selfpc = selfpc;
+               top->count = 1;
+               top->link = 0;
+               goto done;
        }
        }
-       if ( top -> link == 0 ) {
-           top -> link = ++tos[0].link;
-           if ( top -> link >= tolimit )
-               goto overflow;
-           top = &tos[ top -> link ];
-           top -> selfpc = selfpc;
-           top -> count = 1;
-           top -> link = 0;
-           goto done;
+       top = &tos[toindex];
+       if (top->selfpc == selfpc) {
+               /*
+                *      arc at front of chain; usual case.
+                */
+               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.
+        */
+       for (; /* goto done */; ) {
+               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.
+                        */
+                       toindex = ++tos[0].link;
+                       if (toindex >= tolimit) {
+                               goto overflow;
+                       }
+                       top = &tos[toindex];
+                       top->selfpc = selfpc;
+                       top->count = 1;
+                       top->link = *frompcindex;
+                       *frompcindex = toindex;
+                       goto done;
+               }
+               /*
+                *      otherwise, check the next arc on the chain.
+                */
+               prevtop = top;
+               top = &tos[top->link];
+               if (top->selfpc == selfpc) {
+                       /*
+                        *      there it is.
+                        *      increment its count
+                        *      move it to the head of the chain.
+                        */
+                       top->count++;
+                       toindex = prevtop->link;
+                       prevtop->link = top->link;
+                       top->link = *frompcindex;
+                       *frompcindex = toindex;
+                       goto done;
+               }
+
        }
        }
-    }
 done:
 done:
-    profiling = 0;
-    /* and fall through */
+       profiling--;
+       /* and fall through */
 out:
 out:
-    asm( "     rsb" );
-    asm( "#undef r11" );
-    asm( "#undef r10" );
-    asm( "#undef r9" );
-    asm( "#undef _mcount");
+       asm("   rsb");
 
 overflow:
 
 overflow:
-    tolimit = 0;
+       profiling++; /* halt further profiling */
 #   define     TOLIMIT "mcount: tos overflow\n"
 #   define     TOLIMIT "mcount: tos overflow\n"
-    write( 2 , TOLIMIT , sizeof( TOLIMIT ) );
-    goto out;
+       write(2, TOLIMIT, sizeof(TOLIMIT) - 1);
+       goto out;
 }
 }
+asm(".text");
+asm("#the end of mcount()");
+asm(".data");
 
 /*VARARGS1*/
 monitor( lowpc , highpc , buf , bufsiz , nfunc )
     char       *lowpc;
     char       *highpc;
 
 /*VARARGS1*/
 monitor( lowpc , highpc , buf , bufsiz , nfunc )
     char       *lowpc;
     char       *highpc;
-    int                *buf, bufsiz;
+    char       *buf;   /* declared ``short buffer[]'' in monitor(3) */
+    int                bufsiz;
     int                nfunc;  /* not used, available for compatability only */
 {
     register o;
 
     if ( lowpc == 0 ) {
     int                nfunc;  /* not used, available for compatability only */
 {
     register o;
 
     if ( lowpc == 0 ) {
-       profil( (char *) 0 , 0 , 0 , 0 );
+       moncontrol(0);
        _mcleanup();
        return;
     }
        _mcleanup();
        return;
     }
@@ -217,37 +265,33 @@ monitor( lowpc , highpc , buf , bufsiz , nfunc )
     ( (struct phdr *) buf ) -> lpc = lowpc;
     ( (struct phdr *) buf ) -> hpc = highpc;
     ( (struct phdr *) buf ) -> ncnt = ssiz;
     ( (struct phdr *) buf ) -> lpc = lowpc;
     ( (struct phdr *) buf ) -> hpc = highpc;
     ( (struct phdr *) buf ) -> ncnt = ssiz;
-    o = sizeof(struct phdr);
-    buf = (int *) ( ( (int) buf ) + o );
-    bufsiz -= o;
+    bufsiz -= sizeof(struct phdr);
     if ( bufsiz <= 0 )
        return;
     if ( bufsiz <= 0 )
        return;
-    o = ( ( (char *) highpc - (char *) lowpc) );
+    o = highpc - lowpc;
     if( bufsiz < o )
     if( bufsiz < o )
-       o = ( (float) bufsiz / o ) * 65536;
+       s_scale = ( (float) bufsiz / o ) * SCALE_1_TO_1;
     else
     else
-       o = 65536;
-    profil( buf , bufsiz , lowpc , o );
+       s_scale = SCALE_1_TO_1;
+    moncontrol(1);
 }
 
 /*
 }
 
 /*
- * This is a stub for the "brk" system call, which we want to
- * catch so that it will not deallocate our data space.
- * (of which the program is not aware)
+ * Control profiling
+ *     profiling is what mcount checks to see if
+ *     all the data structures are ready.
  */
  */
-asm("#define _curbrk curbrk");
-extern char *curbrk;
-
-brk(addr)
-       char *addr;
+moncontrol(mode)
+    int mode;
 {
 {
-
-       if (addr < minsbrk)
-               addr = minsbrk;
-       asm("   chmk    $17");
-       asm("   jcc     1f");
-       asm("   jmp     cerror");
-asm("1:");
-       curbrk = addr;
-       return (0);
+    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;
+    }
 }
 }