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