xref: /csrg-svn/sys/kern/subr_prof.c (revision 7332)
1*7332Ssam /*	subr_prof.c	4.1	82/06/28	*/
2*7332Ssam 
3*7332Ssam #ifdef GPROF
4*7332Ssam #include "../h/crt0.h"
5*7332Ssam #include "../h/param.h"
6*7332Ssam #include "../h/systm.h"
7*7332Ssam 
8*7332Ssam /*
9*7332Ssam  * Froms is actually a bunch of unsigned shorts indexing tos
10*7332Ssam  */
11*7332Ssam int	profiling = 3;
12*7332Ssam u_short	*froms = 0;
13*7332Ssam struct	tostruct *tos = 0;
14*7332Ssam u_short	tolimit = 0;
15*7332Ssam char	*s_lowpc = (char *)0x80000000;
16*7332Ssam extern	char etext;
17*7332Ssam char	*s_highpc = &etext;
18*7332Ssam u_long	s_textsize = 0;
19*7332Ssam int	ssiz;
20*7332Ssam u_short	*sbuf;
21*7332Ssam u_short	*kcount;
22*7332Ssam 
23*7332Ssam kmstartup()
24*7332Ssam {
25*7332Ssam 	u_long	limit;
26*7332Ssam 
27*7332Ssam 	s_textsize = s_highpc - s_lowpc;
28*7332Ssam 	ssiz = s_textsize + sizeof(struct phdr);
29*7332Ssam 	printf("Profiling kernel, s_textsize=%d [%x..%x]\n",
30*7332Ssam 		s_textsize, s_lowpc, s_highpc);
31*7332Ssam 	sbuf = (u_short *)wmemall(vmemall, ssiz);
32*7332Ssam 	if (sbuf == 0) {
33*7332Ssam 		printf("No space for monitor buffer(s)\n");
34*7332Ssam 		return;
35*7332Ssam 	}
36*7332Ssam 	blkclr((caddr_t)sbuf, ssiz);
37*7332Ssam 	froms = (u_short *)wmemall(vmemall, s_textsize);
38*7332Ssam 	if (froms == 0) {
39*7332Ssam 		printf("No space for monitor buffer(s)\n");
40*7332Ssam 		wmemfree(sbuf, ssiz);
41*7332Ssam 		sbuf = 0;
42*7332Ssam 		return;
43*7332Ssam 	}
44*7332Ssam 	blkclr((caddr_t)froms, s_textsize);
45*7332Ssam 	tos = (struct tostruct *)wmemall(vmemall, s_textsize);
46*7332Ssam 	if (tos == 0) {
47*7332Ssam 		printf("No space for monitor buffer(s)\n");
48*7332Ssam 		wmemfree(sbuf, ssiz);
49*7332Ssam 		sbuf = 0;
50*7332Ssam 		wmemfree(froms, s_textsize);
51*7332Ssam 		froms = 0;
52*7332Ssam 		return;
53*7332Ssam 	}
54*7332Ssam 	blkclr((caddr_t)tos, s_textsize);
55*7332Ssam 	tos[0].link = 0;
56*7332Ssam 	limit = s_textsize / sizeof(struct tostruct);
57*7332Ssam 	/*
58*7332Ssam 	 * Tolimit is what mcount checks to see if
59*7332Ssam 	 * all the data structures are ready!!!
60*7332Ssam 	 * Make sure it won't overflow.
61*7332Ssam 	 */
62*7332Ssam 	tolimit = limit > 65534 ? 65534 : limit;
63*7332Ssam 	((struct phdr *)sbuf)->lpc = s_lowpc;
64*7332Ssam 	((struct phdr *)sbuf)->hpc = s_highpc;
65*7332Ssam 	((struct phdr *)sbuf)->ncnt = ssiz;
66*7332Ssam 	kcount = (u_short *)(((int)sbuf) + sizeof(struct phdr));
67*7332Ssam #ifdef notdef
68*7332Ssam 	profiling = 0;		/* patch by hand when you're ready */
69*7332Ssam #endif
70*7332Ssam }
71*7332Ssam 
72*7332Ssam /*
73*7332Ssam  * This routine is massaged so that it may be jsb'ed to
74*7332Ssam  */
75*7332Ssam asm("#define _mcount mcount");
76*7332Ssam mcount()
77*7332Ssam {
78*7332Ssam 	register char *selfpc;		/* r11 */
79*7332Ssam 	register u_short *frompcindex;	/* r10 */
80*7332Ssam 	register struct tostruct *top;	/* r9 */
81*7332Ssam 
82*7332Ssam 	asm("	forgot to run ex script on gcrt0.s");
83*7332Ssam 	asm("#define r11 r5");
84*7332Ssam 	asm("#define r10 r4");
85*7332Ssam 	asm("#define r9 r3");
86*7332Ssam #ifdef lint
87*7332Ssam 	selfpc = (char *) 0;
88*7332Ssam 	frompcindex = 0;
89*7332Ssam #else not lint
90*7332Ssam 	/*
91*7332Ssam 	 * Find the return address for mcount,
92*7332Ssam 	 * and the return address for mcount's caller.
93*7332Ssam 	 */
94*7332Ssam 	asm("	movl (sp), r11");	/* selfpc = ... (jsb frame) */
95*7332Ssam 	asm("	movl 16(fp), r10");	/* frompcindex =     (calls frame) */
96*7332Ssam #endif not lint
97*7332Ssam 	/*
98*7332Ssam 	 * Check that we are profiling
99*7332Ssam 	 * and that we aren't recursively invoked.
100*7332Ssam 	 */
101*7332Ssam 	if (tolimit == 0)
102*7332Ssam 		goto out;
103*7332Ssam 	if (profiling)
104*7332Ssam 		goto out;
105*7332Ssam 	profiling++;
106*7332Ssam 	/*
107*7332Ssam 	 * Check that frompcindex is a reasonable pc value.
108*7332Ssam 	 * For example:	signal catchers get called from the stack,
109*7332Ssam 	 * 		not from text space.  too bad.
110*7332Ssam 	 */
111*7332Ssam 	frompcindex = (u_short *)((long)frompcindex - (long)s_lowpc);
112*7332Ssam 	if ((u_long)frompcindex > s_textsize)
113*7332Ssam 		goto done;
114*7332Ssam 	frompcindex = &froms[((long)frompcindex) >> 1];
115*7332Ssam 	if (*frompcindex != 0)
116*7332Ssam 		top = &tos[*frompcindex];
117*7332Ssam 	else {
118*7332Ssam 		*frompcindex = ++tos[0].link;
119*7332Ssam 		if (*frompcindex >= tolimit)
120*7332Ssam 			goto overflow;
121*7332Ssam 		top = &tos[*frompcindex];
122*7332Ssam 		top->selfpc = selfpc;
123*7332Ssam 		top->count = 0;
124*7332Ssam 		top->link = 0;
125*7332Ssam 	}
126*7332Ssam 	for (; /* break */; top = &tos[top->link]) {
127*7332Ssam 		if (top->selfpc == selfpc) {
128*7332Ssam 			top->count++;
129*7332Ssam 			break;
130*7332Ssam 		}
131*7332Ssam 		if (top->link != 0)
132*7332Ssam 			continue;
133*7332Ssam 		top->link = ++tos[0].link;
134*7332Ssam 		if (top->link >= tolimit)
135*7332Ssam 			goto overflow;
136*7332Ssam 		top = &tos[top->link];
137*7332Ssam 		top->selfpc = selfpc;
138*7332Ssam 		top->count = 1;
139*7332Ssam 		top->link = 0;
140*7332Ssam 		break;
141*7332Ssam 	}
142*7332Ssam done:
143*7332Ssam 	profiling--;
144*7332Ssam 	/* and fall through */
145*7332Ssam out:
146*7332Ssam 	asm("	rsb");
147*7332Ssam 	asm("#undef r11");
148*7332Ssam 	asm("#undef r10");
149*7332Ssam 	asm("#undef r9");
150*7332Ssam 	asm("#undef _mcount");
151*7332Ssam 
152*7332Ssam overflow:
153*7332Ssam 	tolimit = 0;
154*7332Ssam 	printf("mcount: tos overflow\n");
155*7332Ssam 	goto out;
156*7332Ssam }
157*7332Ssam #endif GPROF
158