OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [newlib/] [libgloss/] [i386/] [cygmon-gmon.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 56 joel
/*-
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
/*
35
 * This is a modified gmon.c by J.W.Hawtin <oolon@ankh.org>,
36
 * 14/8/96 based on the original gmon.c in GCC and the hacked version
37
 * solaris 2 sparc version (config/sparc/gmon-sol.c) by Mark Eichin. To do
38
 * process profiling on solaris 2.X X86
39
 *
40
 * It must be used in conjunction with sol2-gc1.asm, which is used to start
41
 * and stop process monitoring.
42
 *
43
 * Differences.
44
 *
45
 * On Solaris 2 _mcount is called by library functions not mcount, so support
46
 * has been added for both.
47
 *
48
 * Also the prototype for profil() is different
49
 *
50
 * Solaris 2 does not seem to have char *minbrk which allows the setting of
51
 * the minimum SBRK region so this code has been removed and lets pray malloc
52
 * does not mess it up.
53
 *
54
 * Notes
55
 *
56
 * This code could easily be integrated with the original gmon.c and perhaps
57
 * should be.
58
 */
59
 
60
#ifndef lint
61
static char sccsid[] = "@(#)gmon.c      5.3 (Berkeley) 5/22/91";
62
#endif /* not lint */
63
 
64
#define DEBUG
65
#ifdef DEBUG
66
#include <stdio.h>
67
#endif
68
 
69
#include "cygmon-gmon.h"
70
 
71
/*
72
 *      froms is actually a bunch of unsigned shorts indexing tos
73
 */
74
static int              profiling = 3;
75
static unsigned short   *froms;
76
static struct tostruct  *tos = 0;
77
static long             tolimit = 0;
78
static char             *s_lowpc = 0;
79
static char             *s_highpc = 0;
80
static unsigned long    s_textsize = 0;
81
 
82
static int      ssiz;
83
static char     *sbuf;
84
static int      s_scale;
85
    /* see profil(2) where this is describe (incorrectly) */
86
#define         SCALE_1_TO_1    0x10000L
87
 
88
#define MSG "No space for profiling buffer(s)\n"
89
 
90
extern int errno;
91
 
92
int
93
monstartup(lowpc, highpc)
94
     char       *lowpc;
95
     char       *highpc;
96
{
97
  int           monsize;
98
  char          *buffer;
99
  register int  o;
100
 
101
        /*
102
         *      round lowpc and highpc to multiples of the density we're using
103
         *      so the rest of the scaling (here and in gprof) stays in ints.
104
         */
105
  lowpc = (char *)
106
    ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
107
  s_lowpc = lowpc;
108
  highpc = (char *)
109
    ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
110
  s_highpc = highpc;
111
  s_textsize = highpc - lowpc;
112
  monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
113
  buffer = (char *) sbrk (monsize);
114
  if (buffer == (char *) -1)
115
    {
116
      write (2, MSG , sizeof(MSG));
117
      return;
118
    }
119
  bzero (buffer, monsize);
120
  froms = (unsigned short *) sbrk (s_textsize / HASHFRACTION);
121
  if (froms == (unsigned short *) -1)
122
    {
123
      write(2, MSG, sizeof(MSG));
124
      froms = 0;
125
      return;
126
    }
127
  bzero (froms, s_textsize / HASHFRACTION);
128
  tolimit = s_textsize * ARCDENSITY / 100;
129
  if (tolimit < MINARCS)
130
    {
131
      tolimit = MINARCS;
132
    }
133
  else
134
    {
135
      if (tolimit > 65534)
136
        {
137
          tolimit = 65534;
138
        }
139
    }
140
  tos = (struct tostruct *) sbrk( tolimit * sizeof( struct tostruct ) );
141
  if (tos == (struct tostruct *) -1)
142
    {
143
      write (2, MSG, sizeof(MSG));
144
      froms = 0;
145
      tos = 0;
146
      return;
147
    }
148
  bzero (tos, tolimit * sizeof( struct tostruct ) );
149
  tos[0].link = 0;
150
  sbuf = buffer;
151
  ssiz = monsize;
152
  ( (struct phdr *) buffer ) -> lpc = lowpc;
153
  ( (struct phdr *) buffer ) -> hpc = highpc;
154
  ( (struct phdr *) buffer ) -> ncnt = ssiz;
155
  monsize -= sizeof(struct phdr);
156
  if ( monsize <= 0 )
157
    return;
158
  o = highpc - lowpc;
159
  if (monsize < o)
160
    {
161
        s_scale = ( (float) monsize / o ) * SCALE_1_TO_1;
162
    }
163
  else
164
    s_scale = SCALE_1_TO_1;
165
  moncontrol (1);
166
}
167
 
168
void
169
_mcleanup()
170
{
171
  int           fd;
172
  int           fromindex;
173
  int           endfrom;
174
  char          *frompc;
175
  int           toindex;
176
  struct rawarc rawarc;
177
 
178
  moncontrol (0);
179
  profil_write (1, sbuf, ssiz);
180
 
181
  endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
182
  for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ )
183
    {
184
      if ( froms[fromindex] == 0 )
185
        {
186
          continue;
187
        }
188
      frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms));
189
      for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link)
190
        {
191
          rawarc.raw_frompc = (unsigned long) frompc;
192
          rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
193
          rawarc.raw_count = tos[toindex].count;
194
          profil_write (2, &rawarc, sizeof (rawarc));
195
        }
196
    }
197
  profil_write (3, 0, 0);
198
}
199
 
200
static char already_setup = 0;
201
 
202
_mcount()
203
{
204
  register char                 *selfpc;
205
  register unsigned short       *frompcindex;
206
  register struct tostruct      *top;
207
  register struct tostruct      *prevtop;
208
  register long                 toindex;
209
 
210
  /*
211
   *    find the return address for mcount,
212
   *    and the return address for mcount's caller.
213
   */
214
 
215
  /* selfpc = pc pushed by mcount call.
216
     This identifies the function that was just entered.  */
217
  selfpc = (void *) __builtin_return_address (0);
218
  /* frompcindex = pc in preceding frame.
219
     This identifies the caller of the function just entered.  */
220
  frompcindex = (void *) __builtin_return_address (1);
221
 
222
  if (! already_setup)
223
    {
224
      extern etext();
225
      extern _ftext();
226
      already_setup = 1;
227
      monstartup(_ftext, etext);
228
      atexit(_mcleanup);
229
    }
230
  /*
231
   *    check that we are profiling
232
   *    and that we aren't recursively invoked.
233
   */
234
  if (profiling)
235
    {
236
      goto out;
237
    }
238
  profiling++;
239
  /*
240
   *    check that frompcindex is a reasonable pc value.
241
   *    for example:    signal catchers get called from the stack,
242
   *                    not from text space.  too bad.
243
   */
244
  frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
245
  if ((unsigned long)frompcindex > s_textsize)
246
    {
247
      goto done;
248
    }
249
  frompcindex =
250
    &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
251
  toindex = *frompcindex;
252
  if (toindex == 0)
253
    {
254
      /*
255
       *        first time traversing this arc
256
       */
257
      toindex = ++tos[0].link;
258
      if (toindex >= tolimit)
259
        {
260
          goto overflow;
261
        }
262
      *frompcindex = toindex;
263
      top = &tos[toindex];
264
      top->selfpc = selfpc;
265
      top->count = 1;
266
      top->link = 0;
267
      goto done;
268
    }
269
  top = &tos[toindex];
270
  if (top->selfpc == selfpc)
271
    {
272
      /*
273
       *        arc at front of chain; usual case.
274
       */
275
      top->count++;
276
      goto done;
277
    }
278
  /*
279
   *    have to go looking down chain for it.
280
   *    top points to what we are looking at,
281
   *    prevtop points to previous top.
282
   *    we know it is not at the head of the chain.
283
   */
284
  for (; /* goto done */; )
285
    {
286
      if (top->link == 0)
287
        {
288
          /*
289
           *    top is end of the chain and none of the chain
290
           *    had top->selfpc == selfpc.
291
           *    so we allocate a new tostruct
292
           *    and link it to the head of the chain.
293
           */
294
          toindex = ++tos[0].link;
295
          if (toindex >= tolimit)
296
            {
297
              goto overflow;
298
            }
299
          top = &tos[toindex];
300
          top->selfpc = selfpc;
301
          top->count = 1;
302
          top->link = *frompcindex;
303
          *frompcindex = toindex;
304
          goto done;
305
        }
306
      /*
307
       *        otherwise, check the next arc on the chain.
308
       */
309
      prevtop = top;
310
      top = &tos[top->link];
311
      if (top->selfpc == selfpc)
312
        {
313
          /*
314
           *    there it is.
315
           *    increment its count
316
           *    move it to the head of the chain.
317
           */
318
          top->count++;
319
          toindex = prevtop->link;
320
          prevtop->link = top->link;
321
          top->link = *frompcindex;
322
          *frompcindex = toindex;
323
          goto done;
324
        }
325
    }
326
done:
327
  profiling--;
328
  /* and fall through */
329
out:
330
  return;               /* normal return restores saved registers */
331
 
332
overflow:
333
  profiling++; /* halt further profiling */
334
#   define      TOLIMIT "mcount: tos overflow\n"
335
  write (2, TOLIMIT, sizeof(TOLIMIT));
336
  goto out;
337
}
338
 
339
/*
340
 * Control profiling
341
 *      profiling is what mcount checks to see if
342
 *      all the data structures are ready.
343
 */
344
moncontrol(mode)
345
    int mode;
346
{
347
  if (mode)
348
    {
349
      /* start */
350
      profil((unsigned short *)(sbuf + sizeof(struct phdr)),
351
             ssiz - sizeof(struct phdr),
352
             (int)s_lowpc, s_scale);
353
 
354
      profiling = 0;
355
    }
356
  else
357
    {
358
      /* stop */
359
      profil((unsigned short *)0, 0, 0, 0);
360
      profiling = 3;
361
    }
362
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.