xref: /csrg-svn/sys/kern/subr_prof.c (revision 16781)
1*16781Smckusick /*	subr_prof.c	6.2	84/07/28	*/
27332Ssam 
310292Smckusick /* last integrated from: gmon.c	4.10 (Berkeley) 1/14/83 */
410292Smckusick 
57332Ssam #ifdef GPROF
610292Smckusick #include "../h/gprof.h"
77332Ssam #include "../h/param.h"
87332Ssam #include "../h/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);
43*16781Smckusick 	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;
50*16781Smckusick 	froms = (u_short *)calloc(fromssize);
517332Ssam 	if (froms == 0) {
527332Ssam 		printf("No space for monitor buffer(s)\n");
53*16781Smckusick 		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);
65*16781Smckusick 	tos = (struct tostruct *)calloc(tossize);
667332Ssam 	if (tos == 0) {
677332Ssam 		printf("No space for monitor buffer(s)\n");
68*16781Smckusick 		cfreemem(sbuf, ssiz);
697332Ssam 		sbuf = 0;
70*16781Smckusick 		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 */
1037332Ssam 
1047332Ssam #ifdef lint
10510292Smckusick 	selfpc = (char *)0;
1067332Ssam 	frompcindex = 0;
1077332Ssam #else not lint
1087332Ssam 	/*
10910292Smckusick 	 *	find the return address for mcount,
11010292Smckusick 	 *	and the return address for mcount's caller.
1117332Ssam 	 */
11210292Smckusick 	asm("	.text");		/* make sure we're in text space */
1137332Ssam 	asm("	movl (sp), r11");	/* selfpc = ... (jsb frame) */
1147332Ssam 	asm("	movl 16(fp), r10");	/* frompcindex =     (calls frame) */
1157332Ssam #endif not lint
1167332Ssam 	/*
11710292Smckusick 	 *	check that we are profiling
11810292Smckusick 	 *	and that we aren't recursively invoked.
1197332Ssam 	 */
12010292Smckusick 	if (profiling) {
1217332Ssam 		goto out;
12210292Smckusick 	}
1237332Ssam 	profiling++;
1247332Ssam 	/*
12510292Smckusick 	 *	check that frompcindex is a reasonable pc value.
12610292Smckusick 	 *	for example:	signal catchers get called from the stack,
12710292Smckusick 	 *			not from text space.  too bad.
1287332Ssam 	 */
12910292Smckusick 	frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
13010292Smckusick 	if ((unsigned long)frompcindex > s_textsize) {
1317332Ssam 		goto done;
13210292Smckusick 	}
13310292Smckusick 	frompcindex =
13410292Smckusick 	    &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
13510292Smckusick 	toindex = *frompcindex;
13610292Smckusick 	if (toindex == 0) {
13710292Smckusick 		/*
13810292Smckusick 		 *	first time traversing this arc
13910292Smckusick 		 */
14010292Smckusick 		toindex = ++tos[0].link;
14110292Smckusick 		if (toindex >= tolimit) {
1427332Ssam 			goto overflow;
14310292Smckusick 		}
14410292Smckusick 		*frompcindex = toindex;
14510292Smckusick 		top = &tos[toindex];
1467332Ssam 		top->selfpc = selfpc;
14710292Smckusick 		top->count = 1;
1487332Ssam 		top->link = 0;
14910292Smckusick 		goto done;
1507332Ssam 	}
15110292Smckusick 	top = &tos[toindex];
15210292Smckusick 	if (top->selfpc == selfpc) {
15310292Smckusick 		/*
15410292Smckusick 		 *	arc at front of chain; usual case.
15510292Smckusick 		 */
15610292Smckusick 		top->count++;
15710292Smckusick 		goto done;
15810292Smckusick 	}
15910292Smckusick 	/*
16010292Smckusick 	 *	have to go looking down chain for it.
16110292Smckusick 	 *	top points to what we are looking at,
16210292Smckusick 	 *	prevtop points to previous top.
16310292Smckusick 	 *	we know it is not at the head of the chain.
16410292Smckusick 	 */
16510292Smckusick 	for (; /* goto done */; ) {
16610292Smckusick 		if (top->link == 0) {
16710292Smckusick 			/*
16810292Smckusick 			 *	top is end of the chain and none of the chain
16910292Smckusick 			 *	had top->selfpc == selfpc.
17010292Smckusick 			 *	so we allocate a new tostruct
17110292Smckusick 			 *	and link it to the head of the chain.
17210292Smckusick 			 */
17310292Smckusick 			toindex = ++tos[0].link;
17410292Smckusick 			if (toindex >= tolimit) {
17510292Smckusick 				goto overflow;
17610292Smckusick 			}
17710292Smckusick 			top = &tos[toindex];
17810292Smckusick 			top->selfpc = selfpc;
17910292Smckusick 			top->count = 1;
18010292Smckusick 			top->link = *frompcindex;
18110292Smckusick 			*frompcindex = toindex;
18210292Smckusick 			goto done;
18310292Smckusick 		}
18410292Smckusick 		/*
18510292Smckusick 		 *	otherwise, check the next arc on the chain.
18610292Smckusick 		 */
18710292Smckusick 		prevtop = top;
18810292Smckusick 		top = &tos[top->link];
1897332Ssam 		if (top->selfpc == selfpc) {
19010292Smckusick 			/*
19110292Smckusick 			 *	there it is.
19210292Smckusick 			 *	increment its count
19310292Smckusick 			 *	move it to the head of the chain.
19410292Smckusick 			 */
1957332Ssam 			top->count++;
19610292Smckusick 			toindex = prevtop->link;
19710292Smckusick 			prevtop->link = top->link;
19810292Smckusick 			top->link = *frompcindex;
19910292Smckusick 			*frompcindex = toindex;
20010292Smckusick 			goto done;
2017332Ssam 		}
20210292Smckusick 
2037332Ssam 	}
2047332Ssam done:
2057332Ssam 	profiling--;
2067332Ssam 	/* and fall through */
2077332Ssam out:
2087332Ssam 	asm("	rsb");
2097332Ssam 
2107332Ssam overflow:
21110292Smckusick 	profiling = 3;
2127332Ssam 	printf("mcount: tos overflow\n");
2137332Ssam 	goto out;
2147332Ssam }
21510292Smckusick asm(".text");
21610292Smckusick asm("#the end of mcount()");
21710292Smckusick asm(".data");
21810292Smckusick #endif vax
2197332Ssam #endif GPROF
220