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