xref: /csrg-svn/sys/kern/subr_prof.c (revision 17094)
1*17094Sbloom /*	subr_prof.c	6.4	84/08/29	*/
27332Ssam 
310292Smckusick /* last integrated from: gmon.c	4.10 (Berkeley) 1/14/83 */
410292Smckusick 
57332Ssam #ifdef GPROF
6*17094Sbloom #include "gprof.h"
7*17094Sbloom #include "param.h"
8*17094Sbloom #include "systm.h"
97332Ssam 
107332Ssam /*
117332Ssam  * Froms is actually a bunch of unsigned shorts indexing tos
127332Ssam  */
1310292Smckusick int profiling = 3;
1410292Smckusick u_short *froms;
1510292Smckusick struct tostruct *tos = 0;
1610292Smckusick long tolimit = 0;
179758Ssam #ifdef vax
187332Ssam char	*s_lowpc = (char *)0x80000000;
199758Ssam #endif
2010292Smckusick extern char etext;
2110292Smckusick char *s_highpc = &etext;
227332Ssam u_long	s_textsize = 0;
2310292Smckusick int ssiz;
247332Ssam u_short	*sbuf;
257332Ssam u_short	*kcount;
267332Ssam 
277332Ssam kmstartup()
287332Ssam {
2910292Smckusick 	u_long	fromssize, tossize;
307332Ssam 
3110292Smckusick 	/*
3210292Smckusick 	 *	round lowpc and highpc to multiples of the density we're using
3310292Smckusick 	 *	so the rest of the scaling (here and in gprof) stays in ints.
3410292Smckusick 	 */
3510292Smckusick 	s_lowpc = (char *)
3610292Smckusick 	    ROUNDDOWN((unsigned)s_lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
3710292Smckusick 	s_highpc = (char *)
3810292Smckusick 	    ROUNDUP((unsigned)s_highpc, HISTFRACTION*sizeof(HISTCOUNTER));
397332Ssam 	s_textsize = s_highpc - s_lowpc;
407332Ssam 	printf("Profiling kernel, s_textsize=%d [%x..%x]\n",
417332Ssam 		s_textsize, s_lowpc, s_highpc);
4210292Smckusick 	ssiz = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
4316781Smckusick 	sbuf = (u_short *)calloc(ssiz);
447332Ssam 	if (sbuf == 0) {
457332Ssam 		printf("No space for monitor buffer(s)\n");
467332Ssam 		return;
477332Ssam 	}
487332Ssam 	blkclr((caddr_t)sbuf, ssiz);
4910292Smckusick 	fromssize = s_textsize / HASHFRACTION;
5016781Smckusick 	froms = (u_short *)calloc(fromssize);
517332Ssam 	if (froms == 0) {
527332Ssam 		printf("No space for monitor buffer(s)\n");
5316781Smckusick 		cfreemem(sbuf, ssiz);
547332Ssam 		sbuf = 0;
557332Ssam 		return;
567332Ssam 	}
5710292Smckusick 	blkclr((caddr_t)froms, fromssize);
5810292Smckusick 	tolimit = s_textsize * ARCDENSITY / 100;
5910292Smckusick 	if (tolimit < MINARCS) {
6010292Smckusick 		tolimit = MINARCS;
6110292Smckusick 	} else if (tolimit > 65534) {
6210292Smckusick 		tolimit = 65534;
6310292Smckusick 	}
6410292Smckusick 	tossize = tolimit * sizeof(struct tostruct);
6516781Smckusick 	tos = (struct tostruct *)calloc(tossize);
667332Ssam 	if (tos == 0) {
677332Ssam 		printf("No space for monitor buffer(s)\n");
6816781Smckusick 		cfreemem(sbuf, ssiz);
697332Ssam 		sbuf = 0;
7016781Smckusick 		cfreemem(froms, fromssize);
717332Ssam 		froms = 0;
727332Ssam 		return;
737332Ssam 	}
7410292Smckusick 	blkclr((caddr_t)tos, tossize);
757332Ssam 	tos[0].link = 0;
767332Ssam 	((struct phdr *)sbuf)->lpc = s_lowpc;
777332Ssam 	((struct phdr *)sbuf)->hpc = s_highpc;
787332Ssam 	((struct phdr *)sbuf)->ncnt = ssiz;
797332Ssam 	kcount = (u_short *)(((int)sbuf) + sizeof(struct phdr));
807332Ssam #ifdef notdef
8110292Smckusick 	/*
8210292Smckusick 	 *	profiling is what mcount checks to see if
8310292Smckusick 	 *	all the data structures are ready!!!
8410292Smckusick 	 */
857332Ssam 	profiling = 0;		/* patch by hand when you're ready */
867332Ssam #endif
877332Ssam }
887332Ssam 
899758Ssam #ifdef vax
907332Ssam /*
917332Ssam  * This routine is massaged so that it may be jsb'ed to
927332Ssam  */
9310292Smckusick asm(".text");
9410292Smckusick asm("#the beginning of mcount()");
9510292Smckusick asm(".data");
967332Ssam mcount()
977332Ssam {
9810292Smckusick 	register char			*selfpc;	/* r11 => r5 */
9910292Smckusick 	register unsigned short		*frompcindex;	/* r10 => r4 */
10010292Smckusick 	register struct tostruct	*top;		/* r9  => r3 */
10110292Smckusick 	register struct tostruct	*prevtop;	/* r8  => r2 */
10210292Smckusick 	register long			toindex;	/* r7  => r1 */
10316924Smckusick 	static int s;
1047332Ssam 
1057332Ssam #ifdef lint
10610292Smckusick 	selfpc = (char *)0;
1077332Ssam 	frompcindex = 0;
1087332Ssam #else not lint
1097332Ssam 	/*
11010292Smckusick 	 *	find the return address for mcount,
11110292Smckusick 	 *	and the return address for mcount's caller.
1127332Ssam 	 */
11310292Smckusick 	asm("	.text");		/* make sure we're in text space */
1147332Ssam 	asm("	movl (sp), r11");	/* selfpc = ... (jsb frame) */
1157332Ssam 	asm("	movl 16(fp), r10");	/* frompcindex =     (calls frame) */
1167332Ssam #endif not lint
1177332Ssam 	/*
11810292Smckusick 	 *	check that we are profiling
1197332Ssam 	 */
12010292Smckusick 	if (profiling) {
1217332Ssam 		goto out;
12210292Smckusick 	}
1237332Ssam 	/*
12416924Smckusick 	 *	insure that we cannot be recursively invoked.
12516924Smckusick 	 *	this requires that splhigh() and splx() below
12616924Smckusick 	 *	do NOT call mcount!
12716924Smckusick 	 */
12816924Smckusick 	s = splhigh();
12916924Smckusick 	/*
13010292Smckusick 	 *	check that frompcindex is a reasonable pc value.
13110292Smckusick 	 *	for example:	signal catchers get called from the stack,
13210292Smckusick 	 *			not from text space.  too bad.
1337332Ssam 	 */
13410292Smckusick 	frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
13510292Smckusick 	if ((unsigned long)frompcindex > s_textsize) {
1367332Ssam 		goto done;
13710292Smckusick 	}
13810292Smckusick 	frompcindex =
13910292Smckusick 	    &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
14010292Smckusick 	toindex = *frompcindex;
14110292Smckusick 	if (toindex == 0) {
14210292Smckusick 		/*
14310292Smckusick 		 *	first time traversing this arc
14410292Smckusick 		 */
14510292Smckusick 		toindex = ++tos[0].link;
14610292Smckusick 		if (toindex >= tolimit) {
1477332Ssam 			goto overflow;
14810292Smckusick 		}
14910292Smckusick 		*frompcindex = toindex;
15010292Smckusick 		top = &tos[toindex];
1517332Ssam 		top->selfpc = selfpc;
15210292Smckusick 		top->count = 1;
1537332Ssam 		top->link = 0;
15410292Smckusick 		goto done;
1557332Ssam 	}
15610292Smckusick 	top = &tos[toindex];
15710292Smckusick 	if (top->selfpc == selfpc) {
15810292Smckusick 		/*
15910292Smckusick 		 *	arc at front of chain; usual case.
16010292Smckusick 		 */
16110292Smckusick 		top->count++;
16210292Smckusick 		goto done;
16310292Smckusick 	}
16410292Smckusick 	/*
16510292Smckusick 	 *	have to go looking down chain for it.
16610292Smckusick 	 *	top points to what we are looking at,
16710292Smckusick 	 *	prevtop points to previous top.
16810292Smckusick 	 *	we know it is not at the head of the chain.
16910292Smckusick 	 */
17010292Smckusick 	for (; /* goto done */; ) {
17110292Smckusick 		if (top->link == 0) {
17210292Smckusick 			/*
17310292Smckusick 			 *	top is end of the chain and none of the chain
17410292Smckusick 			 *	had top->selfpc == selfpc.
17510292Smckusick 			 *	so we allocate a new tostruct
17610292Smckusick 			 *	and link it to the head of the chain.
17710292Smckusick 			 */
17810292Smckusick 			toindex = ++tos[0].link;
17910292Smckusick 			if (toindex >= tolimit) {
18010292Smckusick 				goto overflow;
18110292Smckusick 			}
18210292Smckusick 			top = &tos[toindex];
18310292Smckusick 			top->selfpc = selfpc;
18410292Smckusick 			top->count = 1;
18510292Smckusick 			top->link = *frompcindex;
18610292Smckusick 			*frompcindex = toindex;
18710292Smckusick 			goto done;
18810292Smckusick 		}
18910292Smckusick 		/*
19010292Smckusick 		 *	otherwise, check the next arc on the chain.
19110292Smckusick 		 */
19210292Smckusick 		prevtop = top;
19310292Smckusick 		top = &tos[top->link];
1947332Ssam 		if (top->selfpc == selfpc) {
19510292Smckusick 			/*
19610292Smckusick 			 *	there it is.
19710292Smckusick 			 *	increment its count
19810292Smckusick 			 *	move it to the head of the chain.
19910292Smckusick 			 */
2007332Ssam 			top->count++;
20110292Smckusick 			toindex = prevtop->link;
20210292Smckusick 			prevtop->link = top->link;
20310292Smckusick 			top->link = *frompcindex;
20410292Smckusick 			*frompcindex = toindex;
20510292Smckusick 			goto done;
2067332Ssam 		}
20710292Smckusick 
2087332Ssam 	}
2097332Ssam done:
21016924Smckusick 	splx(s);
2117332Ssam 	/* and fall through */
2127332Ssam out:
2137332Ssam 	asm("	rsb");
2147332Ssam 
2157332Ssam overflow:
21610292Smckusick 	profiling = 3;
2177332Ssam 	printf("mcount: tos overflow\n");
2187332Ssam 	goto out;
2197332Ssam }
22010292Smckusick asm(".text");
22110292Smckusick asm("#the end of mcount()");
22210292Smckusick asm(".data");
22310292Smckusick #endif vax
2247332Ssam #endif GPROF
225