4.3BSD-Reno/src/lib/csu.tahoe/mon.c
static char *sccsid = "@(#)mon.c 2.0 (Tahoe) 5/7/84";
#define ARCDENSITY 5 /* density of routines */
#define MINARCS 50 /* minimum number of counters */
#define HISTFRACTION 2 /* fraction of text space for histograms */
struct phdr {
char *lpc;
char *hpc;
int ncnt;
};
struct cnt {
char *pc;
long ncall;
} *countbase;
static int cntrs = 0;
static int profiling = 3;
static char *s_sbuf;
static int s_bufsiz;
static int s_scale;
static char *s_lowpc;
int numctrs;
#define MSG "No space for monitor buffer(s)\n"
monstartup(lowpc, highpc)
char *lowpc;
char *highpc;
{
int monsize;
char *buffer;
int cntsiz;
extern char *sbrk();
extern char *minbrk;
cntsiz = (highpc - lowpc) * ARCDENSITY / 100;
if (cntsiz < MINARCS)
cntsiz = MINARCS;
monsize = (highpc - lowpc + HISTFRACTION - 1) / HISTFRACTION
+ sizeof(struct phdr) + cntsiz * sizeof(struct cnt);
monsize = (monsize + 1) & ~1;
buffer = sbrk(monsize);
if (buffer == (char *)-1) {
write(2, MSG, sizeof(MSG));
return;
}
minbrk = sbrk(0);
monitor(lowpc, highpc, buffer, monsize, cntsiz);
}
mcount(cntpa)
long **cntpa;
{
register long **cntp;
register char *selfpc;
/*
* find the return address for mcount,
* and address of counter pointer
*/
selfpc = *((char **)&cntpa-3); /* -8(fp) */
cntp = cntpa;
/*
* check that we aren't recursively invoked.
*/
if (profiling)
goto out;
profiling++;
/*
* check that counter is allocated
*/
if (*cntp == 0) {
/*
* check that a counter is available
*/
if (cntrs++ == numctrs)
goto overflow;
countbase->pc = selfpc;
*cntp = &countbase->ncall;
countbase++;
}
(**cntp)++;
profiling--;
out:
return;
overflow:
# define TOLIMIT "mcount: counter overflow\n"
write( 2 , TOLIMIT , sizeof( TOLIMIT ) );
goto out;
}
monitor(lowpc, highpc, buf, bufsiz, cntsiz)
char *lowpc, *highpc;
char *buf;
int bufsiz, cntsiz;
{
register int o;
struct phdr *php;
static int ssiz;
static char *sbuf;
if (lowpc == 0) {
moncontrol(0);
o = creat("mon.out", 0666);
write(o, sbuf, ssiz);
close(o);
return;
}
sbuf = buf;
ssiz = bufsiz;
php = (struct phdr *)&buf[0];
php->lpc = lowpc;
php->hpc = highpc;
php->ncnt = cntsiz;
numctrs = cntsiz;
countbase = (struct cnt *)(buf + sizeof(struct phdr));
o = sizeof(struct phdr) + cntsiz * sizeof(struct cnt);
buf += o;
bufsiz -= o;
if (bufsiz <= 0)
return;
o = (highpc - lowpc);
if(bufsiz < o)
o = ((float) bufsiz / o) * 65536;
else
o = 65536;
s_scale = o;
s_sbuf = buf;
s_bufsiz = bufsiz;
s_lowpc = lowpc;
moncontrol(1);
}
/*
* Control profiling
* profiling is what mcount checks to see if
* all the data structures are ready.
*/
moncontrol(mode)
int mode;
{
if (mode) {
/* start */
profil(s_sbuf, s_bufsiz, s_lowpc, s_scale);
profiling = 0;
} else {
/* stop */
profil((char *)0, 0, 0, 0);
profiling = 3;
}
}