|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #if defined(LIBC_SCCS) && !defined(lint)
8: static char sccsid[] = "@(#)gmon.c 5.3 (Berkeley) 3/9/86";
9: #endif LIBC_SCCS and not lint
10:
11: #ifdef DEBUG
12: #include <stdio.h>
13: #endif DEBUG
14:
15: #include "gmon.h"
16:
17: /*
18: * froms is actually a bunch of unsigned shorts indexing tos
19: */
20: static int profiling = 3;
21: static unsigned short *froms;
22: static struct tostruct *tos = 0;
23: static long tolimit = 0;
24: static char *s_lowpc = 0;
25: static char *s_highpc = 0;
26: static unsigned long s_textsize = 0;
27:
28: static int ssiz;
29: static char *sbuf;
30: static int s_scale;
31: /* see profil(2) where this is describe (incorrectly) */
32: #define SCALE_1_TO_1 0x10000L
33:
34: #define MSG "No space for monitor buffer(s)\n"
35:
36: monstartup(lowpc, highpc)
37: char *lowpc;
38: char *highpc;
39: {
40: int monsize;
41: char *buffer;
42: char *sbrk();
43: extern char *minbrk;
44:
45: /*
46: * round lowpc and highpc to multiples of the density we're using
47: * so the rest of the scaling (here and in gprof) stays in ints.
48: */
49: lowpc = (char *)
50: ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
51: s_lowpc = lowpc;
52: highpc = (char *)
53: ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
54: s_highpc = highpc;
55: s_textsize = highpc - lowpc;
56: monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
57: buffer = sbrk( monsize );
58: if ( buffer == (char *) -1 ) {
59: write( 2 , MSG , sizeof(MSG) );
60: return;
61: }
62: froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION );
63: if ( froms == (unsigned short *) -1 ) {
64: write( 2 , MSG , sizeof(MSG) );
65: froms = 0;
66: return;
67: }
68: tolimit = s_textsize * ARCDENSITY / 100;
69: if ( tolimit < MINARCS ) {
70: tolimit = MINARCS;
71: } else if ( tolimit > 65534 ) {
72: tolimit = 65534;
73: }
74: tos = (struct tostruct *) sbrk( tolimit * sizeof( struct tostruct ) );
75: if ( tos == (struct tostruct *) -1 ) {
76: write( 2 , MSG , sizeof(MSG) );
77: froms = 0;
78: tos = 0;
79: return;
80: }
81: minbrk = sbrk(0);
82: tos[0].link = 0;
83: monitor( lowpc , highpc , buffer , monsize , tolimit );
84: }
85:
86: _mcleanup()
87: {
88: int fd;
89: int fromindex;
90: int endfrom;
91: char *frompc;
92: int toindex;
93: struct rawarc rawarc;
94:
95: fd = creat( "gmon.out" , 0666 );
96: if ( fd < 0 ) {
97: perror( "mcount: gmon.out" );
98: return;
99: }
100: # ifdef DEBUG
101: fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
102: # endif DEBUG
103: write( fd , sbuf , ssiz );
104: endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
105: for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) {
106: if ( froms[fromindex] == 0 ) {
107: continue;
108: }
109: frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms));
110: for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {
111: # ifdef DEBUG
112: fprintf( stderr ,
113: "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
114: frompc , tos[toindex].selfpc , tos[toindex].count );
115: # endif DEBUG
116: rawarc.raw_frompc = (unsigned long) frompc;
117: rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
118: rawarc.raw_count = tos[toindex].count;
119: write( fd , &rawarc , sizeof rawarc );
120: }
121: }
122: close( fd );
123: }
124:
125: asm(".text");
126: asm(".align 2");
127: asm("#the beginning of mcount()");
128: asm(".data");
129: mcount()
130: {
131: register char *selfpc; /* r11 => r5 */
132: register unsigned short *frompcindex; /* r10 => r4 */
133: register struct tostruct *top; /* r9 => r3 */
134: register struct tostruct *prevtop; /* r8 => r2 */
135: register long toindex; /* r7 => r1 */
136:
137: /*
138: * find the return address for mcount,
139: * and the return address for mcount's caller.
140: */
141: asm(" .text"); /* make sure we're in text space */
142: asm(" movl (sp), r11"); /* selfpc = ... (jsb frame) */
143: asm(" movl 16(fp), r10"); /* frompcindex = (calls frame) */
144: /*
145: * check that we are profiling
146: * and that we aren't recursively invoked.
147: */
148: if (profiling) {
149: goto out;
150: }
151: profiling++;
152: /*
153: * check that frompcindex is a reasonable pc value.
154: * for example: signal catchers get called from the stack,
155: * not from text space. too bad.
156: */
157: frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
158: if ((unsigned long)frompcindex > s_textsize) {
159: goto done;
160: }
161: frompcindex =
162: &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
163: toindex = *frompcindex;
164: if (toindex == 0) {
165: /*
166: * first time traversing this arc
167: */
168: toindex = ++tos[0].link;
169: if (toindex >= tolimit) {
170: goto overflow;
171: }
172: *frompcindex = toindex;
173: top = &tos[toindex];
174: top->selfpc = selfpc;
175: top->count = 1;
176: top->link = 0;
177: goto done;
178: }
179: top = &tos[toindex];
180: if (top->selfpc == selfpc) {
181: /*
182: * arc at front of chain; usual case.
183: */
184: top->count++;
185: goto done;
186: }
187: /*
188: * have to go looking down chain for it.
189: * top points to what we are looking at,
190: * prevtop points to previous top.
191: * we know it is not at the head of the chain.
192: */
193: for (; /* goto done */; ) {
194: if (top->link == 0) {
195: /*
196: * top is end of the chain and none of the chain
197: * had top->selfpc == selfpc.
198: * so we allocate a new tostruct
199: * and link it to the head of the chain.
200: */
201: toindex = ++tos[0].link;
202: if (toindex >= tolimit) {
203: goto overflow;
204: }
205: top = &tos[toindex];
206: top->selfpc = selfpc;
207: top->count = 1;
208: top->link = *frompcindex;
209: *frompcindex = toindex;
210: goto done;
211: }
212: /*
213: * otherwise, check the next arc on the chain.
214: */
215: prevtop = top;
216: top = &tos[top->link];
217: if (top->selfpc == selfpc) {
218: /*
219: * there it is.
220: * increment its count
221: * move it to the head of the chain.
222: */
223: top->count++;
224: toindex = prevtop->link;
225: prevtop->link = top->link;
226: top->link = *frompcindex;
227: *frompcindex = toindex;
228: goto done;
229: }
230:
231: }
232: done:
233: profiling--;
234: /* and fall through */
235: out:
236: asm(" rsb");
237:
238: overflow:
239: profiling++; /* halt further profiling */
240: # define TOLIMIT "mcount: tos overflow\n"
241: write(2, TOLIMIT, sizeof(TOLIMIT));
242: goto out;
243: }
244: asm(".text");
245: asm("#the end of mcount()");
246: asm(".data");
247:
248: /*VARARGS1*/
249: monitor( lowpc , highpc , buf , bufsiz , nfunc )
250: char *lowpc;
251: char *highpc;
252: char *buf; /* declared ``short buffer[]'' in monitor(3) */
253: int bufsiz;
254: int nfunc; /* not used, available for compatability only */
255: {
256: register o;
257:
258: if ( lowpc == 0 ) {
259: moncontrol(0);
260: _mcleanup();
261: return;
262: }
263: sbuf = buf;
264: ssiz = bufsiz;
265: ( (struct phdr *) buf ) -> lpc = lowpc;
266: ( (struct phdr *) buf ) -> hpc = highpc;
267: ( (struct phdr *) buf ) -> ncnt = ssiz;
268: bufsiz -= sizeof(struct phdr);
269: if ( bufsiz <= 0 )
270: return;
271: o = highpc - lowpc;
272: if( bufsiz < o )
273: s_scale = ( (float) bufsiz / o ) * SCALE_1_TO_1;
274: else
275: s_scale = SCALE_1_TO_1;
276: moncontrol(1);
277: }
278:
279: /*
280: * Control profiling
281: * profiling is what mcount checks to see if
282: * all the data structures are ready.
283: */
284: moncontrol(mode)
285: int mode;
286: {
287: if (mode) {
288: /* start */
289: profil(sbuf + sizeof(struct phdr), ssiz - sizeof(struct phdr),
290: s_lowpc, s_scale);
291: profiling = 0;
292: } else {
293: /* stop */
294: profil((char *)0, 0, 0, 0);
295: profiling = 3;
296: }
297: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.