aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Selkirk <paul@psgd.org>2018-12-02 17:19:44 -0500
committerPaul Selkirk <paul@psgd.org>2018-12-02 17:19:44 -0500
commite99737c12cac1fcc8604ac89a14dac5b2606a42d (patch)
tree686c5b7aaca400cfab1800a45d4fa07b24a9bf08
parent97034edb35e92361daaa24512989d00f6c3fd517 (diff)
Clean up the profiling code to the point where I stand a chance of
understanding it 6 months from now. While I'm at it, try to make it a little more efficient (because 50-60% of time in a typical profiling run is spent in the function-entry counting), and collapse profil.c into gmon.c.
-rw-r--r--libraries/libprof/Makefile2
-rw-r--r--libraries/libprof/gmon.c427
-rw-r--r--libraries/libprof/gmon.h57
-rw-r--r--libraries/libprof/profil.c96
-rw-r--r--libraries/libprof/profil.h60
5 files changed, 197 insertions, 445 deletions
diff --git a/libraries/libprof/Makefile b/libraries/libprof/Makefile
index 37b9a23..28bedea 100644
--- a/libraries/libprof/Makefile
+++ b/libraries/libprof/Makefile
@@ -1,6 +1,6 @@
LIB = libprof.a
-OBJS = gmon.o profil.o profiler.o memfunc.o
+OBJS = gmon.o profiler.o memfunc.o
# Don't profile the profiling code, because that way lies madness (and recursion).
CFLAGS := $(subst -pg,,$(CFLAGS))
diff --git a/libraries/libprof/gmon.c b/libraries/libprof/gmon.c
index 317a173..a34f1a2 100644
--- a/libraries/libprof/gmon.c
+++ b/libraries/libprof/gmon.c
@@ -36,289 +36,226 @@
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
-#include <stdint.h>
-#include "gmon.h"
-#include "profil.h"
#include <string.h>
+#include "gmon.h"
#define bzero(ptr,size) memset (ptr, 0, size);
#define ERR(s) write(2, s, sizeof(s))
-struct gmonparam _gmonparam = { GMON_PROF_OFF, NULL, 0, NULL, 0, NULL, 0, 0L, 0, 0, 0};
-static char already_setup = 0; /* flag to indicate if we need to init */
-static int s_scale;
-/* see profil(2) where this is described (incorrectly) */
-#define SCALE_1_TO_1 0x10000L
+/* profiling frequency. (No larger than 1000) */
+/* Note this doesn't set the frequency, but merely describes it. */
+#define PROF_HZ 1000
-static void moncontrol(int mode);
+struct gmonparam _gmonparam = { off, NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, 0};
-void monstartup (size_t lowpc, size_t highpc) {
- register size_t o;
- char *cp;
- struct gmonparam *p = &_gmonparam;
+void monstartup(size_t lowpc, size_t highpc)
+{
+ static char already_setup = 0;
+ struct gmonparam *p = &_gmonparam;
- if (already_setup) {
- /* zero out cp as value will be added there */
- bzero(p->tos, p->kcountsize + p->fromssize + p->tossize);
- moncontrol(1); /* start */
- return;
- }
- already_setup = 1;
+ if (already_setup) {
+ /* reinitialize counters and arcs */
+ bzero(p->kcount, p->kcountsize);
+ bzero(p->froms, p->fromssize);
+ bzero(p->tos, p->tossize);
+ p->state = on;
+ return;
+ }
+ already_setup = 1;
- /* enable semihosting, for eventual output */
- extern void initialise_monitor_handles(void);
- initialise_monitor_handles();
+ /* enable semihosting, for eventual output */
+ extern void initialise_monitor_handles(void);
+ initialise_monitor_handles();
- /*
- * 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.
- */
- p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER));
- p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER));
- p->textsize = p->highpc - p->lowpc + 0x20;
- p->kcountsize = p->textsize / HISTFRACTION;
- p->fromssize = p->textsize / HASHFRACTION;
- p->tolimit = p->textsize * ARCDENSITY / 100;
- if (p->tolimit < MINARCS) {
- p->tolimit = MINARCS;
- } else if (p->tolimit > MAXARCS) {
- p->tolimit = MAXARCS;
- }
- p->tossize = p->tolimit * sizeof(struct tostruct);
+ /*
+ * 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.
+ */
+ p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER));
+ p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER));
+ p->textsize = p->highpc - p->lowpc;
+ p->kcountsize = p->textsize / HISTFRACTION;
+ p->fromssize = p->textsize / HASHFRACTION;
+ p->tolimit = p->textsize * ARCDENSITY / 100;
+ if (p->tolimit < MINARCS) {
+ p->tolimit = MINARCS;
+ } else if (p->tolimit > MAXARCS) {
+ p->tolimit = MAXARCS;
+ }
+ p->tossize = p->tolimit * sizeof(struct tostruct);
- extern void *hal_allocate_static_memory(const size_t size);
- cp = hal_allocate_static_memory(p->kcountsize + p->fromssize + p->tossize);
- if (cp == NULL) {
- ERR("monstartup: out of memory\n");
- return;
- }
+ extern void *hal_allocate_static_memory(const size_t size);
+ void *cp = hal_allocate_static_memory(p->kcountsize + p->fromssize + p->tossize);
+ if (cp == NULL) {
+ ERR("monstartup: out of memory\n");
+ return;
+ }
- /* zero out cp as value will be added there */
- bzero(cp, p->kcountsize + p->fromssize + p->tossize);
+ bzero(cp, p->kcountsize + p->fromssize + p->tossize);
+ p->kcount = (unsigned short *)cp; cp += p->kcountsize;
+ p->froms = (unsigned short *)cp; cp += p->fromssize;
+ p->tos = (struct tostruct *)cp;
- p->tos = (struct tostruct *)cp;
- cp += p->tossize;
- p->kcount = (unsigned short *)cp;
- cp += p->kcountsize;
- p->froms = (unsigned short *)cp;
+ p->state = on;
+}
- p->tos[0].link = 0;
+void _mcleanup(void)
+{
+ static const char gmon_out[] = "gmon.out";
+ int fd;
+ struct gmonparam *p = &_gmonparam;
- o = p->highpc - p->lowpc;
- if (p->kcountsize < o) {
-#ifndef notdef
- s_scale = ((float)p->kcountsize / o ) * SCALE_1_TO_1;
-#else /* avoid floating point */
- int quot = o / p->kcountsize;
+ if (p->state == err) {
+ ERR("_mcleanup: tos overflow\n");
+ }
- if (quot >= 0x10000)
- s_scale = 1;
- else if (quot >= 0x100)
- s_scale = 0x10000 / quot;
- else if (o >= 0x800000)
- s_scale = 0x1000000 / (o / (p->kcountsize >> 8));
- else
- s_scale = 0x1000000 / ((o << 8) / p->kcountsize);
-#endif
- } else {
- s_scale = SCALE_1_TO_1;
- }
- moncontrol(1); /* start */
-}
+ fd = open(gmon_out , O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0666);
+ if (fd < 0) {
+ perror( gmon_out );
+ return;
+ }
-void _mcleanup(void) {
- static const char gmon_out[] = "gmon.out";
- int fd;
- int fromindex;
- int endfrom;
- size_t frompc;
- int toindex;
- struct rawarc rawarc;
- struct gmonparam *p = &_gmonparam;
- struct gmonhdr gmonhdr = {0}, *hdr;
- const char *proffile;
-#ifdef DEBUG
- int log, len;
- char dbuf[200];
-#endif
+ struct gmonhdr hdr = {
+ .lpc = p->lowpc,
+ .hpc = p->highpc,
+ .ncnt = p->kcountsize + sizeof(struct gmonhdr),
+ .version = GMONVERSION,
+ .profrate = PROF_HZ
+ };
+ write(fd, &hdr, sizeof(hdr));
- if (p->state == GMON_PROF_ERROR) {
- ERR("_mcleanup: tos overflow\n");
- }
- moncontrol(0); /* stop */
- proffile = gmon_out;
- fd = open(proffile , O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0666);
- if (fd < 0) {
- perror( proffile );
- return;
- }
-#ifdef DEBUG
- log = open("gmon.log", O_CREAT|O_TRUNC|O_WRONLY, 0664);
- if (log < 0) {
- perror("mcount: gmon.log");
- return;
- }
- len = sprintf(dbuf, "[mcleanup1] kcount 0x%x ssiz %d\n",
- (unsigned int)p->kcount, p->kcountsize);
- write(log, dbuf, len);
-#endif
- hdr = (struct gmonhdr *)&gmonhdr;
- hdr->lpc = p->lowpc;
- hdr->hpc = p->highpc;
- hdr->ncnt = p->kcountsize + sizeof(gmonhdr);
- hdr->version = GMONVERSION;
- hdr->profrate = PROF_HZ;
- hdr->spare[0] = hdr->spare[1] = hdr->spare[2] = 0;
- write(fd, (char *)hdr, sizeof *hdr);
- write(fd, p->kcount, p->kcountsize);
- endfrom = p->fromssize / sizeof(*p->froms);
- for (fromindex = 0; fromindex < endfrom; fromindex++) {
- if (p->froms[fromindex] == 0) {
- continue;
- }
- frompc = p->lowpc;
- frompc += fromindex * HASHFRACTION * sizeof(*p->froms);
- for (toindex = p->froms[fromindex]; toindex != 0; toindex = p->tos[toindex].link) {
-#ifdef DEBUG
- len = sprintf(dbuf,
- "[mcleanup2] frompc 0x%x selfpc 0x%x count %ld\n" ,
- frompc, p->tos[toindex].selfpc,
- p->tos[toindex].count);
- write(log, dbuf, len);
-#endif
- rawarc.raw_frompc = frompc;
- rawarc.raw_selfpc = p->tos[toindex].selfpc;
- rawarc.raw_count = p->tos[toindex].count;
- write(fd, &rawarc, sizeof rawarc);
- }
- }
- close(fd);
-}
+ write(fd, p->kcount, p->kcountsize);
-/*
- * Control profiling
- * profiling is what mcount checks to see if
- * all the data structures are ready.
- */
-static void moncontrol(int mode) {
- struct gmonparam *p = &_gmonparam;
+ for (size_t fromindex = 0; fromindex < p->fromssize / sizeof(*p->froms); fromindex++) {
+ size_t frompc = p->lowpc + fromindex * HASHFRACTION * sizeof(*p->froms);
+ for (size_t toindex = p->froms[fromindex]; toindex != 0; toindex = p->tos[toindex].next) {
+ struct rawarc arc = {
+ .frompc = frompc,
+ .selfpc = p->tos[toindex].selfpc,
+ .count = p->tos[toindex].count
+ };
+ write(fd, &arc, sizeof(arc));
+ }
+ }
- if (mode) {
- /* start */
- profil((char *)p->kcount, p->kcountsize, p->lowpc, s_scale);
- p->state = GMON_PROF_ON;
- } else {
- /* stop */
- profil((char *)0, 0, 0, 0);
- p->state = GMON_PROF_OFF;
- }
+ close(fd);
}
-void _mcount_internal(uint32_t *frompcindex, uint32_t *selfpc) {
- register struct tostruct *top;
- register struct tostruct *prevtop;
- register long toindex;
+void _mcount_internal(size_t frompc, size_t selfpc)
+{
+ register unsigned short *fromptr;
+ register struct tostruct *top;
+ register unsigned short toindex;
struct gmonparam *p = &_gmonparam;
/*
- * check that we are profiling
- * and that we aren't recursively invoked.
- */
- if (p->state!=GMON_PROF_ON) {
- goto out;
- }
- p->state++;
- /*
- * check that frompcindex is a reasonable pc value.
- * for example: signal catchers get called from the stack,
- * not from text space. too bad.
+ * check that we are profiling and that we aren't recursively invoked.
+ * check that frompc is a reasonable pc value.
*/
- frompcindex = (uint32_t*)((long)frompcindex - (long)p->lowpc);
- if ((unsigned long)frompcindex > p->textsize) {
- goto done;
+ if (p->state != on || (frompc -= p->lowpc) > p->textsize) {
+ return;
}
- frompcindex = (uint32_t*)&p->froms[((long)frompcindex) / (HASHFRACTION * sizeof(*p->froms))];
- toindex = *((unsigned short*)frompcindex); /* get froms[] value */
- if (toindex == 0) {
- /*
- * first time traversing this arc
- */
- toindex = ++p->tos[0].link; /* the link of tos[0] points to the last used record in the array */
+
+ fromptr = &p->froms[frompc / (HASHFRACTION * sizeof(*p->froms))];
+ toindex = *fromptr; /* get froms[] value */
+
+ if (toindex == 0) { /* we haven't seen this caller before */
+ toindex = ++p->tos[0].next; /* index of the last used record in the array */
if (toindex >= p->tolimit) { /* more tos[] entries than we can handle! */
- goto overflow;
- }
- *((unsigned short*)frompcindex) = (unsigned short)toindex; /* store new 'to' value into froms[] */
+ overflow:
+ p->state = err; /* halt further profiling */
+#define TOLIMIT "mcount: tos overflow\n"
+ write (2, TOLIMIT, sizeof(TOLIMIT));
+ return;
+ }
+ *fromptr = toindex; /* store new 'to' value into froms[] */
top = &p->tos[toindex];
- top->selfpc = (size_t)selfpc;
+ top->selfpc = selfpc;
top->count = 1;
- top->link = 0;
- goto done;
- }
- top = &p->tos[toindex];
- if (top->selfpc == (size_t)selfpc) {
- /*
- * arc at front of chain; usual case.
- */
- top->count++;
- goto done;
+ top->next = 0;
}
- /*
- * 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) {
+
+ else { /* we've seen this caller before */
+ top = &p->tos[toindex];
+ if (top->selfpc == selfpc) {
/*
- * 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.
+ * arc at front of chain; usual case.
*/
- toindex = ++p->tos[0].link;
- if (toindex >= p->tolimit) {
- goto overflow;
- }
- top = &p->tos[toindex];
- top->selfpc = (size_t)selfpc;
- top->count = 1;
- top->link = *((unsigned short*)frompcindex);
- *(unsigned short*)frompcindex = (unsigned short)toindex;
- goto done;
+ top->count++;
}
- /*
- * otherwise, check the next arc on the chain.
- */
- prevtop = top;
- top = &p->tos[top->link];
- if (top->selfpc == (size_t)selfpc) {
+
+ else {
/*
- * there it is.
- * increment its count
- * move it to the head of the chain.
+ * 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.
*/
- top->count++;
- toindex = prevtop->link;
- prevtop->link = top->link;
- top->link = *((unsigned short*)frompcindex);
- *((unsigned short*)frompcindex) = (unsigned short)toindex;
- goto done;
+ while (1) {
+ if (top->next == 0) {
+ /*
+ * top is end of the chain and none of the chain
+ * had top->selfpc == selfpc.
+ * so we allocate a new tostruct
+ * and put it at the head of the chain.
+ */
+ toindex = ++p->tos[0].next;
+ if (toindex >= p->tolimit) {
+ goto overflow;
+ }
+ top = &p->tos[toindex];
+ top->selfpc = selfpc;
+ top->count = 1;
+ top->next = *fromptr;
+ *fromptr = toindex;
+ break;
+ }
+
+ else {
+ /*
+ * otherwise, check the next arc on the chain.
+ */
+ register struct tostruct *prevtop = top;
+ top = &p->tos[top->next];
+ if (top->selfpc == selfpc) {
+ /*
+ * there it is.
+ * increment its count
+ * move it to the head of the chain.
+ */
+ top->count++;
+ toindex = prevtop->next;
+ prevtop->next = top->next;
+ top->next = *fromptr;
+ *fromptr = toindex;
+ break;
+ }
+ }
+ }
}
}
- done:
- p->state--;
- /* and fall through */
- out:
- return; /* normal return restores saved registers */
- overflow:
- p->state++; /* halt further profiling */
- #define TOLIMIT "mcount: tos overflow\n"
- write (2, TOLIMIT, sizeof(TOLIMIT));
- goto out;
+
+ return; /* normal return restores saved registers */
}
-void _monInit(void) {
- _gmonparam.state = GMON_PROF_OFF;
- already_setup = 0;
+#include <stdint.h>
+#include "stm32f4xx_hal.h" /* __get_MSP */
+
+/* called from the SysTick handler */
+void profil_callback(void)
+{
+ struct gmonparam *p = &_gmonparam;
+
+ if (p->state == on) {
+ /* The interrupt mechanism pushes xPSR, PC, LR, R12, and R3-R0 onto the
+ * stack, so PC is the 6th word from the top at that point. However, the
+ * normal function entry code pushes registers as well, so the stack
+ * offset right now depends on the call tree that got us here.
+ */
+ size_t pc = (size_t)((uint32_t *)__get_MSP())[6 + 6];
+ if ((pc -= p->lowpc) < p->textsize) {
+ size_t idx = pc / (HISTFRACTION * sizeof(*p->kcount));
+ p->kcount[idx]++;
+ }
+ }
}
diff --git a/libraries/libprof/gmon.h b/libraries/libprof/gmon.h
index 8b5ecf0..9016502 100644
--- a/libraries/libprof/gmon.h
+++ b/libraries/libprof/gmon.h
@@ -40,28 +40,6 @@
#ifndef _SYS_GMON_H_
#define _SYS_GMON_H_
-#ifndef __P
-#define __P(x) x
-#endif
-
-/* On POSIX systems, profile.h is a KRB5 header. To avoid collisions, just
- pull in profile.h's content here. The profile.h header won't be provided
- by Mingw-w64 anymore at one point. */
-#if 0
-#include <profile.h>
-#else
-#ifndef _WIN64
-#define _MCOUNT_CALL __attribute__ ((regparm (2)))
-extern void _mcount(void);
-#else
-#define _MCOUNT_CALL
-extern void mcount(void);
-#endif
-#define _MCOUNT_DECL __attribute__((gnu_inline)) __inline__ \
- void _MCOUNT_CALL _mcount_private
-#define MCOUNT
-#endif
-
/*
* Structure prepended to gmon.out profiling data file.
*/
@@ -83,7 +61,8 @@ struct gmonhdr {
/*
* fraction of text space to allocate for histogram counters here, 1/2
*/
-#define HISTFRACTION 2
+//#define HISTFRACTION 2
+#define HISTFRACTION 1
/*
* Fraction of text space to allocate for from hash buckets.
@@ -113,7 +92,8 @@ struct gmonhdr {
* profiling data structures without (in practice) sacrificing
* any granularity.
*/
-#define HASHFRACTION 2
+//#define HASHFRACTION 2
+#define HASHFRACTION 1
/*
* percent of text space to allocate for tostructs with a minimum.
@@ -123,10 +103,10 @@ struct gmonhdr {
#define MAXARCS ((1 << (8 * sizeof(HISTCOUNTER))) - 2)
struct tostruct {
- size_t selfpc; /* callee address/program counter. The caller address is in froms[] array which points to tos[] array */
- long count; /* how many times it has been called */
- unsigned short link; /* link to next entry in hash table. For tos[0] this points to the last used entry */
- unsigned short pad; /* additional padding bytes, to have entries 4byte aligned */
+ size_t selfpc; /* callee address. The caller address is in froms[] array which points to tos[] array */
+ unsigned long count; /* how many times it has been called */
+ unsigned short next; /* next entry in hash table. For tos[0] this is the index of the last used entry */
+ unsigned short pad; /* additional padding bytes, to have entries 4byte aligned */
};
/*
@@ -134,9 +114,9 @@ struct tostruct {
* the called site and a count.
*/
struct rawarc {
- size_t raw_frompc;
- size_t raw_selfpc;
- long raw_count;
+ size_t frompc;
+ size_t selfpc;
+ long count;
};
/*
@@ -149,29 +129,20 @@ struct rawarc {
* The profiling data structures are housed in this structure.
*/
struct gmonparam {
- int state;
+ enum { off, on, err } state;
unsigned short *kcount; /* histogram PC sample array */
size_t kcountsize; /* size of kcount[] array in bytes */
unsigned short *froms; /* array of hashed 'from' addresses. The 16bit value is an index into the tos[] array */
size_t fromssize; /* size of froms[] array in bytes */
- struct tostruct *tos; /* to struct, contains histogram counter */
+ struct tostruct *tos; /* to struct, contains arc counters */
size_t tossize; /* size of tos[] array in bytes */
- long tolimit;
+ size_t tolimit;
size_t lowpc; /* low program counter of area */
size_t highpc; /* high program counter */
size_t textsize; /* code size */
};
extern struct gmonparam _gmonparam;
-/*
- * Possible states of profiling.
- */
-#define GMON_PROF_ON 0
-#define GMON_PROF_BUSY 1
-#define GMON_PROF_ERROR 2
-#define GMON_PROF_OFF 3
-
void _mcleanup(void); /* routine to be called to write gmon.out file */
-void _monInit(void); /* initialization routine */
#endif /* !_SYS_GMONH_ */
diff --git a/libraries/libprof/profil.c b/libraries/libprof/profil.c
deleted file mode 100644
index b0d8d55..0000000
--- a/libraries/libprof/profil.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* profil.c -- win32 profil.c equivalent
-
- Copyright 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
-
- This file is part of Cygwin.
-
- This software is a copyrighted work licensed under the terms of the
- Cygwin license. Please consult the file "CYGWIN_LICENSE" for
- details. */
-
-/*
- * This file is taken from Cygwin distribution, adapted to be used for bare embedded targets.
- */
-#include <stdio.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <math.h>
-#include "profil.h"
-#include <string.h>
-
-#include "stm32f4xx_hal.h" /* __get_MSP */
-
-/* global profinfo for profil() call */
-static struct profinfo prof = {
- PROFILE_NOT_INIT, 0, 0, 0, 0
-};
-
-/* sample the current program counter */
-void profil_callback(void) {
- if (prof.state == PROFILE_ON) {
- /* The interrupt mechanism pushes xPSR, PC, LR, R12, and R3-R0 onto the
- * stack, so PC is the 6th word from the top at that point. However, the
- * normal function entry code pushes registers as well, so the stack
- * offset right now depends on the call tree that got us here.
- */
- size_t pc = (size_t)((uint32_t *)__get_MSP())[6 + 6];
- if (pc >= prof.lowpc && pc < prof.highpc) {
- size_t idx = PROFIDX (pc, prof.lowpc, prof.scale);
- prof.counter[idx]++;
- }
- }
-}
-
-/* Stop profiling to the profiling buffer pointed to by p. */
-static int profile_off (struct profinfo *p) {
- p->state = PROFILE_OFF;
- return 0;
-}
-
-/* Create a timer thread and pass it a pointer P to the profiling buffer. */
-static int profile_on (struct profinfo *p) {
- p->state = PROFILE_ON;
- return 0; /* ok */
-}
-
-/*
- * start or stop profiling
- *
- * profiling goes into the SAMPLES buffer of size SIZE (which is treated
- * as an array of unsigned shorts of size size/2)
- *
- * each bin represents a range of pc addresses from OFFSET. The number
- * of pc addresses in a bin depends on SCALE. (A scale of 65536 maps
- * each bin to two addresses, A scale of 32768 maps each bin to 4 addresses,
- * a scale of 1 maps each bin to 128k address). Scale may be 1 - 65536,
- * or zero to turn off profiling
- */
-int profile_ctl (struct profinfo *p, char *samples, size_t size, size_t offset, unsigned int scale) {
- size_t maxbin;
-
- if (scale > 65536) {
- errno = EINVAL;
- return -1;
- }
- profile_off(p);
- if (scale) {
- memset(samples, 0, size);
- memset(p, 0, sizeof *p);
- maxbin = size >> 1;
- prof.counter = (unsigned short*)samples;
- prof.lowpc = offset;
- prof.highpc = PROFADDR(maxbin, offset, scale);
- prof.scale = scale;
- return profile_on(p);
- }
- return 0;
-}
-
-/* Equivalent to unix profil()
- Every SLEEPTIME interval, the user's program counter (PC) is examined:
- offset is subtracted and the result is multiplied by scale.
- The word pointed to by this address is incremented. */
-int profil (char *samples, size_t size, size_t offset, unsigned int scale) {
- return profile_ctl (&prof, samples, size, offset, scale);
-}
-
diff --git a/libraries/libprof/profil.h b/libraries/libprof/profil.h
deleted file mode 100644
index c72dc00..0000000
--- a/libraries/libprof/profil.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* profil.h: gprof profiling header file
-
- Copyright 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
-
-This file is part of Cygwin.
-
-This software is a copyrighted work licensed under the terms of the
-Cygwin license. Please consult the file "CYGWIN_LICENSE" for
-details. */
-
-/*
- * This file is taken from Cygwin distribution. Please keep it in sync.
- * The differences should be within __MINGW32__ guard.
- */
-
-#ifndef __PROFIL_H__
-#define __PROFIL_H__
-
-/* profiling frequency. (No larger than 1000) */
-#define PROF_HZ 1000
-
-/* convert an addr to an index */
-#define PROFIDX(pc, base, scale) \
- ({ \
- size_t i = (pc - base) / 2; \
- if (sizeof (unsigned long long int) > sizeof (size_t)) \
- i = (unsigned long long int) i * scale / 65536; \
- else \
- i = i / 65536 * scale + i % 65536 * scale / 65536; \
- i; \
- })
-
-/* convert an index into an address */
-#define PROFADDR(idx, base, scale) \
- ((base) \
- + ((((unsigned long long)(idx) << 16) \
- / (unsigned long long)(scale)) << 1))
-
-/* convert a bin size into a scale */
-#define PROFSCALE(range, bins) (((bins) << 16) / ((range) >> 1))
-
-typedef void *_WINHANDLE;
-
-typedef enum {
- PROFILE_NOT_INIT = 0,
- PROFILE_ON,
- PROFILE_OFF
-} PROFILE_State;
-
-struct profinfo {
- PROFILE_State state; /* profiling state */
- unsigned short *counter; /* profiling counters */
- size_t lowpc, highpc; /* range to be profiled */
- unsigned int scale; /* scale value of bins */
-};
-
-int profile_ctl(struct profinfo *, char *, size_t, size_t, unsigned int);
-int profil(char *, size_t, size_t, unsigned int);
-
-#endif /* __PROFIL_H__ */