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.4 (Berkeley) 07/21/87 7 */ 8 9 #ifdef GPROF 10 #include "gprof.h" 11 #include "param.h" 12 #include "systm.h" 13 #include "malloc.h" 14 15 /* 16 * Froms is actually a bunch of unsigned shorts indexing tos 17 */ 18 int profiling = 3; 19 u_short *froms; 20 struct tostruct *tos = 0; 21 long tolimit = 0; 22 #if defined(vax) 23 char *s_lowpc = (char *)0x80000000; 24 #endif 25 #if defined(tahoe) 26 char *s_lowpc = (char *)0xc0000000; 27 #endif 28 extern char etext; 29 char *s_highpc = &etext; 30 u_long s_textsize = 0; 31 int ssiz; 32 u_short *sbuf; 33 u_short *kcount; 34 35 kmstartup() 36 { 37 u_long fromssize, tossize; 38 39 /* 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. 42 */ 43 s_lowpc = (char *) 44 ROUNDDOWN((unsigned)s_lowpc, HISTFRACTION*sizeof (HISTCOUNTER)); 45 s_highpc = (char *) 46 ROUNDUP((unsigned)s_highpc, HISTFRACTION*sizeof (HISTCOUNTER)); 47 s_textsize = s_highpc - s_lowpc; 48 printf("Profiling kernel, s_textsize=%d [%x..%x]\n", 49 s_textsize, s_lowpc, s_highpc); 50 ssiz = (s_textsize / HISTFRACTION) + sizeof (struct phdr); 51 sbuf = (u_short *)malloc(ssiz, M_GPROF, M_WAITOK); 52 if (sbuf == 0) { 53 printf("No space for monitor buffer(s)\n"); 54 return; 55 } 56 bzero(sbuf, ssiz); 57 fromssize = s_textsize / HASHFRACTION; 58 froms = (u_short *)malloc(fromssize, M_GPROF, M_WAITOK); 59 if (froms == 0) { 60 printf("No space for monitor buffer(s)\n"); 61 free(sbuf, M_GPROF); 62 sbuf = 0; 63 return; 64 } 65 bzero(froms, fromsize); 66 tolimit = s_textsize * ARCDENSITY / 100; 67 if (tolimit < MINARCS) 68 tolimit = MINARCS; 69 else if (tolimit > (0xffff - 1)) 70 tolimit = 0xffff - 1; 71 tossize = tolimit * sizeof (struct tostruct); 72 tos = (struct tostruct *)malloc(tossize, M_GPROF, M_WAITOK); 73 if (tos == 0) { 74 printf("No space for monitor buffer(s)\n"); 75 free(sbuf, M_GPROF), sbuf = 0; 76 free(froms, M_GPROF), froms = 0; 77 return; 78 } 79 bzero(tos, tossize); 80 tos[0].link = 0; 81 ((struct phdr *)sbuf)->lpc = s_lowpc; 82 ((struct phdr *)sbuf)->hpc = s_highpc; 83 ((struct phdr *)sbuf)->ncnt = ssiz; 84 kcount = (u_short *)(((int)sbuf) + sizeof (struct phdr)); 85 #ifdef notdef 86 /* 87 * Profiling is what mcount checks to see if 88 * all the data structures are ready!!! 89 */ 90 profiling = 0; /* patch by hand when you're ready */ 91 #endif 92 } 93 94 /* 95 * This routine is massaged so that it may be jsb'ed to on vax. 96 */ 97 asm(".text"); 98 asm("#the beginning of mcount()"); 99 asm(".data"); 100 mcount() 101 { 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 */ 107 static int s; 108 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 */ 119 #ifdef lint 120 selfpc = (char *)0; 121 frompcindex = 0; 122 #else 123 #if defined(vax) 124 asm(" movl (sp), r11"); /* selfpc = ... (jsb frame) */ 125 asm(" movl 16(fp), r10"); /* frompcindex = (calls frame) */ 126 #endif 127 #if defined(tahoe) 128 ; /* avoid label botch */ 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 134 /* 135 * Insure that we cannot be recursively invoked. 136 * this requires that splhigh() and splx() below 137 * do NOT call mcount! 138 */ 139 s = splhigh(); 140 /* 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. 144 */ 145 frompcindex = (u_short *)((long)frompcindex - (long)s_lowpc); 146 if ((u_long)frompcindex > s_textsize) 147 goto done; 148 frompcindex = 149 &froms[((long)frompcindex) / (HASHFRACTION * sizeof (*froms))]; 150 toindex = *frompcindex; 151 if (toindex == 0) { 152 /* 153 * First time traversing this arc 154 */ 155 toindex = ++tos[0].link; 156 if (toindex >= tolimit) 157 goto overflow; 158 *frompcindex = toindex; 159 top = &tos[toindex]; 160 top->selfpc = selfpc; 161 top->count = 1; 162 top->link = 0; 163 goto done; 164 } 165 top = &tos[toindex]; 166 if (top->selfpc == selfpc) { 167 /* 168 * Arc at front of chain; usual case. 169 */ 170 top->count++; 171 goto done; 172 } 173 /* 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. 178 */ 179 for (; /* goto done */; ) { 180 if (top->link == 0) { 181 /* 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. 186 */ 187 toindex = ++tos[0].link; 188 if (toindex >= tolimit) 189 goto overflow; 190 top = &tos[toindex]; 191 top->selfpc = selfpc; 192 top->count = 1; 193 top->link = *frompcindex; 194 *frompcindex = toindex; 195 goto done; 196 } 197 /* 198 * Otherwise, check the next arc on the chain. 199 */ 200 prevtop = top; 201 top = &tos[top->link]; 202 if (top->selfpc == selfpc) { 203 /* 204 * There it is, increment its count and 205 * move it to the head of the chain. 206 */ 207 top->count++; 208 toindex = prevtop->link; 209 prevtop->link = top->link; 210 top->link = *frompcindex; 211 *frompcindex = toindex; 212 goto done; 213 } 214 215 } 216 done: 217 splx(s); 218 /* and fall through */ 219 out: 220 #if defined(vax) 221 asm(" rsb"); 222 #endif 223 return; 224 overflow: 225 profiling = 3; 226 printf("mcount: tos overflow\n"); 227 goto out; 228 } 229 asm(".text"); 230 asm("#the end of mcount()"); 231 asm(".data"); 232 #endif 233