xref: /csrg-svn/sys/kern/subr_prof.c (revision 10292)
1 /*	subr_prof.c	4.4	83/01/15	*/
2 
3 /* last integrated from: gmon.c	4.10 (Berkeley) 1/14/83 */
4 
5 #ifdef GPROF
6 #include "../h/gprof.h"
7 #include "../h/param.h"
8 #include "../h/systm.h"
9 
10 /*
11  * Froms is actually a bunch of unsigned shorts indexing tos
12  */
13 int profiling = 3;
14 u_short *froms;
15 struct tostruct *tos = 0;
16 long tolimit = 0;
17 #ifdef vax
18 char	*s_lowpc = (char *)0x80000000;
19 #endif
20 #ifdef sun
21 char	*s_lowpc = (char *)0x4000;
22 #endif
23 extern char etext;
24 char *s_highpc = &etext;
25 u_long	s_textsize = 0;
26 int ssiz;
27 u_short	*sbuf;
28 u_short	*kcount;
29 
30 kmstartup()
31 {
32 	u_long	fromssize, tossize;
33 
34 	/*
35 	 *	round lowpc and highpc to multiples of the density we're using
36 	 *	so the rest of the scaling (here and in gprof) stays in ints.
37 	 */
38 	s_lowpc = (char *)
39 	    ROUNDDOWN((unsigned)s_lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
40 	s_highpc = (char *)
41 	    ROUNDUP((unsigned)s_highpc, HISTFRACTION*sizeof(HISTCOUNTER));
42 	s_textsize = s_highpc - s_lowpc;
43 	printf("Profiling kernel, s_textsize=%d [%x..%x]\n",
44 		s_textsize, s_lowpc, s_highpc);
45 	ssiz = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
46 	sbuf = (u_short *)wmemall(memall, ssiz);
47 	if (sbuf == 0) {
48 		printf("No space for monitor buffer(s)\n");
49 		return;
50 	}
51 	blkclr((caddr_t)sbuf, ssiz);
52 	fromssize = s_textsize / HASHFRACTION;
53 	froms = (u_short *)wmemall(memall, fromssize);
54 	if (froms == 0) {
55 		printf("No space for monitor buffer(s)\n");
56 		wmemfree(sbuf, ssiz);
57 		sbuf = 0;
58 		return;
59 	}
60 	blkclr((caddr_t)froms, fromssize);
61 	tolimit = s_textsize * ARCDENSITY / 100;
62 	if (tolimit < MINARCS) {
63 		tolimit = MINARCS;
64 	} else if (tolimit > 65534) {
65 		tolimit = 65534;
66 	}
67 	tossize = tolimit * sizeof(struct tostruct);
68 	tos = (struct tostruct *)wmemall(memall, tossize);
69 	if (tos == 0) {
70 		printf("No space for monitor buffer(s)\n");
71 		wmemfree(sbuf, ssiz);
72 		sbuf = 0;
73 		wmemfree(froms, fromssize);
74 		froms = 0;
75 		return;
76 	}
77 	blkclr((caddr_t)tos, tossize);
78 	tos[0].link = 0;
79 	((struct phdr *)sbuf)->lpc = s_lowpc;
80 	((struct phdr *)sbuf)->hpc = s_highpc;
81 	((struct phdr *)sbuf)->ncnt = ssiz;
82 	kcount = (u_short *)(((int)sbuf) + sizeof(struct phdr));
83 #ifdef notdef
84 	/*
85 	 *	profiling is what mcount checks to see if
86 	 *	all the data structures are ready!!!
87 	 */
88 	profiling = 0;		/* patch by hand when you're ready */
89 #endif
90 }
91 
92 #ifdef vax
93 /*
94  * This routine is massaged so that it may be jsb'ed to
95  */
96 asm(".text");
97 asm("#the beginning of mcount()");
98 asm(".data");
99 mcount()
100 {
101 	register char			*selfpc;	/* r11 => r5 */
102 	register unsigned short		*frompcindex;	/* r10 => r4 */
103 	register struct tostruct	*top;		/* r9  => r3 */
104 	register struct tostruct	*prevtop;	/* r8  => r2 */
105 	register long			toindex;	/* r7  => r1 */
106 
107 #ifdef lint
108 	selfpc = (char *)0;
109 	frompcindex = 0;
110 #else not lint
111 	/*
112 	 *	find the return address for mcount,
113 	 *	and the return address for mcount's caller.
114 	 */
115 	asm("	.text");		/* make sure we're in text space */
116 	asm("	movl (sp), r11");	/* selfpc = ... (jsb frame) */
117 	asm("	movl 16(fp), r10");	/* frompcindex =     (calls frame) */
118 #endif not lint
119 	/*
120 	 *	check that we are profiling
121 	 *	and that we aren't recursively invoked.
122 	 */
123 	if (profiling) {
124 		goto out;
125 	}
126 	profiling++;
127 	/*
128 	 *	check that frompcindex is a reasonable pc value.
129 	 *	for example:	signal catchers get called from the stack,
130 	 *			not from text space.  too bad.
131 	 */
132 	frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
133 	if ((unsigned long)frompcindex > s_textsize) {
134 		goto done;
135 	}
136 	frompcindex =
137 	    &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
138 	toindex = *frompcindex;
139 	if (toindex == 0) {
140 		/*
141 		 *	first time traversing this arc
142 		 */
143 		toindex = ++tos[0].link;
144 		if (toindex >= tolimit) {
145 			goto overflow;
146 		}
147 		*frompcindex = toindex;
148 		top = &tos[toindex];
149 		top->selfpc = selfpc;
150 		top->count = 1;
151 		top->link = 0;
152 		goto done;
153 	}
154 	top = &tos[toindex];
155 	if (top->selfpc == selfpc) {
156 		/*
157 		 *	arc at front of chain; usual case.
158 		 */
159 		top->count++;
160 		goto done;
161 	}
162 	/*
163 	 *	have to go looking down chain for it.
164 	 *	top points to what we are looking at,
165 	 *	prevtop points to previous top.
166 	 *	we know it is not at the head of the chain.
167 	 */
168 	for (; /* goto done */; ) {
169 		if (top->link == 0) {
170 			/*
171 			 *	top is end of the chain and none of the chain
172 			 *	had top->selfpc == selfpc.
173 			 *	so we allocate a new tostruct
174 			 *	and link it to the head of the chain.
175 			 */
176 			toindex = ++tos[0].link;
177 			if (toindex >= tolimit) {
178 				goto overflow;
179 			}
180 			top = &tos[toindex];
181 			top->selfpc = selfpc;
182 			top->count = 1;
183 			top->link = *frompcindex;
184 			*frompcindex = toindex;
185 			goto done;
186 		}
187 		/*
188 		 *	otherwise, check the next arc on the chain.
189 		 */
190 		prevtop = top;
191 		top = &tos[top->link];
192 		if (top->selfpc == selfpc) {
193 			/*
194 			 *	there it is.
195 			 *	increment its count
196 			 *	move it to the head of the chain.
197 			 */
198 			top->count++;
199 			toindex = prevtop->link;
200 			prevtop->link = top->link;
201 			top->link = *frompcindex;
202 			*frompcindex = toindex;
203 			goto done;
204 		}
205 
206 	}
207 done:
208 	profiling--;
209 	/* and fall through */
210 out:
211 	asm("	rsb");
212 
213 overflow:
214 	profiling = 3;
215 	printf("mcount: tos overflow\n");
216 	goto out;
217 }
218 asm(".text");
219 asm("#the end of mcount()");
220 asm(".data");
221 #endif vax
222 #endif GPROF
223