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: }

Defined functions

_mcleanup defined in line 86; used 3 times
mcount defined in line 129; used 2 times
moncontrol defined in line 284; used 6 times
monstartup defined in line 36; used 1 times

Defined variables

froms defined in line 21; used 10 times
profiling defined in line 20; used 6 times
s_highpc defined in line 25; used 1 times
  • in line 54
s_lowpc defined in line 24; used 4 times
s_scale defined in line 30; used 3 times
s_textsize defined in line 26; used 6 times
sbuf defined in line 29; used 4 times
sccsid defined in line 8; never used
ssiz defined in line 28; used 5 times
tolimit defined in line 23; used 9 times
tos defined in line 22; used 15 times

Defined macros

MSG defined in line 34; used 6 times
SCALE_1_TO_1 defined in line 32; used 2 times
TOLIMIT defined in line 240; used 2 times
  • in line 241(2)
Last modified: 1986-03-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1421
Valid CSS Valid XHTML 1.0 Strict