xref: /csrg-svn/sys/kern/subr_prof.c (revision 9161)
1*9161Ssam /*	subr_prof.c	4.2	82/11/13	*/
27332Ssam 
37332Ssam #ifdef GPROF
47332Ssam #include "../h/crt0.h"
57332Ssam #include "../h/param.h"
67332Ssam #include "../h/systm.h"
77332Ssam 
87332Ssam /*
97332Ssam  * Froms is actually a bunch of unsigned shorts indexing tos
107332Ssam  */
117332Ssam int	profiling = 3;
127332Ssam u_short	*froms = 0;
137332Ssam struct	tostruct *tos = 0;
147332Ssam u_short	tolimit = 0;
157332Ssam char	*s_lowpc = (char *)0x80000000;
167332Ssam extern	char etext;
177332Ssam char	*s_highpc = &etext;
187332Ssam u_long	s_textsize = 0;
197332Ssam int	ssiz;
207332Ssam u_short	*sbuf;
217332Ssam u_short	*kcount;
227332Ssam 
237332Ssam kmstartup()
247332Ssam {
257332Ssam 	u_long	limit;
267332Ssam 
277332Ssam 	s_textsize = s_highpc - s_lowpc;
287332Ssam 	ssiz = s_textsize + sizeof(struct phdr);
297332Ssam 	printf("Profiling kernel, s_textsize=%d [%x..%x]\n",
307332Ssam 		s_textsize, s_lowpc, s_highpc);
31*9161Ssam 	sbuf = (u_short *)wmemall(memall, ssiz);
327332Ssam 	if (sbuf == 0) {
337332Ssam 		printf("No space for monitor buffer(s)\n");
347332Ssam 		return;
357332Ssam 	}
367332Ssam 	blkclr((caddr_t)sbuf, ssiz);
37*9161Ssam 	froms = (u_short *)wmemall(memall, s_textsize);
387332Ssam 	if (froms == 0) {
397332Ssam 		printf("No space for monitor buffer(s)\n");
407332Ssam 		wmemfree(sbuf, ssiz);
417332Ssam 		sbuf = 0;
427332Ssam 		return;
437332Ssam 	}
447332Ssam 	blkclr((caddr_t)froms, s_textsize);
45*9161Ssam 	tos = (struct tostruct *)wmemall(memall, s_textsize);
467332Ssam 	if (tos == 0) {
477332Ssam 		printf("No space for monitor buffer(s)\n");
487332Ssam 		wmemfree(sbuf, ssiz);
497332Ssam 		sbuf = 0;
507332Ssam 		wmemfree(froms, s_textsize);
517332Ssam 		froms = 0;
527332Ssam 		return;
537332Ssam 	}
547332Ssam 	blkclr((caddr_t)tos, s_textsize);
557332Ssam 	tos[0].link = 0;
567332Ssam 	limit = s_textsize / sizeof(struct tostruct);
577332Ssam 	/*
587332Ssam 	 * Tolimit is what mcount checks to see if
597332Ssam 	 * all the data structures are ready!!!
607332Ssam 	 * Make sure it won't overflow.
617332Ssam 	 */
627332Ssam 	tolimit = limit > 65534 ? 65534 : limit;
637332Ssam 	((struct phdr *)sbuf)->lpc = s_lowpc;
647332Ssam 	((struct phdr *)sbuf)->hpc = s_highpc;
657332Ssam 	((struct phdr *)sbuf)->ncnt = ssiz;
667332Ssam 	kcount = (u_short *)(((int)sbuf) + sizeof(struct phdr));
677332Ssam #ifdef notdef
687332Ssam 	profiling = 0;		/* patch by hand when you're ready */
697332Ssam #endif
707332Ssam }
717332Ssam 
727332Ssam /*
737332Ssam  * This routine is massaged so that it may be jsb'ed to
747332Ssam  */
757332Ssam asm("#define _mcount mcount");
767332Ssam mcount()
777332Ssam {
787332Ssam 	register char *selfpc;		/* r11 */
797332Ssam 	register u_short *frompcindex;	/* r10 */
807332Ssam 	register struct tostruct *top;	/* r9 */
817332Ssam 
827332Ssam 	asm("	forgot to run ex script on gcrt0.s");
837332Ssam 	asm("#define r11 r5");
847332Ssam 	asm("#define r10 r4");
857332Ssam 	asm("#define r9 r3");
867332Ssam #ifdef lint
877332Ssam 	selfpc = (char *) 0;
887332Ssam 	frompcindex = 0;
897332Ssam #else not lint
907332Ssam 	/*
917332Ssam 	 * Find the return address for mcount,
927332Ssam 	 * and the return address for mcount's caller.
937332Ssam 	 */
947332Ssam 	asm("	movl (sp), r11");	/* selfpc = ... (jsb frame) */
957332Ssam 	asm("	movl 16(fp), r10");	/* frompcindex =     (calls frame) */
967332Ssam #endif not lint
977332Ssam 	/*
987332Ssam 	 * Check that we are profiling
997332Ssam 	 * and that we aren't recursively invoked.
1007332Ssam 	 */
1017332Ssam 	if (tolimit == 0)
1027332Ssam 		goto out;
1037332Ssam 	if (profiling)
1047332Ssam 		goto out;
1057332Ssam 	profiling++;
1067332Ssam 	/*
1077332Ssam 	 * Check that frompcindex is a reasonable pc value.
1087332Ssam 	 * For example:	signal catchers get called from the stack,
1097332Ssam 	 * 		not from text space.  too bad.
1107332Ssam 	 */
1117332Ssam 	frompcindex = (u_short *)((long)frompcindex - (long)s_lowpc);
1127332Ssam 	if ((u_long)frompcindex > s_textsize)
1137332Ssam 		goto done;
1147332Ssam 	frompcindex = &froms[((long)frompcindex) >> 1];
1157332Ssam 	if (*frompcindex != 0)
1167332Ssam 		top = &tos[*frompcindex];
1177332Ssam 	else {
1187332Ssam 		*frompcindex = ++tos[0].link;
1197332Ssam 		if (*frompcindex >= tolimit)
1207332Ssam 			goto overflow;
1217332Ssam 		top = &tos[*frompcindex];
1227332Ssam 		top->selfpc = selfpc;
1237332Ssam 		top->count = 0;
1247332Ssam 		top->link = 0;
1257332Ssam 	}
1267332Ssam 	for (; /* break */; top = &tos[top->link]) {
1277332Ssam 		if (top->selfpc == selfpc) {
1287332Ssam 			top->count++;
1297332Ssam 			break;
1307332Ssam 		}
1317332Ssam 		if (top->link != 0)
1327332Ssam 			continue;
1337332Ssam 		top->link = ++tos[0].link;
1347332Ssam 		if (top->link >= tolimit)
1357332Ssam 			goto overflow;
1367332Ssam 		top = &tos[top->link];
1377332Ssam 		top->selfpc = selfpc;
1387332Ssam 		top->count = 1;
1397332Ssam 		top->link = 0;
1407332Ssam 		break;
1417332Ssam 	}
1427332Ssam done:
1437332Ssam 	profiling--;
1447332Ssam 	/* and fall through */
1457332Ssam out:
1467332Ssam 	asm("	rsb");
1477332Ssam 	asm("#undef r11");
1487332Ssam 	asm("#undef r10");
1497332Ssam 	asm("#undef r9");
1507332Ssam 	asm("#undef _mcount");
1517332Ssam 
1527332Ssam overflow:
1537332Ssam 	tolimit = 0;
1547332Ssam 	printf("mcount: tos overflow\n");
1557332Ssam 	goto out;
1567332Ssam }
1577332Ssam #endif GPROF
158