(update of http://marc.theaimsgroup.com/?l=openbsd-misc&m=115898040215357&w=2)
Here's an improved version of the patch. It does away with
kmstartup(), completing the coverage of the recorded call graph.
--- /dev/null Sun Sep 24 23:24:37 2006
+++ sys/conf/gen_addr_etext Sat Sep 23 00:36:45 2006
@@ -0,0 +1,19 @@
+#!/bin/sh
+f=addr_etext.h
+l='#define ADDR_ETEXT 0x\'
+if [ $# = 0 ]; then
+ echo "$l" > $f
+ echo '0 + KERNBASE + (1<<16)' >> $f
+ exit 0
+fi
+if [ $# = 1 ]; then
+ a=$(objdump -t "$1" | awk '/ etext$/{print $1}')
+ [ -z "$a" ] && exit 2
+ b=$(sed -n 2p < $f)
+ [ -z "$b" ] && exit 2
+ [ x"$a" = x"$b" ] && exit 1
+ echo "$l" > $f
+ echo "$a" >> $f
+ exit 0
+fi
+exit 2
Index: sys/kern/init_main.c
===================================================================
RCS file: /cvs/src/sys/kern/init_main.c,v
retrieving revision 1.130
diff -u -r1.130 init_main.c
--- sys/kern/init_main.c 6 May 2006 23:02:36 -0000 1.130
+++ sys/kern/init_main.c 24 Sep 2006 23:24:42 -0000
@@ -347,6 +347,9 @@
/* Start real time and statistics clocks. */
initclocks();
+#ifdef GPROF
+ startprofclock(&proc0);
+#endif
/* Lock the kernel on behalf of proc0. */
KERNEL_PROC_LOCK(p);
@@ -385,11 +388,6 @@
domaininit();
if_attachdomain();
splx(s);
-
-#ifdef GPROF
- /* Initialize kernel profiling. */
- kmstartup();
-#endif
#if !defined(NO_PROPOLICE)
{
Index: sys/kern/subr_prof.c
===================================================================
RCS file: /cvs/src/sys/kern/subr_prof.c,v
retrieving revision 1.15
diff -u -r1.15 subr_prof.c
--- sys/kern/subr_prof.c 9 Dec 2005 09:09:52 -0000 1.15
+++ sys/kern/subr_prof.c 24 Sep 2006 23:24:42 -0000
@@ -45,53 +45,40 @@
#ifdef GPROF
#include <sys/malloc.h>
#include <sys/gmon.h>
-#include <uvm/uvm_extern.h>
+#include "addr_etext.h"
/*
- * Froms is actually a bunch of unsigned shorts indexing tos
+ * 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.
*/
-struct gmonparam _gmonparam = { GMON_PROF_OFF };
-
-extern char etext[];
-
+#define LOWPC ROUNDDOWN(KERNBASE, HISTFRACTION * sizeof(HISTCOUNTER))
+#define HIGHPC ROUNDUP((ADDR_ETEXT), HISTFRACTION * sizeof(HISTCOUNTER))
+#define TEXTSIZE (HIGHPC - LOWPC)
+#define KCOUNTSIZE (TEXTSIZE / HISTFRACTION)
+#define FROMSSIZE (TEXTSIZE / HASHFRACTION)
+#define TOLIM (TEXTSIZE * ARCDENSITY / 100)
+#define TOLIMIT (TOLIM < MINARCS ? MINARCS : TOLIM > MAXARCS ? MAXARCS : TOLIM)
+#define TOSSIZE (TOLIMIT * sizeof(struct tostruct))
-void
-kmstartup(void)
-{
- char *cp;
- struct gmonparam *p = &_gmonparam;
- int size;
+static char buf[KCOUNTSIZE + FROMSSIZE + TOSSIZE];
- /*
- * 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(KERNBASE, HISTFRACTION * sizeof(HISTCOUNTER));
- p->highpc = ROUNDUP((u_long)etext, HISTFRACTION * sizeof(HISTCOUNTER));
- p->textsize = p->highpc - p->lowpc;
- printf("Profiling kernel, textsize=%ld [%lx..%lx]\n",
- p->textsize, p->lowpc, p->highpc);
- p->kcountsize = p->textsize / HISTFRACTION;
- p->hashfraction = HASHFRACTION;
- 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);
- size = p->kcountsize + p->fromssize + p->tossize;
- cp = (char *)uvm_km_zalloc(kernel_map, round_page(size));
- if (cp == 0) {
- printf("No memory for profiling.\n");
- return;
- }
- p->tos = (struct tostruct *)cp;
- cp += p->tossize;
- p->kcount = (u_short *)cp;
- cp += p->kcountsize;
- p->froms = (u_short *)cp;
-}
+/*
+ * Froms is actually a bunch of unsigned shorts indexing tos
+ */
+struct gmonparam _gmonparam = {
+ /* state = */ GMON_PROF_ON,
+ /* kcount = */ (ushort *)(buf + TOSSIZE),
+ KCOUNTSIZE,
+ /* froms = */ (ushort *)(buf + TOSSIZE + KCOUNTSIZE),
+ FROMSSIZE,
+ /* tos = */ (struct tostruct *)buf,
+ TOSSIZE,
+ TOLIMIT,
+ LOWPC,
+ HIGHPC,
+ TEXTSIZE,
+ HASHFRACTION
+};
/*
* Return kernel profiling information.
Index: usr.sbin/config/mkmakefile.c
===================================================================
RCS file: /cvs/src/usr.sbin/config/mkmakefile.c,v
retrieving revision 1.20
diff -u -r1.20 mkmakefile.c
--- usr.sbin/config/mkmakefile.c 6 May 2006 11:31:46 -0000 1.20
+++ usr.sbin/config/mkmakefile.c 24 Sep 2006 23:24:42 -0000
@@ -42,6 +42,7 @@
*/
#include <sys/param.h>
+#include <sys/wait.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
@@ -167,6 +168,8 @@
#endif
}
+static int option_gprof = 0;
+
static int
emitdefs(FILE *fp)
{
@@ -177,6 +180,8 @@
return (1);
sp = "";
for (nv = options; nv != NULL; nv = nv->nv_next) {
+ if (!strcmp(nv->nv_name, "GPROF"))
+ option_gprof = 1;
if (ht_lookup(defopttab, nv->nv_name) != NULL)
continue;
if (fprintf(fp, "%s-D%s", sp, nv->nv_name) < 0)
@@ -186,6 +191,18 @@
return 1;
sp = " ";
}
+ if (option_gprof) {
+ size_t len = strlen(srcdir) + 30;
+ char *buf = emalloc(len);
+ int s;
+
+ if (strchr(srcdir, '\''))
+ panic("'ouch");
+ snprintf(buf, len, "sh -- '%s/conf/gen_addr_etext'", srcdir);
+ s = system(buf);
+ if (s == -1 || !WIFEXITED(s) || WEXITSTATUS(s))
+ panic("gen_addr_etext");
+ }
if (putc('\n', fp) < 0)
return (1);
if (fprintf(fp, "PARAM=-DMAXUSERS=%d\n", maxusers) < 0)
@@ -444,9 +461,15 @@
if (fprintf(fp, "\n"
"\t${SYSTEM_LD_HEAD}\n"
"\t${SYSTEM_LD} swap%s.o\n"
- "\t${SYSTEM_LD_TAIL}\n"
+ "\t${SYSTEM_LD_TAIL}\n", swname) < 0)
+ return (1);
+ if (option_gprof && fputs(
+ "\tif sh $S/conf/gen_addr_etext $@; then make $@;"
+ " else [ $$? = 1 ]; fi\n", fp) < 0)
+ return (1);
+ if (fprintf(fp,
"\n"
- "swap%s.o: ", swname, swname) < 0)
+ "swap%s.o: ", swname) < 0)
return (1);
if (cf->cf_root != NULL) {
if (fprintf(fp, "swap%s.c\n", nm) < 0)