📄 gmon.c
字号:
#ifndef lintstatic char sccsid[] = "@(#)gmon.c 1.1 92/07/30 SMI";#endif#ifdef DEBUG#include <stdio.h>#endif DEBUG/* * Environment variable PROFDIR added such that: * If PROFDIR doesn't exist, "gmon.out" is produced as before. * If PROFDIR = NULL, no profiling output is produced. * If PROFDIR = string, "string/pid.progname" is produced, * where name consists of argv[0] suitably massaged. */#include <sys/param.h>#include <sys/dir.h>#include "gmon.h"#define PROFDIR "PROFDIR"extern int creat(), write(), close(), getpid();extern void profil(), perror();extern char *getenv(), *strcpy(), *strrchr();void monitor(), moncontrol();char **___Argv = NULL; /* initialized to argv array by mcrt0 (if loaded) */ /* * froms is actually a bunch of unsigned shorts indexing tos */extern char profiling;static unsigned short *froms;static struct tostruct *tos = 0;static long tolimit = 0;static int s_lowpc = 0;static char *s_highpc = 0;static unsigned long s_textsize = 0;static int s_scale; /* see profil(2) where this is described (incorrectly) */#define SCALE_1_TO_1 0x10000Lstatic int ssiz;static int *sbuf;#define MSG "No space for monitor buffer(s)\n"static char gmon_out[MAXPATHLEN];static char progname[MAXNAMLEN];monstartup(lowpc, highpc) char *lowpc; char *highpc;{ int monsize, fromsize, tosize; char *buffer; char *_alloc_profil_buf(); /* * round lowpc and highpc to multiples of the density we're using * so the rest of the scaling (here and in gprof) stays in ints. */ lowpc = (char *) ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER)); s_lowpc = (int) lowpc; highpc = (char *) ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER)); s_highpc = highpc; s_textsize = highpc - lowpc; monsize = ROUNDUP((s_textsize / HISTFRACTION) + sizeof(struct phdr), sizeof(long)); fromsize = ROUNDUP(s_textsize / HASHFRACTION, sizeof(long)); tolimit = s_textsize * ARCDENSITY / 100; if ( tolimit < MINARCS ) { tolimit = MINARCS; } else if ( tolimit > 65534 ) { tolimit = 65534; } tosize = ROUNDUP( tolimit * sizeof( struct tostruct ), sizeof(long) ); buffer = _alloc_profil_buf(monsize+fromsize+tosize); if(buffer == (char*) -1) { write( 2 , MSG , sizeof(MSG) ); froms = 0; tos = 0; return; } froms = (unsigned short*) (buffer + monsize); tos = (struct tostruct*) (buffer + monsize + fromsize); tos[0].link = 0; monitor( lowpc , highpc , buffer , monsize , tolimit );}_mcleanup(){ int fd; int fromindex; int endfrom; int frompc; int toindex; struct rawarc rawarc; char *name = gmon_out; moncontrol(0); if (sbuf != NULL) { register int pid, n; if (progname[0] != '\0') { /* finish constructing "PROFDIR/pid.progname" */ /* set name to end of PROFDIR */ name = strrchr(gmon_out, '\0'); if ((pid = getpid()) <= 0) /* extra test just in case */ pid = 1; /* getpid returns something inappropriate */ for (n = 10000; n > pid; n /= 10) ; /* suppress leading zeros */ for ( ; ; n /= 10) { *name++ = pid/n + '0'; if (n == 1) break; pid %= n; } *name++ = '.'; (void)strcpy(name, progname); } fd = creat( gmon_out , 0666 ); if ( fd < 0 ) { perror( gmon_out ); return; }# ifdef DEBUG fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );# endif DEBUG if (write( fd , sbuf , ssiz ) == -1) { perror( gmon_out ); return; } } endfrom = s_textsize / (HASHFRACTION * sizeof(*froms)); for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) { if ( froms[fromindex] == 0 ) { continue; } frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms)); for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {# ifdef DEBUG fprintf( stderr , "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" , frompc , tos[toindex].selfpc , tos[toindex].count );# endif DEBUG rawarc.raw_frompc = (unsigned long) frompc; rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc; rawarc.raw_count = tos[toindex].count; write( fd , &rawarc , sizeof rawarc ); } } close( fd );}/*VARARGS1*/voidmonitor( lowpc , highpc , buf , bufsiz , nfunc ) char *lowpc; char *highpc; int *buf, bufsiz; int nfunc; /* not used, available for compatability only */{ register o; register char *s, *name = gmon_out; if ( lowpc == NULL ) { /* true only at the end */ moncontrol(0); _mcleanup(); return; }#if 0 if (ssiz >= bufsize || lowpc >= highpc) return; /* buffer too small or PC range bad */#endif if ((s = getenv(PROFDIR)) == NULL) /* PROFDIR not in environment */ (void)strcpy(name, GMON_OUT); /* use default "gmon.out" */ else if (*s == '\0') /* value of PROFDIR is NULL */ return; /* no profiling on this run */ else { /* set up mon_out and progname to construct "PROFDIR/pid.progname" when done profiling */ while (*s != '\0') /* copy PROFDIR value (path-prefix) */ *name++ = *s++; *name++ = '/'; /* two slashes won't hurt */ if (___Argv != NULL) /* mcrt0.s executed */ if ((s = strrchr(___Argv[0], '/')) != NULL) strcpy(progname, s + 1); else strcpy(progname, ___Argv[0]); } sbuf = buf; /* for writing buffer at the wrapup */ ssiz = bufsiz; ( (struct phdr *) buf ) -> lpc = lowpc; /* initialize the first */ ( (struct phdr *) buf ) -> hpc = highpc; /* region of the buffer */ ( (struct phdr *) buf ) -> ncnt = ssiz; o = sizeof(struct phdr); buf = (int *) ( ( (int) buf ) + o ); bufsiz -= o; if ( bufsiz <= 0 ) return; o = ( ( (char *) highpc - (char *) lowpc) ); if( bufsiz < o ) s_scale = ( (float) bufsiz / o ) * SCALE_1_TO_1; else s_scale = SCALE_1_TO_1; moncontrol(1);}/* * Control profiling * profiling is what mcount checks to see if * all the data structures are ready. */voidmoncontrol(mode) int mode;{ if (mode) { /* start */ profil((char*) sbuf + sizeof(struct phdr), ssiz - sizeof(struct phdr), s_lowpc, s_scale); profiling = 0; } else { /* stop */ profil((char *)0, 0, 0, 0); profiling = 3; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -