source: trunk/libs/newlib/src/libgloss/i386/cygmon-gmon.c @ 474

Last change on this file since 474 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 9.3 KB
Line 
1/*-
2 * Copyright (c) 1991, 2000 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
61static 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 */
74static int              profiling = 3;
75static unsigned short   *froms;
76static struct tostruct  *tos = 0;
77static long             tolimit = 0;
78static char             *s_lowpc = 0;
79static char             *s_highpc = 0;
80static unsigned long    s_textsize = 0;
81
82static int      ssiz;
83static char     *sbuf;
84static 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
90extern int errno;
91
92int
93monstartup(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
168void
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
200static 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    }
326done:
327  profiling--;
328  /* and fall through */
329out:
330  return;               /* normal return restores saved registers */
331
332overflow:
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 */
344moncontrol(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}
Note: See TracBrowser for help on using the repository browser.