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