1*7332Ssam /* subr_prof.c 4.1 82/06/28 */ 2*7332Ssam 3*7332Ssam #ifdef GPROF 4*7332Ssam #include "../h/crt0.h" 5*7332Ssam #include "../h/param.h" 6*7332Ssam #include "../h/systm.h" 7*7332Ssam 8*7332Ssam /* 9*7332Ssam * Froms is actually a bunch of unsigned shorts indexing tos 10*7332Ssam */ 11*7332Ssam int profiling = 3; 12*7332Ssam u_short *froms = 0; 13*7332Ssam struct tostruct *tos = 0; 14*7332Ssam u_short tolimit = 0; 15*7332Ssam char *s_lowpc = (char *)0x80000000; 16*7332Ssam extern char etext; 17*7332Ssam char *s_highpc = &etext; 18*7332Ssam u_long s_textsize = 0; 19*7332Ssam int ssiz; 20*7332Ssam u_short *sbuf; 21*7332Ssam u_short *kcount; 22*7332Ssam 23*7332Ssam kmstartup() 24*7332Ssam { 25*7332Ssam u_long limit; 26*7332Ssam 27*7332Ssam s_textsize = s_highpc - s_lowpc; 28*7332Ssam ssiz = s_textsize + sizeof(struct phdr); 29*7332Ssam printf("Profiling kernel, s_textsize=%d [%x..%x]\n", 30*7332Ssam s_textsize, s_lowpc, s_highpc); 31*7332Ssam sbuf = (u_short *)wmemall(vmemall, ssiz); 32*7332Ssam if (sbuf == 0) { 33*7332Ssam printf("No space for monitor buffer(s)\n"); 34*7332Ssam return; 35*7332Ssam } 36*7332Ssam blkclr((caddr_t)sbuf, ssiz); 37*7332Ssam froms = (u_short *)wmemall(vmemall, s_textsize); 38*7332Ssam if (froms == 0) { 39*7332Ssam printf("No space for monitor buffer(s)\n"); 40*7332Ssam wmemfree(sbuf, ssiz); 41*7332Ssam sbuf = 0; 42*7332Ssam return; 43*7332Ssam } 44*7332Ssam blkclr((caddr_t)froms, s_textsize); 45*7332Ssam tos = (struct tostruct *)wmemall(vmemall, s_textsize); 46*7332Ssam if (tos == 0) { 47*7332Ssam printf("No space for monitor buffer(s)\n"); 48*7332Ssam wmemfree(sbuf, ssiz); 49*7332Ssam sbuf = 0; 50*7332Ssam wmemfree(froms, s_textsize); 51*7332Ssam froms = 0; 52*7332Ssam return; 53*7332Ssam } 54*7332Ssam blkclr((caddr_t)tos, s_textsize); 55*7332Ssam tos[0].link = 0; 56*7332Ssam limit = s_textsize / sizeof(struct tostruct); 57*7332Ssam /* 58*7332Ssam * Tolimit is what mcount checks to see if 59*7332Ssam * all the data structures are ready!!! 60*7332Ssam * Make sure it won't overflow. 61*7332Ssam */ 62*7332Ssam tolimit = limit > 65534 ? 65534 : limit; 63*7332Ssam ((struct phdr *)sbuf)->lpc = s_lowpc; 64*7332Ssam ((struct phdr *)sbuf)->hpc = s_highpc; 65*7332Ssam ((struct phdr *)sbuf)->ncnt = ssiz; 66*7332Ssam kcount = (u_short *)(((int)sbuf) + sizeof(struct phdr)); 67*7332Ssam #ifdef notdef 68*7332Ssam profiling = 0; /* patch by hand when you're ready */ 69*7332Ssam #endif 70*7332Ssam } 71*7332Ssam 72*7332Ssam /* 73*7332Ssam * This routine is massaged so that it may be jsb'ed to 74*7332Ssam */ 75*7332Ssam asm("#define _mcount mcount"); 76*7332Ssam mcount() 77*7332Ssam { 78*7332Ssam register char *selfpc; /* r11 */ 79*7332Ssam register u_short *frompcindex; /* r10 */ 80*7332Ssam register struct tostruct *top; /* r9 */ 81*7332Ssam 82*7332Ssam asm(" forgot to run ex script on gcrt0.s"); 83*7332Ssam asm("#define r11 r5"); 84*7332Ssam asm("#define r10 r4"); 85*7332Ssam asm("#define r9 r3"); 86*7332Ssam #ifdef lint 87*7332Ssam selfpc = (char *) 0; 88*7332Ssam frompcindex = 0; 89*7332Ssam #else not lint 90*7332Ssam /* 91*7332Ssam * Find the return address for mcount, 92*7332Ssam * and the return address for mcount's caller. 93*7332Ssam */ 94*7332Ssam asm(" movl (sp), r11"); /* selfpc = ... (jsb frame) */ 95*7332Ssam asm(" movl 16(fp), r10"); /* frompcindex = (calls frame) */ 96*7332Ssam #endif not lint 97*7332Ssam /* 98*7332Ssam * Check that we are profiling 99*7332Ssam * and that we aren't recursively invoked. 100*7332Ssam */ 101*7332Ssam if (tolimit == 0) 102*7332Ssam goto out; 103*7332Ssam if (profiling) 104*7332Ssam goto out; 105*7332Ssam profiling++; 106*7332Ssam /* 107*7332Ssam * Check that frompcindex is a reasonable pc value. 108*7332Ssam * For example: signal catchers get called from the stack, 109*7332Ssam * not from text space. too bad. 110*7332Ssam */ 111*7332Ssam frompcindex = (u_short *)((long)frompcindex - (long)s_lowpc); 112*7332Ssam if ((u_long)frompcindex > s_textsize) 113*7332Ssam goto done; 114*7332Ssam frompcindex = &froms[((long)frompcindex) >> 1]; 115*7332Ssam if (*frompcindex != 0) 116*7332Ssam top = &tos[*frompcindex]; 117*7332Ssam else { 118*7332Ssam *frompcindex = ++tos[0].link; 119*7332Ssam if (*frompcindex >= tolimit) 120*7332Ssam goto overflow; 121*7332Ssam top = &tos[*frompcindex]; 122*7332Ssam top->selfpc = selfpc; 123*7332Ssam top->count = 0; 124*7332Ssam top->link = 0; 125*7332Ssam } 126*7332Ssam for (; /* break */; top = &tos[top->link]) { 127*7332Ssam if (top->selfpc == selfpc) { 128*7332Ssam top->count++; 129*7332Ssam break; 130*7332Ssam } 131*7332Ssam if (top->link != 0) 132*7332Ssam continue; 133*7332Ssam top->link = ++tos[0].link; 134*7332Ssam if (top->link >= tolimit) 135*7332Ssam goto overflow; 136*7332Ssam top = &tos[top->link]; 137*7332Ssam top->selfpc = selfpc; 138*7332Ssam top->count = 1; 139*7332Ssam top->link = 0; 140*7332Ssam break; 141*7332Ssam } 142*7332Ssam done: 143*7332Ssam profiling--; 144*7332Ssam /* and fall through */ 145*7332Ssam out: 146*7332Ssam asm(" rsb"); 147*7332Ssam asm("#undef r11"); 148*7332Ssam asm("#undef r10"); 149*7332Ssam asm("#undef r9"); 150*7332Ssam asm("#undef _mcount"); 151*7332Ssam 152*7332Ssam overflow: 153*7332Ssam tolimit = 0; 154*7332Ssam printf("mcount: tos overflow\n"); 155*7332Ssam goto out; 156*7332Ssam } 157*7332Ssam #endif GPROF 158