diff options
| -rw-r--r-- | sys/amd64/include/profile.h | 1 | ||||
| -rw-r--r-- | sys/i386/include/profile.h | 1 | ||||
| -rw-r--r-- | sys/kern/subr_prof.c | 69 |
3 files changed, 66 insertions, 5 deletions
diff --git a/sys/amd64/include/profile.h b/sys/amd64/include/profile.h index 5f511b3b6a16..82ff6030b608 100644 --- a/sys/amd64/include/profile.h +++ b/sys/amd64/include/profile.h @@ -117,6 +117,7 @@ typedef u_int fptrdiff_t; #ifdef _KERNEL void mcount __P((uintfptr_t frompc, uintfptr_t selfpc)); +void kmupetext __P((uintfptr_t nhighpc)); #ifdef GUPROF struct gmonparam; diff --git a/sys/i386/include/profile.h b/sys/i386/include/profile.h index 5f511b3b6a16..82ff6030b608 100644 --- a/sys/i386/include/profile.h +++ b/sys/i386/include/profile.h @@ -117,6 +117,7 @@ typedef u_int fptrdiff_t; #ifdef _KERNEL void mcount __P((uintfptr_t frompc, uintfptr_t selfpc)); +void kmupetext __P((uintfptr_t nhighpc)); #ifdef GUPROF struct gmonparam; diff --git a/sys/kern/subr_prof.c b/sys/kern/subr_prof.c index ae1d5c3c171e..67629d4c0c0b 100644 --- a/sys/kern/subr_prof.c +++ b/sys/kern/subr_prof.c @@ -78,6 +78,69 @@ nullfunc_profiled() } #endif /* GUPROF */ +/* + * Update the histograms to support extending the text region arbitrarily. + * This is done slightly naively (no sparse regions), so will waste slight + * amounts of memory, but will overall work nicely enough to allow profiling + * of KLDs. + */ +void +kmupetext(uintfptr_t nhighpc) +{ + struct gmonparam np; /* slightly large */ + struct gmonparam *p = &_gmonparam; + char *cp; + critical_t savecrit; + + GIANT_REQUIRED; + bcopy(p, &np, sizeof(*p)); + np.highpc = ROUNDUP(nhighpc, HISTFRACTION * sizeof(HISTCOUNTER)); + if (np.highpc <= p->highpc) + return; + np.textsize = np.highpc - p->lowpc; + np.kcountsize = np.textsize / HISTFRACTION; + np.hashfraction = HASHFRACTION; + np.fromssize = np.textsize / HASHFRACTION; + np.tolimit = np.textsize * ARCDENSITY / 100; + if (np.tolimit < MINARCS) + np.tolimit = MINARCS; + else if (np.tolimit > MAXARCS) + np.tolimit = MAXARCS; + np.tossize = np.tolimit * sizeof(struct tostruct); + cp = malloc(np.kcountsize + np.fromssize + np.tossize, + M_GPROF, M_WAITOK); + /* + * Check for something else extending highpc while we slept. + */ + if (np.highpc <= p->highpc) { + free(cp, M_GPROF); + return; + } + np.tos = (struct tostruct *)cp; + cp += np.tossize; + np.kcount = (HISTCOUNTER *)cp; + cp += np.kcountsize; + np.froms = (u_short *)cp; +#ifdef GUPROF + /* Reinitialize pointers to overhead counters. */ + np.cputime_count = &KCOUNT(&np, PC_TO_I(&np, cputime)); + np.mcount_count = &KCOUNT(&np, PC_TO_I(&np, mcount)); + np.mexitcount_count = &KCOUNT(&np, PC_TO_I(&np, mexitcount)); +#endif + savecrit = critical_enter(); + bcopy(p->tos, np.tos, p->tossize); + bzero((char *)np.tos + p->tossize, np.tossize - p->tossize); + bcopy(p->kcount, np.kcount, p->kcountsize); + bzero((char *)np.kcount + p->kcountsize, np.kcountsize - + p->kcountsize); + bcopy(p->froms, np.froms, p->fromssize); + bzero((char *)np.froms + p->fromssize, np.fromssize - p->fromssize); + cp = (char *)p->tos; + bcopy(&np, p, sizeof(*p)); + critical_exit(savecrit); + free(cp, M_GPROF); +} + static void kmstartup(dummy) void *dummy; @@ -115,11 +178,7 @@ kmstartup(dummy) p->tolimit = MAXARCS; p->tossize = p->tolimit * sizeof(struct tostruct); cp = (char *)malloc(p->kcountsize + p->fromssize + p->tossize, - M_GPROF, M_NOWAIT | M_ZERO); - if (cp == 0) { - printf("No memory for profiling.\n"); - return; - } + M_GPROF, M_WAITOK | M_ZERO); p->tos = (struct tostruct *)cp; cp += p->tossize; p->kcount = (HISTCOUNTER *)cp; |
