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