Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Johnston <jjohnstn@redhat.com>2007-02-09 00:22:05 +0300
committerJeff Johnston <jjohnstn@redhat.com>2007-02-09 00:22:05 +0300
commit1d94f7311465ca3c972541fc2c7c02255640d29c (patch)
tree645846719ee345cc3ff3bcd28b40b6baf69e43ea /libgloss/mep/mep-gmon.c
parentaafecff6a8081056a732b78582f7eebb5f6fd022 (diff)
2007-02-08 Dave Brolley <brolley@redhat.com>
* mep: New target directory. * README: Add MeP. * configure.in: Add support for MeP. * configure: Regenerated. * mep/configure.in: New file. * mep/configure: Ditto. * mep/Makefile.in: Ditto. * mep/aclocal.m4: Ditto. * mep/crt0.S: Ditto. * mep/crtn.S: Ditto. * mep/sim-crt0.S: Ditto. * mep/sim-crtn.S: Ditto. * mep/fmax.ld: Ditto. * mep/gcov-io.h: Ditto. * mep/gmap_default.ld: Ditto. * mep/handlers.c: Ditto. * mep/h_reset.c: Ditto. * mep/isatty.c: Ditto. * mep/mep-bb.c: Ditto. * mep/mep-gmon.c: Ditto. * mep/min.ld: Ditto. * mep/read.c: Ditto. * mep/sbrk.c: Ditto. * mep/sdram-crt0.S: Ditto. * mep/sdram-crtn.S: Ditto. * mep/simnovec-crt0.S: Ditto. * mep/simple.ld: Ditto. * mep/simsdran-crt0.S: Ditto. * mep/syscalls.S: Ditto. * mep/write.c: Ditto.
Diffstat (limited to 'libgloss/mep/mep-gmon.c')
-rw-r--r--libgloss/mep/mep-gmon.c411
1 files changed, 411 insertions, 0 deletions
diff --git a/libgloss/mep/mep-gmon.c b/libgloss/mep/mep-gmon.c
new file mode 100644
index 000000000..72d6369a3
--- /dev/null
+++ b/libgloss/mep/mep-gmon.c
@@ -0,0 +1,411 @@
+/*-
+ * Copyright (c) 1991, 1998, 2001 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. [rescinded 22 July 1999]
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)gmon.c 5.3 (Berkeley) 5/22/91";
+#endif /* not lint */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define GMON_PTR_SIZE 4
+
+struct phdr
+ {
+ char *lpc; /* base pc address of sample buffer */
+ char *hpc; /* max pc address of sampled buffer */
+ int ncnt; /* size of sample buffer (plus this header) */
+
+ char version[4]; /* version number */
+ char profrate[4]; /* profiling clock rate */
+ char spare[3*4]; /* reserved */
+ };
+
+#define GMONVERSION 0x00051879
+
+/*
+ * Histogram counters are unsigned shorts:
+ */
+#define HISTCOUNTER unsigned short
+
+/*
+ * Fraction of text space to allocate for histogram counters here, 1/2:
+ */
+#define HISTFRACTION 2
+
+/*
+ * Fraction of text space to allocate for from hash buckets. The
+ * value of HASHFRACTION is based on the minimum number of bytes of
+ * separation between two subroutine call points in the object code.
+ * Given MIN_SUBR_SEPARATION bytes of separation the value of
+ * HASHFRACTION is calculated as:
+ *
+ * HASHFRACTION = MIN_SUBR_SEPARATION / (2 * sizeof(short) - 1);
+ *
+ * For the VAX, the shortest two call sequence is:
+ *
+ * calls $0,(r0)
+ * calls $0,(r0)
+ *
+ * which is separated by only three bytes, thus HASHFRACTION is
+ * calculated as:
+ *
+ * HASHFRACTION = 3 / (2 * 2 - 1) = 1
+ *
+ * Note that the division above rounds down, thus if MIN_SUBR_FRACTION
+ * is less than three, this algorithm will not work!
+ */
+#define HASHFRACTION 1
+
+/*
+ * Percent of text space to allocate for tostructs with a minimum:
+ */
+#define ARCDENSITY 2
+#define MINARCS 50
+
+struct tostruct
+ {
+ char *selfpc;
+ int count;
+ unsigned short link;
+ };
+
+/*
+ * A raw arc, with pointers to the calling site and the called site
+ * and a count. Everything is defined in terms of characters so
+ * as to get a packed representation (otherwise, different compilers
+ * might introduce different padding):
+ */
+struct rawarc
+ {
+ unsigned long raw_frompc;
+ unsigned long raw_selfpc;
+ int raw_count;
+ };
+
+/*
+ * General rounding functions:
+ */
+#define ROUNDDOWN(x,y) (((x)/(y))*(y))
+#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y))
+
+
+#ifdef __alpha
+extern char *sbrk ();
+#endif
+
+ /*
+ * froms is actually a bunch of unsigned shorts indexing tos
+ */
+static int profiling = 3;
+static unsigned short *froms;
+static struct tostruct *tos = 0;
+static long tolimit = 0;
+static char *s_lowpc = 0;
+static char *s_highpc = 0;
+static unsigned long s_textsize = 0;
+
+static int ssiz;
+static char *sbuf;
+static int s_scale;
+ /* see profil(2) where this is describe (incorrectly) */
+#define SCALE_1_TO_1 0x10000L
+
+#define MSG "No space for profiling buffer(s)\n"
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static void
+moncleanup ()
+{
+ int fd;
+ int fromindex;
+ int endfrom;
+ char *frompc;
+ int toindex;
+ struct rawarc rawarc;
+
+ profiling = 1;
+ fd = open ("gmon.out", O_WRONLY|O_TRUNC|O_CREAT|O_BINARY, 0666);
+ if (fd < 0)
+ {
+ perror ("mcount: gmon.out");
+ return;
+ }
+#ifdef DEBUG
+ fprintf (stderr, "[mcleanup] sbuf 0x%x ssiz %d\n", sbuf, ssiz);
+#endif /* DEBUG */
+ write (fd, sbuf, ssiz);
+ endfrom = s_textsize / (HASHFRACTION * sizeof (*froms));
+ for (fromindex = 0; fromindex < endfrom; fromindex++)
+ {
+ if (froms[fromindex] == 0)
+ {
+ continue;
+ }
+ frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof (*froms));
+ for (toindex = froms[fromindex]; toindex != 0;
+ toindex = tos[toindex].link)
+ {
+#ifdef DEBUG
+ fprintf (stderr,
+ "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n",
+ frompc, tos[toindex].selfpc, tos[toindex].count);
+#endif /* DEBUG */
+ rawarc.raw_frompc = (unsigned long) frompc;
+ rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
+ rawarc.raw_count = tos[toindex].count;
+ write (fd, &rawarc, sizeof rawarc);
+ }
+ }
+ close (fd);
+}
+
+static void
+monstartup (lowpc, highpc)
+ char *lowpc;
+ char *highpc;
+{
+ int monsize;
+ char *buffer;
+ register int o;
+
+ atexit (moncleanup);
+
+ /*
+ * round lowpc and highpc to multiples of the density we're using
+ * so the rest of the scaling (here and in gprof) stays in ints.
+ */
+ lowpc = (char *)
+ ROUNDDOWN ((unsigned) lowpc, HISTFRACTION * sizeof (HISTCOUNTER));
+ s_lowpc = lowpc;
+ highpc = (char *)
+ ROUNDUP ((unsigned) highpc, HISTFRACTION * sizeof (HISTCOUNTER));
+ s_highpc = highpc;
+ s_textsize = highpc - lowpc;
+ monsize = (s_textsize / HISTFRACTION) + sizeof (struct phdr);
+ buffer = sbrk (monsize);
+ if (buffer == (char *) -1)
+ {
+ write (2, MSG, sizeof (MSG));
+ return;
+ }
+ froms = (unsigned short *) sbrk (s_textsize / HASHFRACTION);
+ if (froms == (unsigned short *) -1)
+ {
+ write (2, MSG, sizeof (MSG));
+ froms = 0;
+ return;
+ }
+ tolimit = s_textsize * ARCDENSITY / 100;
+ if (tolimit < MINARCS)
+ {
+ tolimit = MINARCS;
+ }
+ else if (tolimit > 65534)
+ {
+ tolimit = 65534;
+ }
+ tos = (struct tostruct *) sbrk (tolimit * sizeof (struct tostruct));
+ if (tos == (struct tostruct *) -1)
+ {
+ write (2, MSG, sizeof (MSG));
+ froms = 0;
+ tos = 0;
+ return;
+ }
+ tos[0].link = 0;
+ sbuf = buffer;
+ ssiz = monsize;
+ ((struct phdr *) buffer)->lpc = lowpc;
+ ((struct phdr *) buffer)->hpc = highpc;
+ ((struct phdr *) buffer)->ncnt = ssiz;
+ monsize -= sizeof (struct phdr);
+ if (monsize <= 0)
+ return;
+ o = highpc - lowpc;
+ if (monsize < o)
+#if 0
+ s_scale = ((float) monsize / o) * SCALE_1_TO_1;
+#else /* avoid floating point */
+ {
+ int quot = o / monsize;
+
+ if (quot >= 0x10000)
+ s_scale = 1;
+ else if (quot >= 0x100)
+ s_scale = 0x10000 / quot;
+ else if (o >= 0x800000)
+ s_scale = 0x1000000 / (o / (monsize >> 8));
+ else
+ s_scale = 0x1000000 / ((o << 8) / monsize);
+ }
+#endif
+ else
+ s_scale = SCALE_1_TO_1;
+ profiling = 0;
+}
+
+/* These happen to be in the right place because of how crt0 works */
+extern char __attribute__((far)) _start;
+extern char __attribute__((far)) _etext;
+
+void
+__mep_mcount_2 (selfpc, frompcindex)
+ char *selfpc;
+ unsigned short *frompcindex;
+{
+ struct tostruct *top;
+ struct tostruct *prevtop;
+ long toindex;
+ static int initialized = 0;
+
+ if (!initialized)
+ {
+ initialized = 1;
+ monstartup (&_start, &_etext);
+ }
+
+ /*
+ * check that we are profiling
+ * and that we aren't recursively invoked.
+ */
+ if (profiling)
+ {
+ goto out;
+ }
+ profiling++;
+ /*
+ * check that frompcindex is a reasonable pc value.
+ * for example: signal catchers get called from the stack,
+ * not from text space. too bad.
+ */
+ frompcindex = (unsigned short *) ((long) frompcindex - (long) s_lowpc);
+ if ((unsigned long) frompcindex > s_textsize)
+ {
+ goto done;
+ }
+ frompcindex =
+ &froms[((long) frompcindex) / (HASHFRACTION * sizeof (*froms))];
+ toindex = *frompcindex;
+ if (toindex == 0)
+ {
+ /*
+ * first time traversing this arc
+ */
+ toindex = ++tos[0].link;
+ if (toindex >= tolimit)
+ {
+ goto overflow;
+ }
+ *frompcindex = toindex;
+ top = &tos[toindex];
+ top->selfpc = selfpc;
+ top->count = 1;
+ top->link = 0;
+ goto done;
+ }
+ top = &tos[toindex];
+ if (top->selfpc == selfpc)
+ {
+ /*
+ * arc at front of chain; usual case.
+ */
+ top->count++;
+ goto done;
+ }
+ /*
+ * have to go looking down chain for it.
+ * top points to what we are looking at,
+ * prevtop points to previous top.
+ * we know it is not at the head of the chain.
+ */
+ for (; /* goto done */ ;)
+ {
+ if (top->link == 0)
+ {
+ /*
+ * top is end of the chain and none of the chain
+ * had top->selfpc == selfpc.
+ * so we allocate a new tostruct
+ * and link it to the head of the chain.
+ */
+ toindex = ++tos[0].link;
+ if (toindex >= tolimit)
+ {
+ goto overflow;
+ }
+ top = &tos[toindex];
+ top->selfpc = selfpc;
+ top->count = 1;
+ top->link = *frompcindex;
+ *frompcindex = toindex;
+ goto done;
+ }
+ /*
+ * otherwise, check the next arc on the chain.
+ */
+ prevtop = top;
+ top = &tos[top->link];
+ if (top->selfpc == selfpc)
+ {
+ /*
+ * there it is.
+ * increment its count
+ * move it to the head of the chain.
+ */
+ top->count++;
+ toindex = prevtop->link;
+ prevtop->link = top->link;
+ top->link = *frompcindex;
+ *frompcindex = toindex;
+ goto done;
+ }
+
+ }
+done:
+ profiling--;
+ /* and fall through */
+out:
+ return; /* normal return restores saved registers */
+
+overflow:
+ profiling++; /* halt further profiling */
+# define TOLIMIT "mcount: tos overflow\n"
+ write (2, TOLIMIT, sizeof (TOLIMIT));
+ goto out;
+}
+
+
+