|
|
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(".even"); ! 127: asm(".data"); ! 128: mcount() ! 129: { ! 130: register char *selfpc; /* PCC a5 */ ! 131: register unsigned short *frompcindex; /* PCC a4 */ ! 132: register struct tostruct *top; ! 133: register struct tostruct *prevtop; ! 134: register long toindex; ! 135: ! 136: /* ! 137: * find the return address for mcount, ! 138: * and the return address for mcount's caller. ! 139: */ ! 140: asm(" .text"); /* make sure we're in text space */ ! 141: #ifdef __GNUC__ ! 142: /* ! 143: * selfpc = pc pushed by mcount jsr ! 144: */ ! 145: asm("movl a6@(4),%0" : "=r" (selfpc)); ! 146: /* ! 147: * frompcindex = pc pushed by jsr into self. ! 148: * In GCC the caller's stack frame has already been built so we ! 149: * have to chase a6 to find caller's raddr. ! 150: * NOTE: this assumes that all profiled routines use link/unlk. ! 151: */ ! 152: asm("movl a6@(0)@(4),%0" : "=r" (frompcindex)); ! 153: #else ! 154: asm(" movl a6@(4),a5"); /* selfpc = pc pushed by mcount jsr */ ! 155: asm(" movl a6@(8),a4"); /* frompcindex = pc pushed by jsr into ! 156: self, stack frame not yet built */ ! 157: #endif ! 158: /* ! 159: * check that we are profiling ! 160: * and that we aren't recursively invoked. ! 161: */ ! 162: if (profiling) { ! 163: goto out; ! 164: } ! 165: profiling++; ! 166: /* ! 167: * check that frompcindex is a reasonable pc value. ! 168: * for example: signal catchers get called from the stack, ! 169: * not from text space. too bad. ! 170: */ ! 171: frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc); ! 172: if ((unsigned long)frompcindex > s_textsize) { ! 173: goto done; ! 174: } ! 175: frompcindex = ! 176: &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))]; ! 177: toindex = *frompcindex; ! 178: if (toindex == 0) { ! 179: /* ! 180: * first time traversing this arc ! 181: */ ! 182: toindex = ++tos[0].link; ! 183: if (toindex >= tolimit) { ! 184: goto overflow; ! 185: } ! 186: *frompcindex = toindex; ! 187: top = &tos[toindex]; ! 188: top->selfpc = selfpc; ! 189: top->count = 1; ! 190: top->link = 0; ! 191: goto done; ! 192: } ! 193: top = &tos[toindex]; ! 194: if (top->selfpc == selfpc) { ! 195: /* ! 196: * arc at front of chain; usual case. ! 197: */ ! 198: top->count++; ! 199: goto done; ! 200: } ! 201: /* ! 202: * have to go looking down chain for it. ! 203: * top points to what we are looking at, ! 204: * prevtop points to previous top. ! 205: * we know it is not at the head of the chain. ! 206: */ ! 207: for (; /* goto done */; ) { ! 208: if (top->link == 0) { ! 209: /* ! 210: * top is end of the chain and none of the chain ! 211: * had top->selfpc == selfpc. ! 212: * so we allocate a new tostruct ! 213: * and link it to the head of the chain. ! 214: */ ! 215: toindex = ++tos[0].link; ! 216: if (toindex >= tolimit) { ! 217: goto overflow; ! 218: } ! 219: top = &tos[toindex]; ! 220: top->selfpc = selfpc; ! 221: top->count = 1; ! 222: top->link = *frompcindex; ! 223: *frompcindex = toindex; ! 224: goto done; ! 225: } ! 226: /* ! 227: * otherwise, check the next arc on the chain. ! 228: */ ! 229: prevtop = top; ! 230: top = &tos[top->link]; ! 231: if (top->selfpc == selfpc) { ! 232: /* ! 233: * there it is. ! 234: * increment its count ! 235: * move it to the head of the chain. ! 236: */ ! 237: top->count++; ! 238: toindex = prevtop->link; ! 239: prevtop->link = top->link; ! 240: top->link = *frompcindex; ! 241: *frompcindex = toindex; ! 242: goto done; ! 243: } ! 244: ! 245: } ! 246: done: ! 247: profiling--; ! 248: /* and fall through */ ! 249: out: ! 250: return; /* normal return restores saved registers */ ! 251: ! 252: overflow: ! 253: profiling++; /* halt further profiling */ ! 254: # define TOLIMIT "mcount: tos overflow\n" ! 255: write(2, TOLIMIT, sizeof(TOLIMIT)); ! 256: goto out; ! 257: } ! 258: asm(".text"); ! 259: asm(".data"); ! 260: ! 261: /*VARARGS1*/ ! 262: monitor( lowpc , highpc , buf , bufsiz , nfunc ) ! 263: char *lowpc; ! 264: char *highpc; ! 265: char *buf; /* declared ``short buffer[]'' in monitor(3) */ ! 266: int bufsiz; ! 267: int nfunc; /* not used, available for compatability only */ ! 268: { ! 269: register o; ! 270: ! 271: if ( lowpc == 0 ) { ! 272: moncontrol(0); ! 273: _mcleanup(); ! 274: return; ! 275: } ! 276: sbuf = buf; ! 277: ssiz = bufsiz; ! 278: ( (struct phdr *) buf ) -> lpc = lowpc; ! 279: ( (struct phdr *) buf ) -> hpc = highpc; ! 280: ( (struct phdr *) buf ) -> ncnt = ssiz; ! 281: bufsiz -= sizeof(struct phdr); ! 282: if ( bufsiz <= 0 ) ! 283: return; ! 284: o = highpc - lowpc; ! 285: if( bufsiz < o ) ! 286: #ifndef hp300 ! 287: s_scale = ( (float) bufsiz / o ) * SCALE_1_TO_1; ! 288: #else /* avoid floating point */ ! 289: { ! 290: int quot = o / bufsiz; ! 291: ! 292: if (quot >= 0x10000) ! 293: s_scale = 1; ! 294: else if (quot >= 0x100) ! 295: s_scale = 0x10000 / quot; ! 296: else if (o >= 0x800000) ! 297: s_scale = 0x1000000 / (o / (bufsiz >> 8)); ! 298: else ! 299: s_scale = 0x1000000 / ((o << 8) / bufsiz); ! 300: } ! 301: #endif ! 302: else ! 303: s_scale = SCALE_1_TO_1; ! 304: moncontrol(1); ! 305: } ! 306: ! 307: /* ! 308: * Control profiling ! 309: * profiling is what mcount checks to see if ! 310: * all the data structures are ready. ! 311: */ ! 312: moncontrol(mode) ! 313: int mode; ! 314: { ! 315: if (mode) { ! 316: /* start */ ! 317: profil(sbuf + sizeof(struct phdr), ssiz - sizeof(struct phdr), ! 318: s_lowpc, s_scale); ! 319: profiling = 0; ! 320: } else { ! 321: /* stop */ ! 322: profil((char *)0, 0, 0, 0); ! 323: profiling = 3; ! 324: } ! 325: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.