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