|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 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: ! 7: #if defined(LIBC_SCCS) && !defined(lint) ! 8: static char sccsid[] = "@(#)gmon.c 5.3 (Berkeley) 3/9/86"; ! 9: #endif LIBC_SCCS and not lint ! 10: ! 11: #ifdef DEBUG ! 12: #include <stdio.h> ! 13: #endif DEBUG ! 14: ! 15: #include "gmon.h" ! 16: ! 17: /* ! 18: * froms is actually a bunch of unsigned shorts indexing tos ! 19: */ ! 20: static int profiling = 3; ! 21: static unsigned short *froms; ! 22: static struct tostruct *tos = 0; ! 23: static long tolimit = 0; ! 24: static char *s_lowpc = 0; ! 25: static char *s_highpc = 0; ! 26: static unsigned long s_textsize = 0; ! 27: ! 28: static int ssiz; ! 29: static char *sbuf; ! 30: static int s_scale; ! 31: /* see profil(2) where this is describe (incorrectly) */ ! 32: #define SCALE_1_TO_1 0x10000L ! 33: ! 34: #define MSG "No space for monitor buffer(s)\n" ! 35: ! 36: monstartup(lowpc, highpc) ! 37: char *lowpc; ! 38: char *highpc; ! 39: { ! 40: int monsize; ! 41: char *buffer; ! 42: char *sbrk(); ! 43: extern char *minbrk; ! 44: ! 45: /* ! 46: * round lowpc and highpc to multiples of the density we're using ! 47: * so the rest of the scaling (here and in gprof) stays in ints. ! 48: */ ! 49: lowpc = (char *) ! 50: ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER)); ! 51: s_lowpc = lowpc; ! 52: highpc = (char *) ! 53: ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER)); ! 54: s_highpc = highpc; ! 55: s_textsize = highpc - lowpc; ! 56: monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr); ! 57: buffer = sbrk( monsize ); ! 58: if ( buffer == (char *) -1 ) { ! 59: write( 2 , MSG , sizeof(MSG) ); ! 60: return; ! 61: } ! 62: froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION ); ! 63: if ( froms == (unsigned short *) -1 ) { ! 64: write( 2 , MSG , sizeof(MSG) ); ! 65: froms = 0; ! 66: return; ! 67: } ! 68: tolimit = s_textsize * ARCDENSITY / 100; ! 69: if ( tolimit < MINARCS ) { ! 70: tolimit = MINARCS; ! 71: } else if ( tolimit > 65534 ) { ! 72: tolimit = 65534; ! 73: } ! 74: tos = (struct tostruct *) sbrk( tolimit * sizeof( struct tostruct ) ); ! 75: if ( tos == (struct tostruct *) -1 ) { ! 76: write( 2 , MSG , sizeof(MSG) ); ! 77: froms = 0; ! 78: tos = 0; ! 79: return; ! 80: } ! 81: minbrk = sbrk(0); ! 82: tos[0].link = 0; ! 83: monitor( lowpc , highpc , buffer , monsize , tolimit ); ! 84: } ! 85: ! 86: _mcleanup() ! 87: { ! 88: int fd; ! 89: int fromindex; ! 90: int endfrom; ! 91: char *frompc; ! 92: int toindex; ! 93: struct rawarc rawarc; ! 94: ! 95: fd = creat( "gmon.out" , 0666 ); ! 96: if ( fd < 0 ) { ! 97: perror( "mcount: gmon.out" ); ! 98: return; ! 99: } ! 100: # ifdef DEBUG ! 101: fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz ); ! 102: # endif DEBUG ! 103: write( fd , sbuf , ssiz ); ! 104: endfrom = s_textsize / (HASHFRACTION * sizeof(*froms)); ! 105: for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) { ! 106: if ( froms[fromindex] == 0 ) { ! 107: continue; ! 108: } ! 109: frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms)); ! 110: for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) { ! 111: # ifdef DEBUG ! 112: fprintf( stderr , ! 113: "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" , ! 114: frompc , tos[toindex].selfpc , tos[toindex].count ); ! 115: # endif DEBUG ! 116: rawarc.raw_frompc = (unsigned long) frompc; ! 117: rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc; ! 118: rawarc.raw_count = tos[toindex].count; ! 119: write( fd , &rawarc , sizeof rawarc ); ! 120: } ! 121: } ! 122: close( fd ); ! 123: } ! 124: ! 125: asm(".text"); ! 126: asm(".align 2"); ! 127: asm("#the beginning of mcount()"); ! 128: asm(".data"); ! 129: mcount() ! 130: { ! 131: register char *selfpc; /* r11 => r5 */ ! 132: register unsigned short *frompcindex; /* r10 => r4 */ ! 133: register struct tostruct *top; /* r9 => r3 */ ! 134: register struct tostruct *prevtop; /* r8 => r2 */ ! 135: register long toindex; /* r7 => r1 */ ! 136: ! 137: /* ! 138: * find the return address for mcount, ! 139: * and the return address for mcount's caller. ! 140: */ ! 141: asm(" .text"); /* make sure we're in text space */ ! 142: asm(" movl (sp), r11"); /* selfpc = ... (jsb frame) */ ! 143: asm(" movl 16(fp), r10"); /* frompcindex = (calls frame) */ ! 144: /* ! 145: * check that we are profiling ! 146: * and that we aren't recursively invoked. ! 147: */ ! 148: if (profiling) { ! 149: goto out; ! 150: } ! 151: profiling++; ! 152: /* ! 153: * check that frompcindex is a reasonable pc value. ! 154: * for example: signal catchers get called from the stack, ! 155: * not from text space. too bad. ! 156: */ ! 157: frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc); ! 158: if ((unsigned long)frompcindex > s_textsize) { ! 159: goto done; ! 160: } ! 161: frompcindex = ! 162: &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))]; ! 163: toindex = *frompcindex; ! 164: if (toindex == 0) { ! 165: /* ! 166: * first time traversing this arc ! 167: */ ! 168: toindex = ++tos[0].link; ! 169: if (toindex >= tolimit) { ! 170: goto overflow; ! 171: } ! 172: *frompcindex = toindex; ! 173: top = &tos[toindex]; ! 174: top->selfpc = selfpc; ! 175: top->count = 1; ! 176: top->link = 0; ! 177: goto done; ! 178: } ! 179: top = &tos[toindex]; ! 180: if (top->selfpc == selfpc) { ! 181: /* ! 182: * arc at front of chain; usual case. ! 183: */ ! 184: top->count++; ! 185: goto done; ! 186: } ! 187: /* ! 188: * have to go looking down chain for it. ! 189: * top points to what we are looking at, ! 190: * prevtop points to previous top. ! 191: * we know it is not at the head of the chain. ! 192: */ ! 193: for (; /* goto done */; ) { ! 194: if (top->link == 0) { ! 195: /* ! 196: * top is end of the chain and none of the chain ! 197: * had top->selfpc == selfpc. ! 198: * so we allocate a new tostruct ! 199: * and link it to the head of the chain. ! 200: */ ! 201: toindex = ++tos[0].link; ! 202: if (toindex >= tolimit) { ! 203: goto overflow; ! 204: } ! 205: top = &tos[toindex]; ! 206: top->selfpc = selfpc; ! 207: top->count = 1; ! 208: top->link = *frompcindex; ! 209: *frompcindex = toindex; ! 210: goto done; ! 211: } ! 212: /* ! 213: * otherwise, check the next arc on the chain. ! 214: */ ! 215: prevtop = top; ! 216: top = &tos[top->link]; ! 217: if (top->selfpc == selfpc) { ! 218: /* ! 219: * there it is. ! 220: * increment its count ! 221: * move it to the head of the chain. ! 222: */ ! 223: top->count++; ! 224: toindex = prevtop->link; ! 225: prevtop->link = top->link; ! 226: top->link = *frompcindex; ! 227: *frompcindex = toindex; ! 228: goto done; ! 229: } ! 230: ! 231: } ! 232: done: ! 233: profiling--; ! 234: /* and fall through */ ! 235: out: ! 236: asm(" rsb"); ! 237: ! 238: overflow: ! 239: profiling++; /* halt further profiling */ ! 240: # define TOLIMIT "mcount: tos overflow\n" ! 241: write(2, TOLIMIT, sizeof(TOLIMIT)); ! 242: goto out; ! 243: } ! 244: asm(".text"); ! 245: asm("#the end of mcount()"); ! 246: asm(".data"); ! 247: ! 248: /*VARARGS1*/ ! 249: monitor( lowpc , highpc , buf , bufsiz , nfunc ) ! 250: char *lowpc; ! 251: char *highpc; ! 252: char *buf; /* declared ``short buffer[]'' in monitor(3) */ ! 253: int bufsiz; ! 254: int nfunc; /* not used, available for compatability only */ ! 255: { ! 256: register o; ! 257: ! 258: if ( lowpc == 0 ) { ! 259: moncontrol(0); ! 260: _mcleanup(); ! 261: return; ! 262: } ! 263: sbuf = buf; ! 264: ssiz = bufsiz; ! 265: ( (struct phdr *) buf ) -> lpc = lowpc; ! 266: ( (struct phdr *) buf ) -> hpc = highpc; ! 267: ( (struct phdr *) buf ) -> ncnt = ssiz; ! 268: bufsiz -= sizeof(struct phdr); ! 269: if ( bufsiz <= 0 ) ! 270: return; ! 271: o = highpc - lowpc; ! 272: if( bufsiz < o ) ! 273: s_scale = ( (float) bufsiz / o ) * SCALE_1_TO_1; ! 274: else ! 275: s_scale = SCALE_1_TO_1; ! 276: moncontrol(1); ! 277: } ! 278: ! 279: /* ! 280: * Control profiling ! 281: * profiling is what mcount checks to see if ! 282: * all the data structures are ready. ! 283: */ ! 284: moncontrol(mode) ! 285: int mode; ! 286: { ! 287: if (mode) { ! 288: /* start */ ! 289: profil(sbuf + sizeof(struct phdr), ssiz - sizeof(struct phdr), ! 290: s_lowpc, s_scale); ! 291: profiling = 0; ! 292: } else { ! 293: /* stop */ ! 294: profil((char *)0, 0, 0, 0); ! 295: profiling = 3; ! 296: } ! 297: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.