123380Smckusick /* 229100Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 323380Smckusick * All rights reserved. The Berkeley software License Agreement 423380Smckusick * specifies the terms and conditions for redistribution. 523380Smckusick * 6*29946Skarels * @(#)subr_prof.c 7.2 (Berkeley) 11/03/86 723380Smckusick */ 87332Ssam 97332Ssam #ifdef GPROF 1017094Sbloom #include "gprof.h" 1117094Sbloom #include "param.h" 1217094Sbloom #include "systm.h" 137332Ssam 147332Ssam /* 157332Ssam * Froms is actually a bunch of unsigned shorts indexing tos 167332Ssam */ 17*29946Skarels int profiling = 3; 18*29946Skarels u_short *froms; 19*29946Skarels struct tostruct *tos = 0; 20*29946Skarels long tolimit = 0; 21*29946Skarels #if defined(vax) 227332Ssam char *s_lowpc = (char *)0x80000000; 239758Ssam #endif 24*29946Skarels #if defined(tahoe) 25*29946Skarels char *s_lowpc = (char *)0xc0000000; 26*29946Skarels #endif 27*29946Skarels extern char etext; 28*29946Skarels char *s_highpc = &etext; 297332Ssam u_long s_textsize = 0; 30*29946Skarels int ssiz; 317332Ssam u_short *sbuf; 327332Ssam u_short *kcount; 337332Ssam 347332Ssam kmstartup() 357332Ssam { 36*29946Skarels u_long fromssize, tossize; 377332Ssam 3810292Smckusick /* 39*29946Skarels * Round lowpc and highpc to multiples of the density we're using 40*29946Skarels * so the rest of the scaling (here and in gprof) stays in ints. 4110292Smckusick */ 4210292Smckusick s_lowpc = (char *) 43*29946Skarels ROUNDDOWN((unsigned)s_lowpc, HISTFRACTION*sizeof (HISTCOUNTER)); 4410292Smckusick s_highpc = (char *) 45*29946Skarels ROUNDUP((unsigned)s_highpc, HISTFRACTION*sizeof (HISTCOUNTER)); 467332Ssam s_textsize = s_highpc - s_lowpc; 477332Ssam printf("Profiling kernel, s_textsize=%d [%x..%x]\n", 487332Ssam s_textsize, s_lowpc, s_highpc); 49*29946Skarels ssiz = (s_textsize / HISTFRACTION) + sizeof (struct phdr); 5016781Smckusick sbuf = (u_short *)calloc(ssiz); 517332Ssam if (sbuf == 0) { 527332Ssam printf("No space for monitor buffer(s)\n"); 537332Ssam return; 547332Ssam } 5510292Smckusick fromssize = s_textsize / HASHFRACTION; 5616781Smckusick froms = (u_short *)calloc(fromssize); 577332Ssam if (froms == 0) { 587332Ssam printf("No space for monitor buffer(s)\n"); 5916781Smckusick cfreemem(sbuf, ssiz); 607332Ssam sbuf = 0; 617332Ssam return; 627332Ssam } 6310292Smckusick tolimit = s_textsize * ARCDENSITY / 100; 64*29946Skarels if (tolimit < MINARCS) 6510292Smckusick tolimit = MINARCS; 66*29946Skarels else if (tolimit > (0xffff - 1)) 67*29946Skarels tolimit = 0xffff - 1; 68*29946Skarels tossize = tolimit * sizeof (struct tostruct); 6916781Smckusick tos = (struct tostruct *)calloc(tossize); 707332Ssam if (tos == 0) { 717332Ssam printf("No space for monitor buffer(s)\n"); 72*29946Skarels cfreemem(sbuf, ssiz), sbuf = 0; 73*29946Skarels cfreemem(froms, fromssize), froms = 0; 747332Ssam return; 757332Ssam } 767332Ssam tos[0].link = 0; 777332Ssam ((struct phdr *)sbuf)->lpc = s_lowpc; 787332Ssam ((struct phdr *)sbuf)->hpc = s_highpc; 797332Ssam ((struct phdr *)sbuf)->ncnt = ssiz; 80*29946Skarels kcount = (u_short *)(((int)sbuf) + sizeof (struct phdr)); 817332Ssam #ifdef notdef 8210292Smckusick /* 83*29946Skarels * Profiling is what mcount checks to see if 84*29946Skarels * all the data structures are ready!!! 8510292Smckusick */ 867332Ssam profiling = 0; /* patch by hand when you're ready */ 877332Ssam #endif 887332Ssam } 897332Ssam 907332Ssam /* 91*29946Skarels * This routine is massaged so that it may be jsb'ed to on vax. 927332Ssam */ 9310292Smckusick asm(".text"); 9410292Smckusick asm("#the beginning of mcount()"); 9510292Smckusick asm(".data"); 967332Ssam mcount() 977332Ssam { 98*29946Skarels register char *selfpc; /* r11 => r5 */ 99*29946Skarels register u_short *frompcindex; /* r10 => r4 */ 100*29946Skarels register struct tostruct *top; /* r9 => r3 */ 101*29946Skarels register struct tostruct *prevtop; /* r8 => r2 */ 102*29946Skarels register long toindex; /* r7 => r1 */ 10316924Smckusick static int s; 1047332Ssam 105*29946Skarels asm(" .text"); /* make sure we're in text space */ 106*29946Skarels /* 107*29946Skarels * Check that we are profiling. 108*29946Skarels */ 109*29946Skarels if (profiling) 110*29946Skarels goto out; 111*29946Skarels /* 112*29946Skarels * Find the return address for mcount, 113*29946Skarels * and the return address for mcount's caller. 114*29946Skarels */ 1157332Ssam #ifdef lint 11610292Smckusick selfpc = (char *)0; 1177332Ssam frompcindex = 0; 118*29946Skarels #else 119*29946Skarels #if defined(vax) 1207332Ssam asm(" movl (sp), r11"); /* selfpc = ... (jsb frame) */ 1217332Ssam asm(" movl 16(fp), r10"); /* frompcindex = (calls frame) */ 122*29946Skarels #endif 123*29946Skarels #if defined(tahoe) 124*29946Skarels ; /* avoid label botch */ 125*29946Skarels asm(" movl -8(fp),r12"); /* selfpc = callf frame */ 126*29946Skarels asm(" movl (fp),r11"); 127*29946Skarels asm(" movl -8(r11),r11"); /* frompcindex = 1 callf frame back */ 128*29946Skarels #endif 129*29946Skarels #endif 1307332Ssam /* 131*29946Skarels * Insure that we cannot be recursively invoked. 132*29946Skarels * this requires that splhigh() and splx() below 133*29946Skarels * do NOT call mcount! 1347332Ssam */ 13516924Smckusick s = splhigh(); 13616924Smckusick /* 137*29946Skarels * Check that frompcindex is a reasonable pc value. 138*29946Skarels * For example: signal catchers get called from the stack, 139*29946Skarels * not from text space. too bad. 1407332Ssam */ 141*29946Skarels frompcindex = (u_short *)((long)frompcindex - (long)s_lowpc); 142*29946Skarels if ((u_long)frompcindex > s_textsize) 1437332Ssam goto done; 14410292Smckusick frompcindex = 145*29946Skarels &froms[((long)frompcindex) / (HASHFRACTION * sizeof (*froms))]; 14610292Smckusick toindex = *frompcindex; 14710292Smckusick if (toindex == 0) { 14810292Smckusick /* 149*29946Skarels * First time traversing this arc 15010292Smckusick */ 15110292Smckusick toindex = ++tos[0].link; 152*29946Skarels if (toindex >= tolimit) 1537332Ssam goto overflow; 15410292Smckusick *frompcindex = toindex; 15510292Smckusick top = &tos[toindex]; 1567332Ssam top->selfpc = selfpc; 15710292Smckusick top->count = 1; 1587332Ssam top->link = 0; 15910292Smckusick goto done; 1607332Ssam } 16110292Smckusick top = &tos[toindex]; 16210292Smckusick if (top->selfpc == selfpc) { 16310292Smckusick /* 164*29946Skarels * Arc at front of chain; usual case. 16510292Smckusick */ 16610292Smckusick top->count++; 16710292Smckusick goto done; 16810292Smckusick } 16910292Smckusick /* 170*29946Skarels * Have to go looking down chain for it. 171*29946Skarels * Top points to what we are looking at, 172*29946Skarels * prevtop points to previous top. 173*29946Skarels * We know it is not at the head of the chain. 17410292Smckusick */ 17510292Smckusick for (; /* goto done */; ) { 17610292Smckusick if (top->link == 0) { 17710292Smckusick /* 178*29946Skarels * Top is end of the chain and none of the chain 179*29946Skarels * had top->selfpc == selfpc. 180*29946Skarels * So we allocate a new tostruct 181*29946Skarels * and link it to the head of the chain. 18210292Smckusick */ 18310292Smckusick toindex = ++tos[0].link; 184*29946Skarels if (toindex >= tolimit) 18510292Smckusick goto overflow; 18610292Smckusick top = &tos[toindex]; 18710292Smckusick top->selfpc = selfpc; 18810292Smckusick top->count = 1; 18910292Smckusick top->link = *frompcindex; 19010292Smckusick *frompcindex = toindex; 19110292Smckusick goto done; 19210292Smckusick } 19310292Smckusick /* 194*29946Skarels * Otherwise, check the next arc on the chain. 19510292Smckusick */ 19610292Smckusick prevtop = top; 19710292Smckusick top = &tos[top->link]; 1987332Ssam if (top->selfpc == selfpc) { 19910292Smckusick /* 200*29946Skarels * There it is, increment its count and 201*29946Skarels * move it to the head of the chain. 20210292Smckusick */ 2037332Ssam top->count++; 20410292Smckusick toindex = prevtop->link; 20510292Smckusick prevtop->link = top->link; 20610292Smckusick top->link = *frompcindex; 20710292Smckusick *frompcindex = toindex; 20810292Smckusick goto done; 2097332Ssam } 21010292Smckusick 2117332Ssam } 2127332Ssam done: 21316924Smckusick splx(s); 2147332Ssam /* and fall through */ 2157332Ssam out: 216*29946Skarels #if defined(vax) 2177332Ssam asm(" rsb"); 218*29946Skarels #endif 219*29946Skarels return; 2207332Ssam overflow: 22110292Smckusick profiling = 3; 2227332Ssam printf("mcount: tos overflow\n"); 2237332Ssam goto out; 2247332Ssam } 22510292Smckusick asm(".text"); 22610292Smckusick asm("#the end of mcount()"); 22710292Smckusick asm(".data"); 228*29946Skarels #endif 229