home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / kern / subr_mcount.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-07  |  7.6 KB  |  281 lines

  1. /*
  2.  * Copyright (c) 1982, 1986 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.  *    @(#)subr_mcount.c    7.10 (Berkeley) 5/7/91
  34.  */
  35.  
  36. #ifdef GPROF
  37. #include "gprof.h"
  38. #include "param.h"
  39. #include "systm.h"
  40. #include "malloc.h"
  41.  
  42. /*
  43.  * Froms is actually a bunch of unsigned shorts indexing tos
  44.  */
  45. int    profiling = 3;
  46. u_short    *froms;
  47. struct    tostruct *tos = 0;
  48. long    tolimit = 0;
  49. char    *s_lowpc = (char *)KERNBASE;
  50. extern    char etext;
  51. char    *s_highpc = &etext;
  52. u_long    s_textsize = 0;
  53. int    ssiz;
  54. u_short    *sbuf;
  55. u_short    *kcount;
  56.  
  57. kmstartup()
  58. {
  59.     u_long fromssize, tossize;
  60.  
  61.     /*
  62.      * Round lowpc and highpc to multiples of the density we're using
  63.      * so the rest of the scaling (here and in gprof) stays in ints.
  64.      */
  65.     s_lowpc = (char *)
  66.         ROUNDDOWN((unsigned)s_lowpc, HISTFRACTION*sizeof (HISTCOUNTER));
  67.     s_highpc = (char *)
  68.         ROUNDUP((unsigned)s_highpc, HISTFRACTION*sizeof (HISTCOUNTER));
  69.     s_textsize = s_highpc - s_lowpc;
  70.     printf("Profiling kernel, s_textsize=%d [%x..%x]\n",
  71.         s_textsize, s_lowpc, s_highpc);
  72.     ssiz = (s_textsize / HISTFRACTION) + sizeof (struct phdr);
  73.     sbuf = (u_short *)malloc(ssiz, M_GPROF, M_WAITOK);
  74.     if (sbuf == 0) {
  75.         printf("No space for monitor buffer(s)\n");
  76.         return;
  77.     }
  78.     bzero(sbuf, ssiz);
  79.     fromssize = s_textsize / HASHFRACTION;
  80.     froms = (u_short *)malloc(fromssize, M_GPROF, M_NOWAIT);
  81.     if (froms == 0) {
  82.         printf("No space for monitor buffer(s)\n");
  83.         free(sbuf, M_GPROF);
  84.         sbuf = 0;
  85.         return;
  86.     }
  87.     bzero(froms, fromssize);
  88.     tolimit = s_textsize * ARCDENSITY / 100;
  89.     if (tolimit < MINARCS)
  90.         tolimit = MINARCS;
  91.     else if (tolimit > (0xffff - 1))
  92.         tolimit = 0xffff - 1;
  93.     tossize = tolimit * sizeof (struct tostruct);
  94.     tos = (struct tostruct *)malloc(tossize, M_GPROF, M_WAITOK);
  95.     if (tos == 0) {
  96.         printf("No space for monitor buffer(s)\n");
  97.         free(sbuf, M_GPROF), sbuf = 0;
  98.         free(froms, M_GPROF), froms = 0;
  99.         return;
  100.     }
  101.     bzero(tos, tossize);
  102.     tos[0].link = 0;
  103.     ((struct phdr *)sbuf)->lpc = s_lowpc;
  104.     ((struct phdr *)sbuf)->hpc = s_highpc;
  105.     ((struct phdr *)sbuf)->ncnt = ssiz;
  106.     kcount = (u_short *)(((int)sbuf) + sizeof (struct phdr));
  107. }
  108.  
  109. /*
  110.  * This routine is massaged so that it may be jsb'ed to on vax.
  111.  */
  112. asm(".text");
  113. asm("#the beginning of mcount()");
  114. asm(".data");
  115. mcount()
  116. {
  117.     register char *selfpc;            /* r11 => r5 */
  118.     register u_short *frompcindex;        /* r10 => r4 */
  119.     register struct tostruct *top;        /* r9  => r3 */
  120.     register struct tostruct *prevtop;    /* r8  => r2 */
  121.     register long toindex;            /* r7  => r1 */
  122.     static int s;
  123.  
  124.     asm("    .text");        /* make sure we're in text space */
  125.     /*
  126.      * Check that we are profiling.
  127.      */
  128.     if (profiling)
  129.         goto out;
  130.     /*
  131.      * Find the return address for mcount,
  132.      * and the return address for mcount's caller.
  133.      */
  134. #ifdef lint
  135.     selfpc = (char *)0;
  136.     frompcindex = 0;
  137. #else
  138.     ;                /* avoid label botch */
  139. #ifdef __GNUC__
  140. #if defined(vax)
  141.     Fix Me!!
  142. #endif
  143. #if defined(tahoe)
  144.     Fix Me!!
  145. #endif
  146. #if defined(hp300)
  147.     /*
  148.      * selfpc = pc pushed by mcount jsr,
  149.      * frompcindex = pc pushed by jsr into self.
  150.      * In GCC the caller's stack frame has already been built so we
  151.      * have to chase a6 to find caller's raddr.  This assumes that all
  152.      * routines we are profiling were built with GCC and that all
  153.      * profiled routines use link/unlk.
  154.      */
  155.     asm("movl a6@(4),%0" : "=r" (selfpc));
  156.     asm("movl a6@(0)@(4),%0" : "=r" (frompcindex));
  157. #endif
  158. #else
  159. #if defined(vax)
  160.     asm("    movl (sp), r11");    /* selfpc = ... (jsb frame) */
  161.     asm("    movl 16(fp), r10");    /* frompcindex =     (calls frame) */
  162. #endif
  163. #if defined(tahoe)
  164.     asm("    movl -8(fp),r12");    /* selfpc = callf frame */
  165.     asm("    movl (fp),r11");
  166.     asm("    movl -8(r11),r11");    /* frompcindex = 1 callf frame back */
  167. #endif
  168. #if defined(hp300)
  169.     Fix Me!!
  170. #endif
  171. #endif /* not __GNUC__ */
  172. #endif /* not lint */
  173.     /*
  174.      * Insure that we cannot be recursively invoked.
  175.      * this requires that splhigh() and splx() below
  176.      * do NOT call mcount!
  177.      */
  178. #if defined(hp300)
  179.     asm("movw    sr,%0" : "=g" (s));
  180.     asm("movw    #0x2700,sr");
  181. #else
  182.     s = splhigh();
  183. #endif
  184.     /*
  185.      * Check that frompcindex is a reasonable pc value.
  186.      * For example:    signal catchers get called from the stack,
  187.      *    not from text space.  too bad.
  188.      */
  189.     frompcindex = (u_short *)((long)frompcindex - (long)s_lowpc);
  190.     if ((u_long)frompcindex > s_textsize)
  191.         goto done;
  192.     frompcindex =
  193.         &froms[((long)frompcindex) / (HASHFRACTION * sizeof (*froms))];
  194.     toindex = *frompcindex;
  195.     if (toindex == 0) {
  196.         /*
  197.          * First time traversing this arc
  198.          */
  199.         toindex = ++tos[0].link;
  200.         if (toindex >= tolimit)
  201.             goto overflow;
  202.         *frompcindex = toindex;
  203.         top = &tos[toindex];
  204.         top->selfpc = selfpc;
  205.         top->count = 1;
  206.         top->link = 0;
  207.         goto done;
  208.     }
  209.     top = &tos[toindex];
  210.     if (top->selfpc == selfpc) {
  211.         /*
  212.          * Arc at front of chain; usual case.
  213.          */
  214.         top->count++;
  215.         goto done;
  216.     }
  217.     /*
  218.      * Have to go looking down chain for it.
  219.      * Top points to what we are looking at,
  220.      * prevtop points to previous top.
  221.      * We know it is not at the head of the chain.
  222.      */
  223.     for (; /* goto done */; ) {
  224.         if (top->link == 0) {
  225.             /*
  226.              * Top is end of the chain and none of the chain
  227.              * had top->selfpc == selfpc.
  228.              * So we allocate a new tostruct
  229.              * and link it to the head of the chain.
  230.              */
  231.             toindex = ++tos[0].link;
  232.             if (toindex >= tolimit)
  233.                 goto overflow;
  234.             top = &tos[toindex];
  235.             top->selfpc = selfpc;
  236.             top->count = 1;
  237.             top->link = *frompcindex;
  238.             *frompcindex = toindex;
  239.             goto done;
  240.         }
  241.         /*
  242.          * Otherwise, check the next arc on the chain.
  243.          */
  244.         prevtop = top;
  245.         top = &tos[top->link];
  246.         if (top->selfpc == selfpc) {
  247.             /*
  248.              * There it is, increment its count and
  249.              * move it to the head of the chain.
  250.              */
  251.             top->count++;
  252.             toindex = prevtop->link;
  253.             prevtop->link = top->link;
  254.             top->link = *frompcindex;
  255.             *frompcindex = toindex;
  256.             goto done;
  257.         }
  258.  
  259.     }
  260. done:
  261. #if defined(hp300)
  262.     asm("movw    %0,sr" : : "g" (s));
  263. #else
  264.     splx(s);
  265. #endif
  266.     /* and fall through */
  267. out:
  268. #if defined(vax)
  269.     asm("    rsb");
  270. #endif
  271.     return;
  272. overflow:
  273.     profiling = 3;
  274.     printf("mcount: tos overflow\n");
  275.     goto out;
  276. }
  277. asm(".text");
  278. asm("#the end of mcount()");
  279. asm(".data");
  280. #endif
  281.