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