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