00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "config.h"
00036 #include "system.h"
00037
00038 #if 0
00039 #include "sparc/gmon.h"
00040 #else
00041 struct phdr {
00042 char *lpc;
00043 char *hpc;
00044 int ncnt;
00045 };
00046 #define HISTFRACTION 2
00047 #define HISTCOUNTER unsigned short
00048 #define HASHFRACTION 1
00049 #define ARCDENSITY 2
00050 #define MINARCS 50
00051 struct tostruct {
00052 char *selfpc;
00053 long count;
00054 unsigned short link;
00055 };
00056 struct rawarc {
00057 unsigned long raw_frompc;
00058 unsigned long raw_selfpc;
00059 long raw_count;
00060 };
00061 #define ROUNDDOWN(x,y) (((x)/(y))*(y))
00062 #define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y))
00063
00064 #endif
00065
00066
00067 char *minbrk ;
00068
00069
00070
00071
00072 static int profiling = 3;
00073 static unsigned short *froms;
00074 static struct tostruct *tos = 0;
00075 static long tolimit = 0;
00076 static char *s_lowpc = 0;
00077 static char *s_highpc = 0;
00078 static unsigned long s_textsize = 0;
00079
00080 static int ssiz;
00081 static char *sbuf;
00082 static int s_scale;
00083
00084 #define SCALE_1_TO_1 0x10000L
00085
00086 #define MSG "No space for profiling buffer(s)\n"
00087
00088 static void moncontrol PARAMS ((int));
00089 extern void monstartup PARAMS ((char *, char *));
00090 extern void _mcleanup PARAMS ((void));
00091
00092 void monstartup(lowpc, highpc)
00093 char *lowpc;
00094 char *highpc;
00095 {
00096 int monsize;
00097 char *buffer;
00098 register int o;
00099
00100
00101
00102
00103
00104 lowpc = (char *)
00105 ROUNDDOWN((unsigned long)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
00106 s_lowpc = lowpc;
00107 highpc = (char *)
00108 ROUNDUP((unsigned long)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
00109 s_highpc = highpc;
00110 s_textsize = highpc - lowpc;
00111 monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
00112 buffer = sbrk( monsize );
00113 if ( buffer == (char *) -1 ) {
00114 write( 2 , MSG , sizeof(MSG) );
00115 return;
00116 }
00117 froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION );
00118 if ( froms == (unsigned short *) -1 ) {
00119 write( 2 , MSG , sizeof(MSG) );
00120 froms = 0;
00121 return;
00122 }
00123 tolimit = s_textsize * ARCDENSITY / 100;
00124 if ( tolimit < MINARCS ) {
00125 tolimit = MINARCS;
00126 } else if ( tolimit > 65534 ) {
00127 tolimit = 65534;
00128 }
00129 tos = (struct tostruct *) sbrk( tolimit * sizeof( struct tostruct ) );
00130 if ( tos == (struct tostruct *) -1 ) {
00131 write( 2 , MSG , sizeof(MSG) );
00132 froms = 0;
00133 tos = 0;
00134 return;
00135 }
00136 minbrk = sbrk(0);
00137 tos[0].link = 0;
00138 sbuf = buffer;
00139 ssiz = monsize;
00140 ( (struct phdr *) buffer ) -> lpc = lowpc;
00141 ( (struct phdr *) buffer ) -> hpc = highpc;
00142 ( (struct phdr *) buffer ) -> ncnt = ssiz;
00143 monsize -= sizeof(struct phdr);
00144 if ( monsize <= 0 )
00145 return;
00146 o = highpc - lowpc;
00147 if( monsize < o )
00148 #ifndef hp300
00149 s_scale = ( (float) monsize / o ) * SCALE_1_TO_1;
00150 #else
00151 {
00152 int quot = o / monsize;
00153
00154 if (quot >= 0x10000)
00155 s_scale = 1;
00156 else if (quot >= 0x100)
00157 s_scale = 0x10000 / quot;
00158 else if (o >= 0x800000)
00159 s_scale = 0x1000000 / (o / (monsize >> 8));
00160 else
00161 s_scale = 0x1000000 / ((o << 8) / monsize);
00162 }
00163 #endif
00164 else
00165 s_scale = SCALE_1_TO_1;
00166 moncontrol(1);
00167 }
00168
00169 void
00170 _mcleanup()
00171 {
00172 int fd;
00173 int fromindex;
00174 int endfrom;
00175 char *frompc;
00176 int toindex;
00177 struct rawarc rawarc;
00178 char *profdir;
00179 const char *proffile;
00180 char *progname;
00181 char buf[PATH_MAX];
00182 extern char **___Argv;
00183
00184 moncontrol(0);
00185
00186 if ((profdir = getenv("PROFDIR")) != NULL) {
00187
00188 if (*profdir == '\0') {
00189 return;
00190 }
00191
00192 progname=strrchr(___Argv[0], '/');
00193 if (progname == NULL)
00194 progname=___Argv[0];
00195 else
00196 progname++;
00197
00198 sprintf(buf, "%s/%ld.%s", profdir, (long) getpid(), progname);
00199 proffile = buf;
00200 } else {
00201 proffile = "gmon.out";
00202 }
00203
00204 fd = creat( proffile, 0666 );
00205 if ( fd < 0 ) {
00206 perror( proffile );
00207 return;
00208 }
00209 # ifdef DEBUG
00210 fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
00211 # endif
00212 write( fd , sbuf , ssiz );
00213 endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
00214 for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) {
00215 if ( froms[fromindex] == 0 ) {
00216 continue;
00217 }
00218 frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms));
00219 for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {
00220 # ifdef DEBUG
00221 fprintf( stderr ,
00222 "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
00223 frompc , tos[toindex].selfpc , tos[toindex].count );
00224 # endif
00225 rawarc.raw_frompc = (unsigned long) frompc;
00226 rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
00227 rawarc.raw_count = tos[toindex].count;
00228 write( fd , &rawarc , sizeof rawarc );
00229 }
00230 }
00231 close( fd );
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 static void internal_mcount PARAMS ((char *, unsigned short *)) ATTRIBUTE_UNUSED;
00270
00271
00272
00273
00274 asm(".global _mcount; _mcount: mov %i7,%o1; mov %o7,%o0;b,a internal_mcount");
00275
00276 asm(".global mcount; mcount: mov %i7,%o1; mov %o7,%o0;b,a internal_mcount");
00277
00278 static void internal_mcount(selfpc, frompcindex)
00279 register char *selfpc;
00280 register unsigned short *frompcindex;
00281 {
00282 register struct tostruct *top;
00283 register struct tostruct *prevtop;
00284 register long toindex;
00285 static char already_setup;
00286
00287
00288
00289
00290
00291
00292 if(!already_setup) {
00293 extern char etext[];
00294 extern char _start[];
00295 extern char _init[];
00296 already_setup = 1;
00297 monstartup(_start < _init ? _start : _init, etext);
00298 #ifdef USE_ONEXIT
00299 on_exit(_mcleanup, 0);
00300 #else
00301 atexit(_mcleanup);
00302 #endif
00303 }
00304
00305
00306
00307
00308 if (profiling) {
00309 goto out;
00310 }
00311 profiling++;
00312
00313
00314
00315
00316
00317 frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
00318 if ((unsigned long)frompcindex > s_textsize) {
00319 goto done;
00320 }
00321 frompcindex =
00322 &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
00323 toindex = *frompcindex;
00324 if (toindex == 0) {
00325
00326
00327
00328 toindex = ++tos[0].link;
00329 if (toindex >= tolimit) {
00330 goto overflow;
00331 }
00332 *frompcindex = toindex;
00333 top = &tos[toindex];
00334 top->selfpc = selfpc;
00335 top->count = 1;
00336 top->link = 0;
00337 goto done;
00338 }
00339 top = &tos[toindex];
00340 if (top->selfpc == selfpc) {
00341
00342
00343
00344 top->count++;
00345 goto done;
00346 }
00347
00348
00349
00350
00351
00352
00353 for (; ; ) {
00354 if (top->link == 0) {
00355
00356
00357
00358
00359
00360
00361 toindex = ++tos[0].link;
00362 if (toindex >= tolimit) {
00363 goto overflow;
00364 }
00365 top = &tos[toindex];
00366 top->selfpc = selfpc;
00367 top->count = 1;
00368 top->link = *frompcindex;
00369 *frompcindex = toindex;
00370 goto done;
00371 }
00372
00373
00374
00375 prevtop = top;
00376 top = &tos[top->link];
00377 if (top->selfpc == selfpc) {
00378
00379
00380
00381
00382
00383 top->count++;
00384 toindex = prevtop->link;
00385 prevtop->link = top->link;
00386 top->link = *frompcindex;
00387 *frompcindex = toindex;
00388 goto done;
00389 }
00390
00391 }
00392 done:
00393 profiling--;
00394
00395 out:
00396 return;
00397
00398 overflow:
00399 profiling++;
00400 # define TOLIMIT "mcount: tos overflow\n"
00401 write(2, TOLIMIT, sizeof(TOLIMIT));
00402 goto out;
00403 }
00404
00405
00406
00407
00408
00409
00410 static void moncontrol(mode)
00411 int mode;
00412 {
00413 if (mode) {
00414
00415 profil((unsigned short *)(sbuf + sizeof(struct phdr)),
00416 ssiz - sizeof(struct phdr),
00417 (long)s_lowpc, s_scale);
00418 profiling = 0;
00419 } else {
00420
00421 profil((unsigned short *)0, 0, 0, 0);
00422 profiling = 3;
00423 }
00424 }