123380Smckusick /* 2*29100Smckusick * 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*29100Smckusick * @(#)subr_prof.c 7.1 (Berkeley) 06/05/86 723380Smckusick */ 87332Ssam 910292Smckusick /* last integrated from: gmon.c 4.10 (Berkeley) 1/14/83 */ 1010292Smckusick 117332Ssam #ifdef GPROF 1217094Sbloom #include "gprof.h" 1317094Sbloom #include "param.h" 1417094Sbloom #include "systm.h" 157332Ssam 167332Ssam /* 177332Ssam * Froms is actually a bunch of unsigned shorts indexing tos 187332Ssam */ 1910292Smckusick int profiling = 3; 2010292Smckusick u_short *froms; 2110292Smckusick struct tostruct *tos = 0; 2210292Smckusick long tolimit = 0; 239758Ssam #ifdef vax 247332Ssam char *s_lowpc = (char *)0x80000000; 259758Ssam #endif 2610292Smckusick extern char etext; 2710292Smckusick char *s_highpc = &etext; 287332Ssam u_long s_textsize = 0; 2910292Smckusick int ssiz; 307332Ssam u_short *sbuf; 317332Ssam u_short *kcount; 327332Ssam 337332Ssam kmstartup() 347332Ssam { 3510292Smckusick u_long fromssize, tossize; 367332Ssam 3710292Smckusick /* 3810292Smckusick * round lowpc and highpc to multiples of the density we're using 3910292Smckusick * so the rest of the scaling (here and in gprof) stays in ints. 4010292Smckusick */ 4110292Smckusick s_lowpc = (char *) 4210292Smckusick ROUNDDOWN((unsigned)s_lowpc, HISTFRACTION*sizeof(HISTCOUNTER)); 4310292Smckusick s_highpc = (char *) 4410292Smckusick ROUNDUP((unsigned)s_highpc, HISTFRACTION*sizeof(HISTCOUNTER)); 457332Ssam s_textsize = s_highpc - s_lowpc; 467332Ssam printf("Profiling kernel, s_textsize=%d [%x..%x]\n", 477332Ssam s_textsize, s_lowpc, s_highpc); 4810292Smckusick ssiz = (s_textsize / HISTFRACTION) + sizeof(struct phdr); 4916781Smckusick sbuf = (u_short *)calloc(ssiz); 507332Ssam if (sbuf == 0) { 517332Ssam printf("No space for monitor buffer(s)\n"); 527332Ssam return; 537332Ssam } 547332Ssam blkclr((caddr_t)sbuf, ssiz); 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 blkclr((caddr_t)froms, fromssize); 6410292Smckusick tolimit = s_textsize * ARCDENSITY / 100; 6510292Smckusick if (tolimit < MINARCS) { 6610292Smckusick tolimit = MINARCS; 6710292Smckusick } else if (tolimit > 65534) { 6810292Smckusick tolimit = 65534; 6910292Smckusick } 7010292Smckusick tossize = tolimit * sizeof(struct tostruct); 7116781Smckusick tos = (struct tostruct *)calloc(tossize); 727332Ssam if (tos == 0) { 737332Ssam printf("No space for monitor buffer(s)\n"); 7416781Smckusick cfreemem(sbuf, ssiz); 757332Ssam sbuf = 0; 7616781Smckusick cfreemem(froms, fromssize); 777332Ssam froms = 0; 787332Ssam return; 797332Ssam } 8010292Smckusick blkclr((caddr_t)tos, tossize); 817332Ssam tos[0].link = 0; 827332Ssam ((struct phdr *)sbuf)->lpc = s_lowpc; 837332Ssam ((struct phdr *)sbuf)->hpc = s_highpc; 847332Ssam ((struct phdr *)sbuf)->ncnt = ssiz; 857332Ssam kcount = (u_short *)(((int)sbuf) + sizeof(struct phdr)); 867332Ssam #ifdef notdef 8710292Smckusick /* 8810292Smckusick * profiling is what mcount checks to see if 8910292Smckusick * all the data structures are ready!!! 9010292Smckusick */ 917332Ssam profiling = 0; /* patch by hand when you're ready */ 927332Ssam #endif 937332Ssam } 947332Ssam 959758Ssam #ifdef vax 967332Ssam /* 977332Ssam * This routine is massaged so that it may be jsb'ed to 987332Ssam */ 9910292Smckusick asm(".text"); 10010292Smckusick asm("#the beginning of mcount()"); 10110292Smckusick asm(".data"); 1027332Ssam mcount() 1037332Ssam { 10410292Smckusick register char *selfpc; /* r11 => r5 */ 10510292Smckusick register unsigned short *frompcindex; /* r10 => r4 */ 10610292Smckusick register struct tostruct *top; /* r9 => r3 */ 10710292Smckusick register struct tostruct *prevtop; /* r8 => r2 */ 10810292Smckusick register long toindex; /* r7 => r1 */ 10916924Smckusick static int s; 1107332Ssam 1117332Ssam #ifdef lint 11210292Smckusick selfpc = (char *)0; 1137332Ssam frompcindex = 0; 1147332Ssam #else not lint 1157332Ssam /* 11610292Smckusick * find the return address for mcount, 11710292Smckusick * and the return address for mcount's caller. 1187332Ssam */ 11910292Smckusick asm(" .text"); /* make sure we're in text space */ 1207332Ssam asm(" movl (sp), r11"); /* selfpc = ... (jsb frame) */ 1217332Ssam asm(" movl 16(fp), r10"); /* frompcindex = (calls frame) */ 1227332Ssam #endif not lint 1237332Ssam /* 12410292Smckusick * check that we are profiling 1257332Ssam */ 12610292Smckusick if (profiling) { 1277332Ssam goto out; 12810292Smckusick } 1297332Ssam /* 13016924Smckusick * insure that we cannot be recursively invoked. 13116924Smckusick * this requires that splhigh() and splx() below 13216924Smckusick * do NOT call mcount! 13316924Smckusick */ 13416924Smckusick s = splhigh(); 13516924Smckusick /* 13610292Smckusick * check that frompcindex is a reasonable pc value. 13710292Smckusick * for example: signal catchers get called from the stack, 13810292Smckusick * not from text space. too bad. 1397332Ssam */ 14010292Smckusick frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc); 14110292Smckusick if ((unsigned long)frompcindex > s_textsize) { 1427332Ssam goto done; 14310292Smckusick } 14410292Smckusick frompcindex = 14510292Smckusick &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))]; 14610292Smckusick toindex = *frompcindex; 14710292Smckusick if (toindex == 0) { 14810292Smckusick /* 14910292Smckusick * first time traversing this arc 15010292Smckusick */ 15110292Smckusick toindex = ++tos[0].link; 15210292Smckusick if (toindex >= tolimit) { 1537332Ssam goto overflow; 15410292Smckusick } 15510292Smckusick *frompcindex = toindex; 15610292Smckusick top = &tos[toindex]; 1577332Ssam top->selfpc = selfpc; 15810292Smckusick top->count = 1; 1597332Ssam top->link = 0; 16010292Smckusick goto done; 1617332Ssam } 16210292Smckusick top = &tos[toindex]; 16310292Smckusick if (top->selfpc == selfpc) { 16410292Smckusick /* 16510292Smckusick * arc at front of chain; usual case. 16610292Smckusick */ 16710292Smckusick top->count++; 16810292Smckusick goto done; 16910292Smckusick } 17010292Smckusick /* 17110292Smckusick * have to go looking down chain for it. 17210292Smckusick * top points to what we are looking at, 17310292Smckusick * prevtop points to previous top. 17410292Smckusick * we know it is not at the head of the chain. 17510292Smckusick */ 17610292Smckusick for (; /* goto done */; ) { 17710292Smckusick if (top->link == 0) { 17810292Smckusick /* 17910292Smckusick * top is end of the chain and none of the chain 18010292Smckusick * had top->selfpc == selfpc. 18110292Smckusick * so we allocate a new tostruct 18210292Smckusick * and link it to the head of the chain. 18310292Smckusick */ 18410292Smckusick toindex = ++tos[0].link; 18510292Smckusick if (toindex >= tolimit) { 18610292Smckusick goto overflow; 18710292Smckusick } 18810292Smckusick top = &tos[toindex]; 18910292Smckusick top->selfpc = selfpc; 19010292Smckusick top->count = 1; 19110292Smckusick top->link = *frompcindex; 19210292Smckusick *frompcindex = toindex; 19310292Smckusick goto done; 19410292Smckusick } 19510292Smckusick /* 19610292Smckusick * otherwise, check the next arc on the chain. 19710292Smckusick */ 19810292Smckusick prevtop = top; 19910292Smckusick top = &tos[top->link]; 2007332Ssam if (top->selfpc == selfpc) { 20110292Smckusick /* 20210292Smckusick * there it is. 20310292Smckusick * increment its count 20410292Smckusick * move it to the head of the chain. 20510292Smckusick */ 2067332Ssam top->count++; 20710292Smckusick toindex = prevtop->link; 20810292Smckusick prevtop->link = top->link; 20910292Smckusick top->link = *frompcindex; 21010292Smckusick *frompcindex = toindex; 21110292Smckusick goto done; 2127332Ssam } 21310292Smckusick 2147332Ssam } 2157332Ssam done: 21616924Smckusick splx(s); 2177332Ssam /* and fall through */ 2187332Ssam out: 2197332Ssam asm(" rsb"); 2207332Ssam 2217332Ssam overflow: 22210292Smckusick profiling = 3; 2237332Ssam printf("mcount: tos overflow\n"); 2247332Ssam goto out; 2257332Ssam } 22610292Smckusick asm(".text"); 22710292Smckusick asm("#the end of mcount()"); 22810292Smckusick asm(".data"); 22910292Smckusick #endif vax 2307332Ssam #endif GPROF 231