xref: /csrg-svn/sys/kern/subr_prof.c (revision 10292)
1*10292Smckusick /*	subr_prof.c	4.4	83/01/15	*/
27332Ssam 
3*10292Smckusick /* last integrated from: gmon.c	4.10 (Berkeley) 1/14/83 */
4*10292Smckusick 
57332Ssam #ifdef GPROF
6*10292Smckusick #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  */
13*10292Smckusick int profiling = 3;
14*10292Smckusick u_short *froms;
15*10292Smckusick struct tostruct *tos = 0;
16*10292Smckusick long tolimit = 0;
179758Ssam #ifdef vax
187332Ssam char	*s_lowpc = (char *)0x80000000;
199758Ssam #endif
209758Ssam #ifdef sun
219758Ssam char	*s_lowpc = (char *)0x4000;
229758Ssam #endif
23*10292Smckusick extern char etext;
24*10292Smckusick char *s_highpc = &etext;
257332Ssam u_long	s_textsize = 0;
26*10292Smckusick int ssiz;
277332Ssam u_short	*sbuf;
287332Ssam u_short	*kcount;
297332Ssam 
307332Ssam kmstartup()
317332Ssam {
32*10292Smckusick 	u_long	fromssize, tossize;
337332Ssam 
34*10292Smckusick 	/*
35*10292Smckusick 	 *	round lowpc and highpc to multiples of the density we're using
36*10292Smckusick 	 *	so the rest of the scaling (here and in gprof) stays in ints.
37*10292Smckusick 	 */
38*10292Smckusick 	s_lowpc = (char *)
39*10292Smckusick 	    ROUNDDOWN((unsigned)s_lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
40*10292Smckusick 	s_highpc = (char *)
41*10292Smckusick 	    ROUNDUP((unsigned)s_highpc, HISTFRACTION*sizeof(HISTCOUNTER));
427332Ssam 	s_textsize = s_highpc - s_lowpc;
437332Ssam 	printf("Profiling kernel, s_textsize=%d [%x..%x]\n",
447332Ssam 		s_textsize, s_lowpc, s_highpc);
45*10292Smckusick 	ssiz = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
469161Ssam 	sbuf = (u_short *)wmemall(memall, ssiz);
477332Ssam 	if (sbuf == 0) {
487332Ssam 		printf("No space for monitor buffer(s)\n");
497332Ssam 		return;
507332Ssam 	}
517332Ssam 	blkclr((caddr_t)sbuf, ssiz);
52*10292Smckusick 	fromssize = s_textsize / HASHFRACTION;
53*10292Smckusick 	froms = (u_short *)wmemall(memall, fromssize);
547332Ssam 	if (froms == 0) {
557332Ssam 		printf("No space for monitor buffer(s)\n");
567332Ssam 		wmemfree(sbuf, ssiz);
577332Ssam 		sbuf = 0;
587332Ssam 		return;
597332Ssam 	}
60*10292Smckusick 	blkclr((caddr_t)froms, fromssize);
61*10292Smckusick 	tolimit = s_textsize * ARCDENSITY / 100;
62*10292Smckusick 	if (tolimit < MINARCS) {
63*10292Smckusick 		tolimit = MINARCS;
64*10292Smckusick 	} else if (tolimit > 65534) {
65*10292Smckusick 		tolimit = 65534;
66*10292Smckusick 	}
67*10292Smckusick 	tossize = tolimit * sizeof(struct tostruct);
68*10292Smckusick 	tos = (struct tostruct *)wmemall(memall, tossize);
697332Ssam 	if (tos == 0) {
707332Ssam 		printf("No space for monitor buffer(s)\n");
717332Ssam 		wmemfree(sbuf, ssiz);
727332Ssam 		sbuf = 0;
73*10292Smckusick 		wmemfree(froms, fromssize);
747332Ssam 		froms = 0;
757332Ssam 		return;
767332Ssam 	}
77*10292Smckusick 	blkclr((caddr_t)tos, tossize);
787332Ssam 	tos[0].link = 0;
797332Ssam 	((struct phdr *)sbuf)->lpc = s_lowpc;
807332Ssam 	((struct phdr *)sbuf)->hpc = s_highpc;
817332Ssam 	((struct phdr *)sbuf)->ncnt = ssiz;
827332Ssam 	kcount = (u_short *)(((int)sbuf) + sizeof(struct phdr));
837332Ssam #ifdef notdef
84*10292Smckusick 	/*
85*10292Smckusick 	 *	profiling is what mcount checks to see if
86*10292Smckusick 	 *	all the data structures are ready!!!
87*10292Smckusick 	 */
887332Ssam 	profiling = 0;		/* patch by hand when you're ready */
897332Ssam #endif
907332Ssam }
917332Ssam 
929758Ssam #ifdef vax
937332Ssam /*
947332Ssam  * This routine is massaged so that it may be jsb'ed to
957332Ssam  */
96*10292Smckusick asm(".text");
97*10292Smckusick asm("#the beginning of mcount()");
98*10292Smckusick asm(".data");
997332Ssam mcount()
1007332Ssam {
101*10292Smckusick 	register char			*selfpc;	/* r11 => r5 */
102*10292Smckusick 	register unsigned short		*frompcindex;	/* r10 => r4 */
103*10292Smckusick 	register struct tostruct	*top;		/* r9  => r3 */
104*10292Smckusick 	register struct tostruct	*prevtop;	/* r8  => r2 */
105*10292Smckusick 	register long			toindex;	/* r7  => r1 */
1067332Ssam 
1077332Ssam #ifdef lint
108*10292Smckusick 	selfpc = (char *)0;
1097332Ssam 	frompcindex = 0;
1107332Ssam #else not lint
1117332Ssam 	/*
112*10292Smckusick 	 *	find the return address for mcount,
113*10292Smckusick 	 *	and the return address for mcount's caller.
1147332Ssam 	 */
115*10292Smckusick 	asm("	.text");		/* make sure we're in text space */
1167332Ssam 	asm("	movl (sp), r11");	/* selfpc = ... (jsb frame) */
1177332Ssam 	asm("	movl 16(fp), r10");	/* frompcindex =     (calls frame) */
1187332Ssam #endif not lint
1197332Ssam 	/*
120*10292Smckusick 	 *	check that we are profiling
121*10292Smckusick 	 *	and that we aren't recursively invoked.
1227332Ssam 	 */
123*10292Smckusick 	if (profiling) {
1247332Ssam 		goto out;
125*10292Smckusick 	}
1267332Ssam 	profiling++;
1277332Ssam 	/*
128*10292Smckusick 	 *	check that frompcindex is a reasonable pc value.
129*10292Smckusick 	 *	for example:	signal catchers get called from the stack,
130*10292Smckusick 	 *			not from text space.  too bad.
1317332Ssam 	 */
132*10292Smckusick 	frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
133*10292Smckusick 	if ((unsigned long)frompcindex > s_textsize) {
1347332Ssam 		goto done;
135*10292Smckusick 	}
136*10292Smckusick 	frompcindex =
137*10292Smckusick 	    &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
138*10292Smckusick 	toindex = *frompcindex;
139*10292Smckusick 	if (toindex == 0) {
140*10292Smckusick 		/*
141*10292Smckusick 		 *	first time traversing this arc
142*10292Smckusick 		 */
143*10292Smckusick 		toindex = ++tos[0].link;
144*10292Smckusick 		if (toindex >= tolimit) {
1457332Ssam 			goto overflow;
146*10292Smckusick 		}
147*10292Smckusick 		*frompcindex = toindex;
148*10292Smckusick 		top = &tos[toindex];
1497332Ssam 		top->selfpc = selfpc;
150*10292Smckusick 		top->count = 1;
1517332Ssam 		top->link = 0;
152*10292Smckusick 		goto done;
1537332Ssam 	}
154*10292Smckusick 	top = &tos[toindex];
155*10292Smckusick 	if (top->selfpc == selfpc) {
156*10292Smckusick 		/*
157*10292Smckusick 		 *	arc at front of chain; usual case.
158*10292Smckusick 		 */
159*10292Smckusick 		top->count++;
160*10292Smckusick 		goto done;
161*10292Smckusick 	}
162*10292Smckusick 	/*
163*10292Smckusick 	 *	have to go looking down chain for it.
164*10292Smckusick 	 *	top points to what we are looking at,
165*10292Smckusick 	 *	prevtop points to previous top.
166*10292Smckusick 	 *	we know it is not at the head of the chain.
167*10292Smckusick 	 */
168*10292Smckusick 	for (; /* goto done */; ) {
169*10292Smckusick 		if (top->link == 0) {
170*10292Smckusick 			/*
171*10292Smckusick 			 *	top is end of the chain and none of the chain
172*10292Smckusick 			 *	had top->selfpc == selfpc.
173*10292Smckusick 			 *	so we allocate a new tostruct
174*10292Smckusick 			 *	and link it to the head of the chain.
175*10292Smckusick 			 */
176*10292Smckusick 			toindex = ++tos[0].link;
177*10292Smckusick 			if (toindex >= tolimit) {
178*10292Smckusick 				goto overflow;
179*10292Smckusick 			}
180*10292Smckusick 			top = &tos[toindex];
181*10292Smckusick 			top->selfpc = selfpc;
182*10292Smckusick 			top->count = 1;
183*10292Smckusick 			top->link = *frompcindex;
184*10292Smckusick 			*frompcindex = toindex;
185*10292Smckusick 			goto done;
186*10292Smckusick 		}
187*10292Smckusick 		/*
188*10292Smckusick 		 *	otherwise, check the next arc on the chain.
189*10292Smckusick 		 */
190*10292Smckusick 		prevtop = top;
191*10292Smckusick 		top = &tos[top->link];
1927332Ssam 		if (top->selfpc == selfpc) {
193*10292Smckusick 			/*
194*10292Smckusick 			 *	there it is.
195*10292Smckusick 			 *	increment its count
196*10292Smckusick 			 *	move it to the head of the chain.
197*10292Smckusick 			 */
1987332Ssam 			top->count++;
199*10292Smckusick 			toindex = prevtop->link;
200*10292Smckusick 			prevtop->link = top->link;
201*10292Smckusick 			top->link = *frompcindex;
202*10292Smckusick 			*frompcindex = toindex;
203*10292Smckusick 			goto done;
2047332Ssam 		}
205*10292Smckusick 
2067332Ssam 	}
2077332Ssam done:
2087332Ssam 	profiling--;
2097332Ssam 	/* and fall through */
2107332Ssam out:
2117332Ssam 	asm("	rsb");
2127332Ssam 
2137332Ssam overflow:
214*10292Smckusick 	profiling = 3;
2157332Ssam 	printf("mcount: tos overflow\n");
2167332Ssam 	goto out;
2177332Ssam }
218*10292Smckusick asm(".text");
219*10292Smckusick asm("#the end of mcount()");
220*10292Smckusick asm(".data");
221*10292Smckusick #endif vax
2227332Ssam #endif GPROF
223