xref: /csrg-svn/lib/libc/gmon/gmon.c (revision 4514)
1*4514Speter static	char *sccsid = "@(#)gmon.c	1.1 (Berkeley) 10/15/81";
2*4514Speter 
3*4514Speter #include <stdio.h>
4*4514Speter 
5*4514Speter #include "monitor.h"
6*4514Speter 
7*4514Speter     /*	froms is actually a bunch of unsigned shorts indexing tos */
8*4514Speter static unsigned short	*froms;
9*4514Speter static struct tostruct	*tos = 0;
10*4514Speter static unsigned short	tolimit = 0;
11*4514Speter static char		*s_lowpc = 0;
12*4514Speter static char		*s_highpc = 0;
13*4514Speter 
14*4514Speter static	int	ssiz;
15*4514Speter static	int	*sbuf;
16*4514Speter 
17*4514Speter char	*sbrk();
18*4514Speter #define	MSG "No space for monitor buffer(s)\n"
19*4514Speter 
20*4514Speter 	/*ARGSUSED*/
21*4514Speter exit(code)
22*4514Speter 	register int	code;
23*4514Speter {
24*4514Speter 	fflush(stdout);
25*4514Speter 	_mcleanup();
26*4514Speter 	_cleanup();
27*4514Speter #ifdef lint
28*4514Speter 	code = code;
29*4514Speter #endif lint
30*4514Speter 	asm("	movl r11, r0");
31*4514Speter 	asm("	chmk $1");
32*4514Speter }
33*4514Speter 
34*4514Speter _mstartup(lowpc, highpc)
35*4514Speter 	char	*lowpc;
36*4514Speter 	char	*highpc;
37*4514Speter {
38*4514Speter 	int	monsize;
39*4514Speter 	char	*buffer;
40*4514Speter 	int	textsize;
41*4514Speter 
42*4514Speter 	s_lowpc = lowpc;
43*4514Speter 	s_highpc = highpc;
44*4514Speter 	textsize = ((char *)highpc - (char *)lowpc);
45*4514Speter 	monsize = textsize + sizeof(struct phdr);
46*4514Speter 	buffer = sbrk(monsize);
47*4514Speter 	if ( buffer == (char *) -1 ) {
48*4514Speter 	    write(2, MSG, sizeof(MSG));
49*4514Speter 	    return;
50*4514Speter 	}
51*4514Speter 	froms = (unsigned short *) sbrk(textsize);
52*4514Speter 	if ( froms == (unsigned short *) -1 ) {
53*4514Speter 	    write(2 , MSG , sizeof(MSG) );
54*4514Speter 	    froms = 0;
55*4514Speter 	    return;
56*4514Speter 	}
57*4514Speter 	tos = (struct tostruct *) sbrk(textsize);
58*4514Speter 	if ( tos == (struct tostruct *) -1 ) {
59*4514Speter 	    write(2 , MSG , sizeof(MSG) );
60*4514Speter 	    froms = 0;
61*4514Speter 	    tos = 0;
62*4514Speter 	    return;
63*4514Speter 	}
64*4514Speter 	tolimit = textsize / sizeof(struct tostruct);
65*4514Speter 	tos[0].link = 0;
66*4514Speter 	monitor(lowpc, highpc, buffer, monsize);
67*4514Speter }
68*4514Speter 
69*4514Speter _peek()
70*4514Speter {
71*4514Speter }
72*4514Speter 
73*4514Speter _mcleanup()
74*4514Speter {
75*4514Speter     FILE	*fd;
76*4514Speter     int		fromindex;
77*4514Speter     char	*frompc;
78*4514Speter     int		toindex;
79*4514Speter     int		textsize;
80*4514Speter 
81*4514Speter     monitor((int (*)())0);
82*4514Speter     fd = fopen( "dmon.out" , "w" );
83*4514Speter     if ( fd == NULL ) {
84*4514Speter 	perror( "mcount: mon.out2" );
85*4514Speter 	return;
86*4514Speter     }
87*4514Speter     fwrite( sbuf , ssiz , 1 , fd );
88*4514Speter     textsize = s_highpc - s_lowpc;
89*4514Speter     for ( fromindex = 0 ; fromindex < textsize>>1 ; fromindex++ ) {
90*4514Speter 	if ( froms[fromindex] == 0 ) {
91*4514Speter 	    continue;
92*4514Speter 	}
93*4514Speter 	frompc = s_lowpc + (fromindex<<1);
94*4514Speter 	for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {
95*4514Speter #	    ifdef DEBUG
96*4514Speter 		printf( "[mcleanup] frompc %d selfpc %d count %d\n" ,
97*4514Speter 			frompc , tos[toindex].selfpc , tos[toindex].count );
98*4514Speter #	    endif DEBUG
99*4514Speter 	    fwrite( &frompc, 1, sizeof frompc, fd );
100*4514Speter 	    fwrite( &tos[toindex].selfpc, 1, sizeof tos[toindex].selfpc, fd );
101*4514Speter 	    fwrite( &tos[toindex].count, 1, sizeof tos[toindex].count, fd );
102*4514Speter 	}
103*4514Speter     }
104*4514Speter     fclose( fd );
105*4514Speter }
106*4514Speter 
107*4514Speter /*
108*4514Speter  *	This routine is massaged so that it may be jsb'ed to
109*4514Speter  */
110*4514Speter asm("#define _mcount mcount");
111*4514Speter mcount()
112*4514Speter {
113*4514Speter     register char		*selfpc;	/* r11 */
114*4514Speter     register unsigned short	*frompcindex;	/* r10 */
115*4514Speter     register struct tostruct	*top;		/* r9 */
116*4514Speter     /* !!! if you add anything, you have to fix the pushr and popr !!! */
117*4514Speter 
118*4514Speter     asm( "	forgot to run ex script on monitor.s" );
119*4514Speter     asm( "#define r11 r5" );
120*4514Speter     asm( "#define r10 r4" );
121*4514Speter     asm( "#define r9 r3" );
122*4514Speter #ifdef lint
123*4514Speter     selfpc = (char *) 0;
124*4514Speter     frompcindex = 0;
125*4514Speter #else not lint
126*4514Speter 	/*
127*4514Speter 	 *	we've pushed the old r11, r10, and r9,
128*4514Speter 	 *	so the return address for a plain old jsb
129*4514Speter 	 *	which should be at 0(sp) is now at 12(sp)
130*4514Speter 	 */
131*4514Speter     asm("	movl (sp), r11");	/* selfpc = ... (jsb frame) */
132*4514Speter     asm("	movl 16(fp), r10");	/* frompcindex =     (calls frame) */
133*4514Speter #endif not lint
134*4514Speter     /*
135*4514Speter      *	check that we are profiling
136*4514Speter      */
137*4514Speter     if ( tos == 0 ) {
138*4514Speter 	goto out;
139*4514Speter     }
140*4514Speter     frompcindex = &froms[ ( (long) frompcindex - (long) s_lowpc ) >> 1 ];
141*4514Speter     if ( *frompcindex == 0 ) {
142*4514Speter 	*frompcindex = ++tos[0].link;
143*4514Speter 	if ( *frompcindex >= tolimit ) {
144*4514Speter 	    goto overflow;
145*4514Speter 	}
146*4514Speter 	top = &tos[ *frompcindex ];
147*4514Speter 	top->selfpc = selfpc;
148*4514Speter 	top->count = 0;
149*4514Speter 	top->link = 0;
150*4514Speter     } else {
151*4514Speter 	top = &tos[ *frompcindex ];
152*4514Speter     }
153*4514Speter     for ( ; /*break*/ ; top = &tos[ top -> link ] ) {
154*4514Speter 	if ( top -> selfpc == selfpc ) {
155*4514Speter 	    top -> count++;
156*4514Speter 	    break;
157*4514Speter 	}
158*4514Speter 	if ( top -> link == 0 ) {
159*4514Speter 	    top -> link = ++tos[0].link;
160*4514Speter 	    if ( top -> link >= tolimit )
161*4514Speter 		goto overflow;
162*4514Speter 	    top = &tos[ top -> link ];
163*4514Speter 	    top -> selfpc = selfpc;
164*4514Speter 	    top -> count = 1;
165*4514Speter 	    top -> link = 0;
166*4514Speter 	    break;
167*4514Speter 	}
168*4514Speter     }
169*4514Speter out:
170*4514Speter     asm( "	rsb" );
171*4514Speter     asm( "#undef r11" );
172*4514Speter     asm( "#undef r10" );
173*4514Speter     asm( "#undef r9" );
174*4514Speter     asm( "#undef _mcount");
175*4514Speter 
176*4514Speter overflow:
177*4514Speter #   define	TOLIMIT	"mcount: tos overflow\n"
178*4514Speter     write( 2 , TOLIMIT , sizeof( TOLIMIT ) );
179*4514Speter     tos = 0;
180*4514Speter     froms = 0;
181*4514Speter     goto out;
182*4514Speter }
183*4514Speter 
184*4514Speter monitor(lowpc, highpc, buf, bufsiz)
185*4514Speter 	char	*lowpc;
186*4514Speter 	/*VARARGS1*/
187*4514Speter 	char	*highpc;
188*4514Speter 	int *buf, bufsiz;
189*4514Speter {
190*4514Speter 	register o;
191*4514Speter 
192*4514Speter 	if (lowpc == 0) {
193*4514Speter 		profil((char *)0, 0, 0, 0);
194*4514Speter 		return;
195*4514Speter 	}
196*4514Speter 	sbuf = buf;
197*4514Speter 	ssiz = bufsiz;
198*4514Speter 	((struct phdr *)buf)->lpc = lowpc;
199*4514Speter 	((struct phdr *)buf)->hpc = highpc;
200*4514Speter 	((struct phdr *)buf)->ncnt = ssiz;
201*4514Speter 	o = sizeof(struct phdr);
202*4514Speter 	buf = (int *) (((int)buf) + o);
203*4514Speter 	bufsiz -= o;
204*4514Speter 	if (bufsiz<=0)
205*4514Speter 		return;
206*4514Speter 	o = (((char *)highpc - (char *)lowpc)>>1);
207*4514Speter 	if(bufsiz < o)
208*4514Speter 		o = ((float) bufsiz / o) * 32768;
209*4514Speter 	else
210*4514Speter 		o = 0177777;
211*4514Speter 	profil(buf, bufsiz, lowpc, o);
212*4514Speter }
213*4514Speter 
214