source: trunk/third/gcc/gmon.c @ 8834

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