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 "tconfig.h"
00036 #include "tsystem.h"
00037 #include <fcntl.h>
00038 #include "coretypes.h"
00039 #include "tm.h"
00040
00041 #if 0
00042 #include "sparc/gmon.h"
00043 #else
00044 struct phdr {
00045 char *lpc;
00046 char *hpc;
00047 int ncnt;
00048 };
00049 #define HISTFRACTION 2
00050 #define HISTCOUNTER unsigned short
00051 #define HASHFRACTION 1
00052 #define ARCDENSITY 2
00053 #define MINARCS 50
00054 struct tostruct {
00055 char *selfpc;
00056 long count;
00057 unsigned short link;
00058 };
00059 struct rawarc {
00060 unsigned long raw_frompc;
00061 unsigned long raw_selfpc;
00062 long raw_count;
00063 };
00064 #define ROUNDDOWN(x,y) (((x)/(y))*(y))
00065 #define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y))
00066
00067 #endif
00068
00069
00070 char *minbrk ;
00071
00072
00073
00074
00075 static int profiling = 3;
00076 static unsigned short *froms;
00077 static struct tostruct *tos = 0;
00078 static long tolimit = 0;
00079 static char *s_lowpc = 0;
00080 static char *s_highpc = 0;
00081 static unsigned long s_textsize = 0;
00082
00083 static int ssiz;
00084 static char *sbuf;
00085 static int s_scale;
00086
00087 #define SCALE_1_TO_1 0x10000L
00088
00089 #define MSG "No space for profiling buffer(s)\n"
00090
00091 static void moncontrol (int);
00092 extern void monstartup (char *, char *);
00093 extern void _mcleanup (void);
00094
00095 void monstartup(char *lowpc, char *highpc)
00096 {
00097 int monsize;
00098 char *buffer;
00099 register int o;
00100
00101
00102
00103
00104
00105 lowpc = (char *)
00106 ROUNDDOWN((unsigned long)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
00107 s_lowpc = lowpc;
00108 highpc = (char *)
00109 ROUNDUP((unsigned long)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
00110 s_highpc = highpc;
00111 s_textsize = highpc - lowpc;
00112 monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
00113 buffer = sbrk( monsize );
00114 if ( buffer == (char *) -1 ) {
00115 write( 2 , MSG , sizeof(MSG) );
00116 return;
00117 }
00118 froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION );
00119 if ( froms == (unsigned short *) -1 ) {
00120 write( 2 , MSG , sizeof(MSG) );
00121 froms = 0;
00122 return;
00123 }
00124 tolimit = s_textsize * ARCDENSITY / 100;
00125 if ( tolimit < MINARCS ) {
00126 tolimit = MINARCS;
00127 } else if ( tolimit > 65534 ) {
00128 tolimit = 65534;
00129 }
00130 tos = (struct tostruct *) sbrk( tolimit * sizeof( struct tostruct ) );
00131 if ( tos == (struct tostruct *) -1 ) {
00132 write( 2 , MSG , sizeof(MSG) );
00133 froms = 0;
00134 tos = 0;
00135 return;
00136 }
00137 minbrk = sbrk(0);
00138 tos[0].link = 0;
00139 sbuf = buffer;
00140 ssiz = monsize;
00141 ( (struct phdr *) buffer ) -> lpc = lowpc;
00142 ( (struct phdr *) buffer ) -> hpc = highpc;
00143 ( (struct phdr *) buffer ) -> ncnt = ssiz;
00144 monsize -= sizeof(struct phdr);
00145 if ( monsize <= 0 )
00146 return;
00147 o = highpc - lowpc;
00148 if( monsize < o )
00149 #ifndef hp300
00150 s_scale = ( (float) monsize / o ) * SCALE_1_TO_1;
00151 #else
00152 {
00153 int quot = o / monsize;
00154
00155 if (quot >= 0x10000)
00156 s_scale = 1;
00157 else if (quot >= 0x100)
00158 s_scale = 0x10000 / quot;
00159 else if (o >= 0x800000)
00160 s_scale = 0x1000000 / (o / (monsize >> 8));
00161 else
00162 s_scale = 0x1000000 / ((o << 8) / monsize);
00163 }
00164 #endif
00165 else
00166 s_scale = SCALE_1_TO_1;
00167 moncontrol(1);
00168 }
00169
00170 void
00171 _mcleanup(void)
00172 {
00173 int fd;
00174 int fromindex;
00175 int endfrom;
00176 char *frompc;
00177 int toindex;
00178 struct rawarc rawarc;
00179 char *profdir;
00180 const char *proffile;
00181 char *progname;
00182 char buf[PATH_MAX];
00183 extern char **___Argv;
00184
00185 moncontrol(0);
00186
00187 if ((profdir = getenv("PROFDIR")) != NULL) {
00188
00189 if (*profdir == '\0') {
00190 return;
00191 }
00192
00193 progname=strrchr(___Argv[0], '/');
00194 if (progname == NULL)
00195 progname=___Argv[0];
00196 else
00197 progname++;
00198
00199 sprintf(buf, "%s/%ld.%s", profdir, (long) getpid(), progname);
00200 proffile = buf;
00201 } else {
00202 proffile = "gmon.out";
00203 }
00204
00205 fd = creat( proffile, 0666 );
00206 if ( fd < 0 ) {
00207 perror( proffile );
00208 return;
00209 }
00210 # ifdef DEBUG
00211 fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
00212 # endif
00213 write( fd , sbuf , ssiz );
00214 endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
00215 for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) {
00216 if ( froms[fromindex] == 0 ) {
00217 continue;
00218 }
00219 frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms));
00220 for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {
00221 # ifdef DEBUG
00222 fprintf( stderr ,
00223 "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
00224 frompc , tos[toindex].selfpc , tos[toindex].count );
00225 # endif
00226 rawarc.raw_frompc = (unsigned long) frompc;
00227 rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
00228 rawarc.raw_count = tos[toindex].count;
00229 write( fd , &rawarc , sizeof rawarc );
00230 }
00231 }
00232 close( fd );
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
00270 static void internal_mcount (char *, unsigned short *)
00271 __attribute__ ((__unused__));
00272
00273
00274
00275
00276 asm(".global _mcount; _mcount: mov %i7,%o1; mov %o7,%o0;b,a internal_mcount");
00277
00278 asm(".global mcount; mcount: mov %i7,%o1; mov %o7,%o0;b,a internal_mcount");
00279
00280 static void internal_mcount(char *selfpc, 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(int mode)
00411 {
00412 if (mode) {
00413
00414 profil((unsigned short *)(sbuf + sizeof(struct phdr)),
00415 ssiz - sizeof(struct phdr),
00416 (long)s_lowpc, s_scale);
00417 profiling = 0;
00418 } else {
00419
00420 profil((unsigned short *)0, 0, 0, 0);
00421 profiling = 3;
00422 }
00423 }