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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [newlib-1.18.0/] [libgloss/] [mep/] [mep-gmon.c] - Blame information for rev 853

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 207 jeremybenn
/*-
2
 * Copyright (c) 1991, 1998, 2001 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. [rescinded 22 July 1999]
14
 * 4. Neither the name of the University nor the names of its contributors
15
 *    may be used to endorse or promote products derived from this software
16
 *    without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 */
30
 
31
#ifndef lint
32
static char sccsid[] = "@(#)gmon.c      5.3 (Berkeley) 5/22/91";
33
#endif /* not lint */
34
 
35
#include <fcntl.h>
36
#include <unistd.h>
37
#include <stdlib.h>
38
#include <stdio.h>
39
 
40
#define GMON_PTR_SIZE 4
41
 
42
struct phdr
43
  {
44
    char *lpc;                  /* base pc address of sample buffer */
45
    char *hpc;                  /* max pc address of sampled buffer */
46
    int ncnt;                   /* size of sample buffer (plus this header) */
47
 
48
    char version[4];            /* version number */
49
    char profrate[4];           /* profiling clock rate */
50
    char spare[3*4];            /* reserved */
51
  };
52
 
53
#define GMONVERSION     0x00051879
54
 
55
/*
56
 * Histogram counters are unsigned shorts:
57
 */
58
#define HISTCOUNTER unsigned short
59
 
60
/*
61
 * Fraction of text space to allocate for histogram counters here, 1/2:
62
 */
63
#define HISTFRACTION    2
64
 
65
/*
66
 * Fraction of text space to allocate for from hash buckets.  The
67
 * value of HASHFRACTION is based on the minimum number of bytes of
68
 * separation between two subroutine call points in the object code.
69
 * Given MIN_SUBR_SEPARATION bytes of separation the value of
70
 * HASHFRACTION is calculated as:
71
 *
72
 *      HASHFRACTION = MIN_SUBR_SEPARATION / (2 * sizeof(short) - 1);
73
 *
74
 * For the VAX, the shortest two call sequence is:
75
 *
76
 *      calls   $0,(r0)
77
 *      calls   $0,(r0)
78
 *
79
 * which is separated by only three bytes, thus HASHFRACTION is
80
 * calculated as:
81
 *
82
 *      HASHFRACTION = 3 / (2 * 2 - 1) = 1
83
 *
84
 * Note that the division above rounds down, thus if MIN_SUBR_FRACTION
85
 * is less than three, this algorithm will not work!
86
 */
87
#define HASHFRACTION 1
88
 
89
/*
90
 * Percent of text space to allocate for tostructs with a minimum:
91
 */
92
#define ARCDENSITY      2
93
#define MINARCS         50
94
 
95
struct tostruct
96
  {
97
    char *selfpc;
98
    int count;
99
    unsigned short link;
100
  };
101
 
102
/*
103
 * A raw arc, with pointers to the calling site and the called site
104
 * and a count.  Everything is defined in terms of characters so
105
 * as to get a packed representation (otherwise, different compilers
106
 * might introduce different padding):
107
 */
108
struct rawarc
109
  {
110
    unsigned long raw_frompc;
111
    unsigned long raw_selfpc;
112
    int raw_count;
113
  };
114
 
115
/*
116
 * General rounding functions:
117
 */
118
#define ROUNDDOWN(x,y)  (((x)/(y))*(y))
119
#define ROUNDUP(x,y)    ((((x)+(y)-1)/(y))*(y))
120
 
121
 
122
#ifdef __alpha
123
extern char *sbrk ();
124
#endif
125
 
126
    /*
127
     *  froms is actually a bunch of unsigned shorts indexing tos
128
     */
129
static int profiling = 3;
130
static unsigned short *froms;
131
static struct tostruct *tos = 0;
132
static long tolimit = 0;
133
static char *s_lowpc = 0;
134
static char *s_highpc = 0;
135
static unsigned long s_textsize = 0;
136
 
137
static int ssiz;
138
static char *sbuf;
139
static int s_scale;
140
    /* see profil(2) where this is describe (incorrectly) */
141
#define         SCALE_1_TO_1    0x10000L
142
 
143
#define MSG "No space for profiling buffer(s)\n"
144
 
145
#ifndef O_BINARY
146
#define O_BINARY 0
147
#endif
148
 
149
static void
150
moncleanup ()
151
{
152
  int fd;
153
  int fromindex;
154
  int endfrom;
155
  char *frompc;
156
  int toindex;
157
  struct rawarc rawarc;
158
 
159
  profiling = 1;
160
  fd = open ("gmon.out", O_WRONLY|O_TRUNC|O_CREAT|O_BINARY, 0666);
161
  if (fd < 0)
162
    {
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
    {
173
      if (froms[fromindex] == 0)
174
        {
175
          continue;
176
        }
177
      frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof (*froms));
178
      for (toindex = froms[fromindex]; toindex != 0;
179
           toindex = tos[toindex].link)
180
        {
181
#ifdef DEBUG
182
          fprintf (stderr,
183
                   "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n",
184
                   frompc, tos[toindex].selfpc, tos[toindex].count);
185
#endif /* DEBUG */
186
          rawarc.raw_frompc = (unsigned long) frompc;
187
          rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
188
          rawarc.raw_count = tos[toindex].count;
189
          write (fd, &rawarc, sizeof rawarc);
190
        }
191
    }
192
  close (fd);
193
}
194
 
195
static void
196
monstartup (lowpc, highpc)
197
     char *lowpc;
198
     char *highpc;
199
{
200
  int monsize;
201
  char *buffer;
202
  register int o;
203
 
204
  atexit (moncleanup);
205
 
206
  /*
207
   *    round lowpc and highpc to multiples of the density we're using
208
   *    so the rest of the scaling (here and in gprof) stays in ints.
209
   */
210
  lowpc = (char *)
211
    ROUNDDOWN ((unsigned) lowpc, HISTFRACTION * sizeof (HISTCOUNTER));
212
  s_lowpc = lowpc;
213
  highpc = (char *)
214
    ROUNDUP ((unsigned) highpc, HISTFRACTION * sizeof (HISTCOUNTER));
215
  s_highpc = highpc;
216
  s_textsize = highpc - lowpc;
217
  monsize = (s_textsize / HISTFRACTION) + sizeof (struct phdr);
218
  buffer = sbrk (monsize);
219
  if (buffer == (char *) -1)
220
    {
221
      write (2, MSG, sizeof (MSG));
222
      return;
223
    }
224
  froms = (unsigned short *) sbrk (s_textsize / HASHFRACTION);
225
  if (froms == (unsigned short *) -1)
226
    {
227
      write (2, MSG, sizeof (MSG));
228
      froms = 0;
229
      return;
230
    }
231
  tolimit = s_textsize * ARCDENSITY / 100;
232
  if (tolimit < MINARCS)
233
    {
234
      tolimit = MINARCS;
235
    }
236
  else if (tolimit > 65534)
237
    {
238
      tolimit = 65534;
239
    }
240
  tos = (struct tostruct *) sbrk (tolimit * sizeof (struct tostruct));
241
  if (tos == (struct tostruct *) -1)
242
    {
243
      write (2, MSG, sizeof (MSG));
244
      froms = 0;
245
      tos = 0;
246
      return;
247
    }
248
  tos[0].link = 0;
249
  sbuf = buffer;
250
  ssiz = monsize;
251
  ((struct phdr *) buffer)->lpc = lowpc;
252
  ((struct phdr *) buffer)->hpc = highpc;
253
  ((struct phdr *) buffer)->ncnt = ssiz;
254
  monsize -= sizeof (struct phdr);
255
  if (monsize <= 0)
256
    return;
257
  o = highpc - lowpc;
258
  if (monsize < o)
259
#if 0
260
    s_scale = ((float) monsize / o) * SCALE_1_TO_1;
261
#else /* avoid floating point */
262
    {
263
      int quot = o / monsize;
264
 
265
      if (quot >= 0x10000)
266
        s_scale = 1;
267
      else if (quot >= 0x100)
268
        s_scale = 0x10000 / quot;
269
      else if (o >= 0x800000)
270
        s_scale = 0x1000000 / (o / (monsize >> 8));
271
      else
272
        s_scale = 0x1000000 / ((o << 8) / monsize);
273
    }
274
#endif
275
  else
276
    s_scale = SCALE_1_TO_1;
277
  profiling = 0;
278
}
279
 
280
/* These happen to be in the right place because of how crt0 works */
281
extern char __attribute__((far)) _start;
282
extern char __attribute__((far)) _etext;
283
 
284
void
285
__mep_mcount_2 (selfpc, frompcindex)
286
     char *selfpc;
287
     unsigned short *frompcindex;
288
{
289
  struct tostruct *top;
290
  struct tostruct *prevtop;
291
  long toindex;
292
  static int initialized = 0;
293
 
294
  if (!initialized)
295
    {
296
      initialized = 1;
297
      monstartup (&_start, &_etext);
298
    }
299
 
300
  /*
301
   *    check that we are profiling
302
   *    and that we aren't recursively invoked.
303
   */
304
  if (profiling)
305
    {
306
      goto out;
307
    }
308
  profiling++;
309
  /*
310
   *    check that frompcindex is a reasonable pc value.
311
   *    for example:    signal catchers get called from the stack,
312
   *                    not from text space.  too bad.
313
   */
314
  frompcindex = (unsigned short *) ((long) frompcindex - (long) s_lowpc);
315
  if ((unsigned long) frompcindex > s_textsize)
316
    {
317
      goto done;
318
    }
319
  frompcindex =
320
    &froms[((long) frompcindex) / (HASHFRACTION * sizeof (*froms))];
321
  toindex = *frompcindex;
322
  if (toindex == 0)
323
    {
324
      /*
325
       *  first time traversing this arc
326
       */
327
      toindex = ++tos[0].link;
328
      if (toindex >= tolimit)
329
        {
330
          goto overflow;
331
        }
332
      *frompcindex = toindex;
333
      top = &tos[toindex];
334
      top->selfpc = selfpc;
335
      top->count = 1;
336
      top->link = 0;
337
      goto done;
338
    }
339
  top = &tos[toindex];
340
  if (top->selfpc == selfpc)
341
    {
342
      /*
343
       *  arc at front of chain; usual case.
344
       */
345
      top->count++;
346
      goto done;
347
    }
348
  /*
349
   *    have to go looking down chain for it.
350
   *    top points to what we are looking at,
351
   *    prevtop points to previous top.
352
   *    we know it is not at the head of the chain.
353
   */
354
  for (; /* goto done */ ;)
355
    {
356
      if (top->link == 0)
357
        {
358
          /*
359
           *        top is end of the chain and none of the chain
360
           *        had top->selfpc == selfpc.
361
           *        so we allocate a new tostruct
362
           *        and link it to the head of the chain.
363
           */
364
          toindex = ++tos[0].link;
365
          if (toindex >= tolimit)
366
            {
367
              goto overflow;
368
            }
369
          top = &tos[toindex];
370
          top->selfpc = selfpc;
371
          top->count = 1;
372
          top->link = *frompcindex;
373
          *frompcindex = toindex;
374
          goto done;
375
        }
376
      /*
377
       *  otherwise, check the next arc on the chain.
378
       */
379
      prevtop = top;
380
      top = &tos[top->link];
381
      if (top->selfpc == selfpc)
382
        {
383
          /*
384
           *        there it is.
385
           *        increment its count
386
           *        move it to the head of the chain.
387
           */
388
          top->count++;
389
          toindex = prevtop->link;
390
          prevtop->link = top->link;
391
          top->link = *frompcindex;
392
          *frompcindex = toindex;
393
          goto done;
394
        }
395
 
396
    }
397
done:
398
  profiling--;
399
  /* and fall through */
400
out:
401
  return;                       /* normal return restores saved registers */
402
 
403
overflow:
404
  profiling++;                  /* halt further profiling */
405
#   define      TOLIMIT "mcount: tos overflow\n"
406
  write (2, TOLIMIT, sizeof (TOLIMIT));
407
  goto out;
408
}
409
 
410
 
411
 

powered by: WebSVN 2.1.0

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