(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)