home *** CD-ROM | disk | FTP | other *** search
- #include <fcntl.h>
-
- /* header of a GPROF type file
- */
- typedef struct {
- long low;
- long high;
- long nbytes;
- } header;
-
- /* entry of a GPROF type file
- */
- typedef struct {
- unsigned long from;
- unsigned long to;
- unsigned long count;
- } MTABE;
-
- /* internal form - sizeof(MTAB) is 4096 for efficiency
- */
- typedef struct MTAB {
- MTABE calls[341];
- struct MTAB *prev;
- } MTAB;
-
- static header h;
- short *histogram asm("mcount_histogram");
- short mcount_skip asm("mcount_skip");
- static int histlen;
- static MTAB *mtab=0;
-
- /* called by functions. Use the pointer it provides to cache
- ** the last used MTABE, so that repeated calls to/from the same
- ** pair works quickly - no lookup.
- */
- void mcount(_to)
- {
- MTAB *m;
- int i;
- int to;
- int ebp;
- int from;
- int mtabi;
- MTABE **cache;
-
- mcount_skip = 1;
- asm("movl %%edx,%0" : "=g" (cache)); /* obtain the cached pointer */
- to = *((&_to)-1) - 12;
- ebp = *((&_to)-2); /* glean the caller's return address from the stack */
- from = ((int *)ebp)[1];
- if (*cache && ((*cache)->from == from) && ((*cache)->to == to))
- {
- /* cache paid off - works quickly */
- (*cache)->count++;
- mcount_skip = 0;
- return;
- }
-
- /* no cache hit - search all mtab tables for a match, or an empty slot */
- mtabi = -1;
- for (m=mtab; m; m=m->prev)
- {
- for (i=0; i<341; i++)
- {
- if (m->calls[i].from == 0)
- {
- /* empty slot - end of table */
- mtabi = i;
- break;
- }
- if ((m->calls[i].from == from) &&
- (m->calls[i].to == to))
- {
- /* found a match - bump count and return */
- m->calls[i].count ++;
- *cache = m->calls + i;
- mcount_skip = 0;
- return;
- }
- }
- }
- if (mtabi != -1)
- {
- /* found an empty - fill it in */
- mtab->calls[mtabi].from = from;
- mtab->calls[mtabi].to = to;
- mtab->calls[mtabi].count = 1;
- *cache = mtab->calls + mtabi;
- mcount_skip = 0;
- return;
- }
- /* lob off another page of memory and initialize the new table */
- m = (MTAB *)sbrk(sizeof(MTAB));
- memset(m, 0, sizeof(MTAB));
- m->prev = mtab;
- mtab = m;
- m->calls[0].from = from;
- m->calls[0].to = to;
- m->calls[0].count = 1;
- *cache = m->calls;
- mcount_skip = 0;
- }
-
- extern int etext;
-
- extern void mcount_isr_init() asm("mcount_isr_init");
- extern void mcount_init() asm("mcount_init");
- void mcount_init()
- {
- /* this is called by gcrt0.s, before the program starts */
- int hs;
- h.low = 0x1020;
- h.high = (int)&etext;
- histlen = (h.high-h.low)/4*sizeof(short);
- h.nbytes = sizeof(header) + histlen;
- histogram = (short *)sbrk(histlen);
- memset(histogram, 0, histlen);
-
- /* here, do whatever it takes to initialize the timer interrupt */
- mcount_isr_init();
- }
-
- extern void mcount_write() asm("mcount_write");
- void mcount_write()
- {
- /* this is called by gcrt0.s, after the program exits. */
- MTAB *m;
- int i, f;
-
- f = open("gmon.out", O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
- write(f, &h, sizeof(header));
- write(f, histogram, histlen);
- for (m=mtab; m; m=m->prev)
- {
- for (i=0; i<341; i++)
- if (m->calls[i].from == 0)
- break;
- write(f, m->calls, i*12);
- }
- close(f);
- }
-