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 | * | |
0880b18e | 6 | * @(#)subr_prof.c 7.1 (Berkeley) %G% |
da7c5cc6 | 7 | */ |
08621963 KM |
8 | |
9 | /* last integrated from: gmon.c 4.10 (Berkeley) 1/14/83 */ | |
3a3e0b91 SL |
10 | |
11 | #ifdef GPROF | |
94368568 JB |
12 | #include "gprof.h" |
13 | #include "param.h" | |
14 | #include "systm.h" | |
3a3e0b91 SL |
15 | |
16 | /* | |
17 | * Froms is actually a bunch of unsigned shorts indexing tos | |
18 | */ | |
08621963 KM |
19 | int profiling = 3; |
20 | u_short *froms; | |
21 | struct tostruct *tos = 0; | |
22 | long tolimit = 0; | |
961945a8 | 23 | #ifdef vax |
3a3e0b91 | 24 | char *s_lowpc = (char *)0x80000000; |
961945a8 | 25 | #endif |
08621963 KM |
26 | extern char etext; |
27 | char *s_highpc = &etext; | |
3a3e0b91 | 28 | u_long s_textsize = 0; |
08621963 | 29 | int ssiz; |
3a3e0b91 SL |
30 | u_short *sbuf; |
31 | u_short *kcount; | |
32 | ||
33 | kmstartup() | |
34 | { | |
08621963 | 35 | u_long fromssize, tossize; |
3a3e0b91 | 36 | |
08621963 KM |
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)); | |
3a3e0b91 | 45 | s_textsize = s_highpc - s_lowpc; |
3a3e0b91 SL |
46 | printf("Profiling kernel, s_textsize=%d [%x..%x]\n", |
47 | s_textsize, s_lowpc, s_highpc); | |
08621963 | 48 | ssiz = (s_textsize / HISTFRACTION) + sizeof(struct phdr); |
44a388b8 | 49 | sbuf = (u_short *)calloc(ssiz); |
3a3e0b91 SL |
50 | if (sbuf == 0) { |
51 | printf("No space for monitor buffer(s)\n"); | |
52 | return; | |
53 | } | |
54 | blkclr((caddr_t)sbuf, ssiz); | |
08621963 | 55 | fromssize = s_textsize / HASHFRACTION; |
44a388b8 | 56 | froms = (u_short *)calloc(fromssize); |
3a3e0b91 SL |
57 | if (froms == 0) { |
58 | printf("No space for monitor buffer(s)\n"); | |
44a388b8 | 59 | cfreemem(sbuf, ssiz); |
3a3e0b91 SL |
60 | sbuf = 0; |
61 | return; | |
62 | } | |
08621963 KM |
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); | |
44a388b8 | 71 | tos = (struct tostruct *)calloc(tossize); |
3a3e0b91 SL |
72 | if (tos == 0) { |
73 | printf("No space for monitor buffer(s)\n"); | |
44a388b8 | 74 | cfreemem(sbuf, ssiz); |
3a3e0b91 | 75 | sbuf = 0; |
44a388b8 | 76 | cfreemem(froms, fromssize); |
3a3e0b91 SL |
77 | froms = 0; |
78 | return; | |
79 | } | |
08621963 | 80 | blkclr((caddr_t)tos, tossize); |
3a3e0b91 | 81 | tos[0].link = 0; |
3a3e0b91 SL |
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 | |
08621963 KM |
87 | /* |
88 | * profiling is what mcount checks to see if | |
89 | * all the data structures are ready!!! | |
90 | */ | |
3a3e0b91 SL |
91 | profiling = 0; /* patch by hand when you're ready */ |
92 | #endif | |
93 | } | |
94 | ||
961945a8 | 95 | #ifdef vax |
3a3e0b91 SL |
96 | /* |
97 | * This routine is massaged so that it may be jsb'ed to | |
98 | */ | |
08621963 KM |
99 | asm(".text"); |
100 | asm("#the beginning of mcount()"); | |
101 | asm(".data"); | |
3a3e0b91 SL |
102 | mcount() |
103 | { | |
08621963 KM |
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 */ | |
31e126ae | 109 | static int s; |
3a3e0b91 | 110 | |
3a3e0b91 | 111 | #ifdef lint |
08621963 | 112 | selfpc = (char *)0; |
3a3e0b91 SL |
113 | frompcindex = 0; |
114 | #else not lint | |
115 | /* | |
08621963 KM |
116 | * find the return address for mcount, |
117 | * and the return address for mcount's caller. | |
3a3e0b91 | 118 | */ |
08621963 | 119 | asm(" .text"); /* make sure we're in text space */ |
3a3e0b91 SL |
120 | asm(" movl (sp), r11"); /* selfpc = ... (jsb frame) */ |
121 | asm(" movl 16(fp), r10"); /* frompcindex = (calls frame) */ | |
122 | #endif not lint | |
123 | /* | |
08621963 | 124 | * check that we are profiling |
3a3e0b91 | 125 | */ |
08621963 | 126 | if (profiling) { |
3a3e0b91 | 127 | goto out; |
08621963 | 128 | } |
31e126ae KM |
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(); | |
3a3e0b91 | 135 | /* |
08621963 KM |
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. | |
3a3e0b91 | 139 | */ |
08621963 KM |
140 | frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc); |
141 | if ((unsigned long)frompcindex > s_textsize) { | |
3a3e0b91 | 142 | goto done; |
08621963 KM |
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) { | |
3a3e0b91 | 153 | goto overflow; |
08621963 KM |
154 | } |
155 | *frompcindex = toindex; | |
156 | top = &tos[toindex]; | |
3a3e0b91 | 157 | top->selfpc = selfpc; |
08621963 | 158 | top->count = 1; |
3a3e0b91 | 159 | top->link = 0; |
08621963 | 160 | goto done; |
3a3e0b91 | 161 | } |
08621963 KM |
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]; | |
3a3e0b91 | 200 | if (top->selfpc == selfpc) { |
08621963 KM |
201 | /* |
202 | * there it is. | |
203 | * increment its count | |
204 | * move it to the head of the chain. | |
205 | */ | |
3a3e0b91 | 206 | top->count++; |
08621963 KM |
207 | toindex = prevtop->link; |
208 | prevtop->link = top->link; | |
209 | top->link = *frompcindex; | |
210 | *frompcindex = toindex; | |
211 | goto done; | |
3a3e0b91 | 212 | } |
08621963 | 213 | |
3a3e0b91 SL |
214 | } |
215 | done: | |
31e126ae | 216 | splx(s); |
3a3e0b91 SL |
217 | /* and fall through */ |
218 | out: | |
219 | asm(" rsb"); | |
3a3e0b91 SL |
220 | |
221 | overflow: | |
08621963 | 222 | profiling = 3; |
3a3e0b91 SL |
223 | printf("mcount: tos overflow\n"); |
224 | goto out; | |
225 | } | |
08621963 KM |
226 | asm(".text"); |
227 | asm("#the end of mcount()"); | |
228 | asm(".data"); | |
229 | #endif vax | |
3a3e0b91 | 230 | #endif GPROF |