Commit | Line | Data |
---|---|---|
08621963 KM |
1 | /* subr_prof.c 4.4 83/01/15 */ |
2 | ||
3 | /* last integrated from: gmon.c 4.10 (Berkeley) 1/14/83 */ | |
3a3e0b91 SL |
4 | |
5 | #ifdef GPROF | |
08621963 | 6 | #include "../h/gprof.h" |
3a3e0b91 SL |
7 | #include "../h/param.h" |
8 | #include "../h/systm.h" | |
9 | ||
10 | /* | |
11 | * Froms is actually a bunch of unsigned shorts indexing tos | |
12 | */ | |
08621963 KM |
13 | int profiling = 3; |
14 | u_short *froms; | |
15 | struct tostruct *tos = 0; | |
16 | long tolimit = 0; | |
961945a8 | 17 | #ifdef vax |
3a3e0b91 | 18 | char *s_lowpc = (char *)0x80000000; |
961945a8 SL |
19 | #endif |
20 | #ifdef sun | |
21 | char *s_lowpc = (char *)0x4000; | |
22 | #endif | |
08621963 KM |
23 | extern char etext; |
24 | char *s_highpc = &etext; | |
3a3e0b91 | 25 | u_long s_textsize = 0; |
08621963 | 26 | int ssiz; |
3a3e0b91 SL |
27 | u_short *sbuf; |
28 | u_short *kcount; | |
29 | ||
30 | kmstartup() | |
31 | { | |
08621963 | 32 | u_long fromssize, tossize; |
3a3e0b91 | 33 | |
08621963 KM |
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)); | |
3a3e0b91 | 42 | s_textsize = s_highpc - s_lowpc; |
3a3e0b91 SL |
43 | printf("Profiling kernel, s_textsize=%d [%x..%x]\n", |
44 | s_textsize, s_lowpc, s_highpc); | |
08621963 | 45 | ssiz = (s_textsize / HISTFRACTION) + sizeof(struct phdr); |
4f083fd7 | 46 | sbuf = (u_short *)wmemall(memall, ssiz); |
3a3e0b91 SL |
47 | if (sbuf == 0) { |
48 | printf("No space for monitor buffer(s)\n"); | |
49 | return; | |
50 | } | |
51 | blkclr((caddr_t)sbuf, ssiz); | |
08621963 KM |
52 | fromssize = s_textsize / HASHFRACTION; |
53 | froms = (u_short *)wmemall(memall, fromssize); | |
3a3e0b91 SL |
54 | if (froms == 0) { |
55 | printf("No space for monitor buffer(s)\n"); | |
56 | wmemfree(sbuf, ssiz); | |
57 | sbuf = 0; | |
58 | return; | |
59 | } | |
08621963 KM |
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); | |
3a3e0b91 SL |
69 | if (tos == 0) { |
70 | printf("No space for monitor buffer(s)\n"); | |
71 | wmemfree(sbuf, ssiz); | |
72 | sbuf = 0; | |
08621963 | 73 | wmemfree(froms, fromssize); |
3a3e0b91 SL |
74 | froms = 0; |
75 | return; | |
76 | } | |
08621963 | 77 | blkclr((caddr_t)tos, tossize); |
3a3e0b91 | 78 | tos[0].link = 0; |
3a3e0b91 SL |
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 | |
08621963 KM |
84 | /* |
85 | * profiling is what mcount checks to see if | |
86 | * all the data structures are ready!!! | |
87 | */ | |
3a3e0b91 SL |
88 | profiling = 0; /* patch by hand when you're ready */ |
89 | #endif | |
90 | } | |
91 | ||
961945a8 | 92 | #ifdef vax |
3a3e0b91 SL |
93 | /* |
94 | * This routine is massaged so that it may be jsb'ed to | |
95 | */ | |
08621963 KM |
96 | asm(".text"); |
97 | asm("#the beginning of mcount()"); | |
98 | asm(".data"); | |
3a3e0b91 SL |
99 | mcount() |
100 | { | |
08621963 KM |
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 */ | |
3a3e0b91 | 106 | |
3a3e0b91 | 107 | #ifdef lint |
08621963 | 108 | selfpc = (char *)0; |
3a3e0b91 SL |
109 | frompcindex = 0; |
110 | #else not lint | |
111 | /* | |
08621963 KM |
112 | * find the return address for mcount, |
113 | * and the return address for mcount's caller. | |
3a3e0b91 | 114 | */ |
08621963 | 115 | asm(" .text"); /* make sure we're in text space */ |
3a3e0b91 SL |
116 | asm(" movl (sp), r11"); /* selfpc = ... (jsb frame) */ |
117 | asm(" movl 16(fp), r10"); /* frompcindex = (calls frame) */ | |
118 | #endif not lint | |
119 | /* | |
08621963 KM |
120 | * check that we are profiling |
121 | * and that we aren't recursively invoked. | |
3a3e0b91 | 122 | */ |
08621963 | 123 | if (profiling) { |
3a3e0b91 | 124 | goto out; |
08621963 | 125 | } |
3a3e0b91 SL |
126 | profiling++; |
127 | /* | |
08621963 KM |
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. | |
3a3e0b91 | 131 | */ |
08621963 KM |
132 | frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc); |
133 | if ((unsigned long)frompcindex > s_textsize) { | |
3a3e0b91 | 134 | goto done; |
08621963 KM |
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) { | |
3a3e0b91 | 145 | goto overflow; |
08621963 KM |
146 | } |
147 | *frompcindex = toindex; | |
148 | top = &tos[toindex]; | |
3a3e0b91 | 149 | top->selfpc = selfpc; |
08621963 | 150 | top->count = 1; |
3a3e0b91 | 151 | top->link = 0; |
08621963 | 152 | goto done; |
3a3e0b91 | 153 | } |
08621963 KM |
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]; | |
3a3e0b91 | 192 | if (top->selfpc == selfpc) { |
08621963 KM |
193 | /* |
194 | * there it is. | |
195 | * increment its count | |
196 | * move it to the head of the chain. | |
197 | */ | |
3a3e0b91 | 198 | top->count++; |
08621963 KM |
199 | toindex = prevtop->link; |
200 | prevtop->link = top->link; | |
201 | top->link = *frompcindex; | |
202 | *frompcindex = toindex; | |
203 | goto done; | |
3a3e0b91 | 204 | } |
08621963 | 205 | |
3a3e0b91 SL |
206 | } |
207 | done: | |
208 | profiling--; | |
209 | /* and fall through */ | |
210 | out: | |
211 | asm(" rsb"); | |
3a3e0b91 SL |
212 | |
213 | overflow: | |
08621963 | 214 | profiling = 3; |
3a3e0b91 SL |
215 | printf("mcount: tos overflow\n"); |
216 | goto out; | |
217 | } | |
08621963 KM |
218 | asm(".text"); |
219 | asm("#the end of mcount()"); | |
220 | asm(".data"); | |
221 | #endif vax | |
3a3e0b91 | 222 | #endif GPROF |