Add kmupetext(), a function that expands the range of memory covered

by the profiler on a running system.  This is not done sparsely, as
memory is cheaper than processor speed and each gprof mcount() and
mexitcount() operation is already very expensive.

Obtained from:	NAI Labs CBOSS project
Funded by:	DARPA
This commit is contained in:
Brian Feldman 2001-10-30 15:04:57 +00:00
parent 35609d458d
commit 4a44bd4b4a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=85733
3 changed files with 66 additions and 5 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;