summaryrefslogtreecommitdiffstats
path: root/lib/libc/gmon
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/gmon')
-rw-r--r--lib/libc/gmon/Makefile.inc3
-rw-r--r--lib/libc/gmon/gmon.c8
-rw-r--r--lib/libc/gmon/mcount.c169
-rw-r--r--lib/libc/gmon/moncontrol.33
4 files changed, 168 insertions, 15 deletions
diff --git a/lib/libc/gmon/Makefile.inc b/lib/libc/gmon/Makefile.inc
index 959c3fb..57dc293 100644
--- a/lib/libc/gmon/Makefile.inc
+++ b/lib/libc/gmon/Makefile.inc
@@ -4,7 +4,8 @@
.PATH: ${.CURDIR}/gmon
SRCS+= gmon.c mcount.c
-MAN3+= moncontrol.0
+MAN3+= gmon/moncontrol.3
+MLINKS+= moncontrol.3 monstartup.3
# mcount cannot be compiled with profiling
mcount.po: mcount.o
diff --git a/lib/libc/gmon/gmon.c b/lib/libc/gmon/gmon.c
index 022ffb5..81e36dd 100644
--- a/lib/libc/gmon/gmon.c
+++ b/lib/libc/gmon/gmon.c
@@ -44,7 +44,11 @@ static char sccsid[] = "@(#)gmon.c 8.1 (Berkeley) 6/4/93";
#include <fcntl.h>
#include <unistd.h>
+#if defined(__ELF__)
+extern char *minbrk asm (".minbrk");
+#else
extern char *minbrk asm ("minbrk");
+#endif
struct gmonparam _gmonparam = { GMON_PROF_OFF };
@@ -106,7 +110,7 @@ monstartup(lowpc, highpc)
s_scale = ((float)p->kcountsize / o ) * SCALE_1_TO_1;
#else /* avoid floating point */
int quot = o / p->kcountsize;
-
+
if (quot >= 0x10000)
s_scale = 1;
else if (quot >= 0x100)
@@ -239,7 +243,7 @@ static int
hertz()
{
struct itimerval tim;
-
+
tim.it_interval.tv_sec = 0;
tim.it_interval.tv_usec = 1;
tim.it_value.tv_sec = 0;
diff --git a/lib/libc/gmon/mcount.c b/lib/libc/gmon/mcount.c
index 523217d..a48e558 100644
--- a/lib/libc/gmon/mcount.c
+++ b/lib/libc/gmon/mcount.c
@@ -32,11 +32,25 @@
*/
#if !defined(lint) && !defined(KERNEL) && defined(LIBC_SCCS)
+#if 0
static char sccsid[] = "@(#)mcount.c 8.1 (Berkeley) 6/4/93";
#endif
+static const char rcsid[] =
+ "$Id$";
+#endif
#include <sys/param.h>
#include <sys/gmon.h>
+#ifdef KERNEL
+#include <sys/systm.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+void bintr __P((void));
+void btrap __P((void));
+void eintr __P((void));
+void user __P((void));
+#endif
/*
* mcount is called on entry to each function compiled with the profiling
@@ -48,44 +62,132 @@ static char sccsid[] = "@(#)mcount.c 8.1 (Berkeley) 6/4/93";
* _mcount updates data structures that represent traversals of the
* program's call graph edges. frompc and selfpc are the return
* address and function address that represents the given call graph edge.
- *
+ *
* Note: the original BSD code used the same variable (frompcindex) for
* both frompcindex and frompc. Any reasonable, modern compiler will
* perform this optimization.
*/
_MCOUNT_DECL(frompc, selfpc) /* _mcount; may be static, inline, etc */
- register u_long frompc, selfpc;
+ register fptrint_t frompc, selfpc;
{
+#ifdef GUPROF
+ u_int delta;
+#endif
+ register fptrdiff_t frompci;
register u_short *frompcindex;
register struct tostruct *top, *prevtop;
register struct gmonparam *p;
register long toindex;
#ifdef KERNEL
- register int s;
+ MCOUNT_DECL(s)
#endif
p = &_gmonparam;
+#ifndef GUPROF /* XXX */
/*
* check that we are profiling
* and that we aren't recursively invoked.
*/
if (p->state != GMON_PROF_ON)
return;
+#endif
#ifdef KERNEL
- MCOUNT_ENTER;
+ MCOUNT_ENTER(s);
#else
p->state = GMON_PROF_BUSY;
#endif
+ frompci = frompc - p->lowpc;
+
+#ifdef KERNEL
+ /*
+ * When we are called from an exception handler, frompci may be
+ * for a user address. Convert such frompci's to the index of
+ * user() to merge all user counts.
+ */
+ if (frompci >= p->textsize) {
+ if (frompci + p->lowpc
+ >= (fptrint_t)(VM_MAXUSER_ADDRESS + UPAGES * PAGE_SIZE))
+ goto done;
+ frompci = (fptrint_t)user - p->lowpc;
+ if (frompci >= p->textsize)
+ goto done;
+ }
+#endif /* KERNEL */
+
+#ifdef GUPROF
+ if (p->state != GMON_PROF_HIRES)
+ goto skip_guprof_stuff;
/*
- * check that frompcindex is a reasonable pc value.
+ * Look at the clock and add the count of clock cycles since the
+ * clock was last looked at to a counter for frompc. This
+ * solidifies the count for the function containing frompc and
+ * effectively starts another clock for the current function.
+ * The count for the new clock will be solidified when another
+ * function call is made or the function returns.
+ *
+ * We use the usual sampling counters since they can be located
+ * efficiently. 4-byte counters are usually necessary.
+ *
+ * There are many complications for subtracting the profiling
+ * overheads from the counts for normal functions and adding
+ * them to the counts for mcount(), mexitcount() and cputime().
+ * We attempt to handle fractional cycles, but the overheads
+ * are usually underestimated because they are calibrated for
+ * a simpler than usual setup.
+ */
+ delta = cputime() - p->mcount_overhead;
+ p->cputime_overhead_resid += p->cputime_overhead_frac;
+ p->mcount_overhead_resid += p->mcount_overhead_frac;
+ if ((int)delta < 0)
+ *p->mcount_count += delta + p->mcount_overhead
+ - p->cputime_overhead;
+ else if (delta != 0) {
+ if (p->cputime_overhead_resid >= CALIB_SCALE) {
+ p->cputime_overhead_resid -= CALIB_SCALE;
+ ++*p->cputime_count;
+ --delta;
+ }
+ if (delta != 0) {
+ if (p->mcount_overhead_resid >= CALIB_SCALE) {
+ p->mcount_overhead_resid -= CALIB_SCALE;
+ ++*p->mcount_count;
+ --delta;
+ }
+ KCOUNT(p, frompci) += delta;
+ }
+ *p->mcount_count += p->mcount_overhead_sub;
+ }
+ *p->cputime_count += p->cputime_overhead;
+skip_guprof_stuff:
+#endif /* GUPROF */
+
+#ifdef KERNEL
+ /*
+ * When we are called from an exception handler, frompc is faked
+ * to be for where the exception occurred. We've just solidified
+ * the count for there. Now convert frompci to the index of btrap()
+ * for trap handlers and bintr() for interrupt handlers to make
+ * exceptions appear in the call graph as calls from btrap() and
+ * bintr() instead of calls from all over.
+ */
+ if ((fptrint_t)selfpc >= (fptrint_t)btrap
+ && (fptrint_t)selfpc < (fptrint_t)eintr) {
+ if ((fptrint_t)selfpc >= (fptrint_t)bintr)
+ frompci = (fptrint_t)bintr - p->lowpc;
+ else
+ frompci = (fptrint_t)btrap - p->lowpc;
+ }
+#endif /* KERNEL */
+
+ /*
+ * check that frompc is a reasonable pc value.
* for example: signal catchers get called from the stack,
* not from text space. too bad.
*/
- frompc -= p->lowpc;
- if (frompc > p->textsize)
+ if (frompci >= p->textsize)
goto done;
- frompcindex = &p->froms[frompc / (p->hashfraction * sizeof(*p->froms))];
+ frompcindex = &p->froms[frompci / (p->hashfraction * sizeof(*p->froms))];
toindex = *frompcindex;
if (toindex == 0) {
/*
@@ -154,11 +256,11 @@ _MCOUNT_DECL(frompc, selfpc) /* _mcount; may be static, inline, etc */
*frompcindex = toindex;
goto done;
}
-
+
}
done:
#ifdef KERNEL
- MCOUNT_EXIT;
+ MCOUNT_EXIT(s);
#else
p->state = GMON_PROF_ON;
#endif
@@ -166,7 +268,7 @@ done:
overflow:
p->state = GMON_PROF_ERROR;
#ifdef KERNEL
- MCOUNT_EXIT;
+ MCOUNT_EXIT(s);
#endif
return;
}
@@ -176,3 +278,48 @@ overflow:
* which is included by <sys/gmon.h>.
*/
MCOUNT
+
+#ifdef GUPROF
+void
+mexitcount(selfpc)
+ fptrint_t selfpc;
+{
+ struct gmonparam *p;
+ fptrint_t selfpcdiff;
+
+ p = &_gmonparam;
+ selfpcdiff = selfpc - (fptrint_t)p->lowpc;
+ if (selfpcdiff < p->textsize) {
+ u_int delta;
+
+ /*
+ * Solidify the count for the current function.
+ */
+ delta = cputime() - p->mexitcount_overhead;
+ p->cputime_overhead_resid += p->cputime_overhead_frac;
+ p->mexitcount_overhead_resid += p->mexitcount_overhead_frac;
+ if ((int)delta < 0)
+ *p->mexitcount_count += delta + p->mexitcount_overhead
+ - p->cputime_overhead;
+ else if (delta != 0) {
+ if (p->cputime_overhead_resid >= CALIB_SCALE) {
+ p->cputime_overhead_resid -= CALIB_SCALE;
+ ++*p->cputime_count;
+ --delta;
+ }
+ if (delta != 0) {
+ if (p->mexitcount_overhead_resid
+ >= CALIB_SCALE) {
+ p->mexitcount_overhead_resid
+ -= CALIB_SCALE;
+ ++*p->mexitcount_count;
+ --delta;
+ }
+ KCOUNT(p, selfpcdiff) += delta;
+ }
+ *p->mexitcount_count += p->mexitcount_overhead_sub;
+ }
+ *p->cputime_count += p->cputime_overhead;
+ }
+}
+#endif /* GUPROF */
diff --git a/lib/libc/gmon/moncontrol.3 b/lib/libc/gmon/moncontrol.3
index 9b01f2b..1413bf5 100644
--- a/lib/libc/gmon/moncontrol.3
+++ b/lib/libc/gmon/moncontrol.3
@@ -98,4 +98,5 @@ Profiling begins on return from
.Sh SEE ALSO
.Xr cc 1 ,
.Xr gprof 1 ,
-.Xr profil 2
+.Xr profil 2 ,
+.Xr clocks 7
OpenPOWER on IntegriCloud