|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)subr_mcount.c 7.9 (Berkeley) 6/30/90
21: */
22:
23: #ifdef GPROF
24: #include "gprof.h"
25: #include "param.h"
26: #include "systm.h"
27: #include "malloc.h"
28:
29: /*
30: * Froms is actually a bunch of unsigned shorts indexing tos
31: */
32: int profiling = 3;
33: u_short *froms;
34: struct tostruct *tos = 0;
35: long tolimit = 0;
36: char *s_lowpc = (char *)KERNBASE;
37: extern char etext;
38: char *s_highpc = &etext;
39: u_long s_textsize = 0;
40: int ssiz;
41: u_short *sbuf;
42: u_short *kcount;
43:
44: kmstartup()
45: {
46: u_long fromssize, tossize;
47:
48: /*
49: * Round lowpc and highpc to multiples of the density we're using
50: * so the rest of the scaling (here and in gprof) stays in ints.
51: */
52: s_lowpc = (char *)
53: ROUNDDOWN((unsigned)s_lowpc, HISTFRACTION*sizeof (HISTCOUNTER));
54: s_highpc = (char *)
55: ROUNDUP((unsigned)s_highpc, HISTFRACTION*sizeof (HISTCOUNTER));
56: s_textsize = s_highpc - s_lowpc;
57: printf("Profiling kernel, s_textsize=%d [%x..%x]\n",
58: s_textsize, s_lowpc, s_highpc);
59: ssiz = (s_textsize / HISTFRACTION) + sizeof (struct phdr);
60: sbuf = (u_short *)malloc(ssiz, M_GPROF, M_WAITOK);
61: if (sbuf == 0) {
62: printf("No space for monitor buffer(s)\n");
63: return;
64: }
65: bzero(sbuf, ssiz);
66: fromssize = s_textsize / HASHFRACTION;
67: froms = (u_short *)malloc(fromssize, M_GPROF, M_WAITOK);
68: if (froms == 0) {
69: printf("No space for monitor buffer(s)\n");
70: free(sbuf, M_GPROF);
71: sbuf = 0;
72: return;
73: }
74: bzero(froms, fromssize);
75: tolimit = s_textsize * ARCDENSITY / 100;
76: if (tolimit < MINARCS)
77: tolimit = MINARCS;
78: else if (tolimit > (0xffff - 1))
79: tolimit = 0xffff - 1;
80: tossize = tolimit * sizeof (struct tostruct);
81: tos = (struct tostruct *)malloc(tossize, M_GPROF, M_WAITOK);
82: if (tos == 0) {
83: printf("No space for monitor buffer(s)\n");
84: free(sbuf, M_GPROF), sbuf = 0;
85: free(froms, M_GPROF), froms = 0;
86: return;
87: }
88: bzero(tos, tossize);
89: tos[0].link = 0;
90: ((struct phdr *)sbuf)->lpc = s_lowpc;
91: ((struct phdr *)sbuf)->hpc = s_highpc;
92: ((struct phdr *)sbuf)->ncnt = ssiz;
93: kcount = (u_short *)(((int)sbuf) + sizeof (struct phdr));
94: }
95:
96: /*
97: * Special, non-profiled versions
98: */
99: #if defined(hp300) && !defined(__GNUC__)
100: #define splhigh _splhigh
101: #define splx _splx
102: #endif
103:
104: /*
105: * This routine is massaged so that it may be jsb'ed to on vax.
106: */
107: asm(".text");
108: asm("#the beginning of mcount()");
109: asm(".data");
110: mcount()
111: {
112: register char *selfpc; /* r11 => r5 */
113: register u_short *frompcindex; /* r10 => r4 */
114: register struct tostruct *top; /* r9 => r3 */
115: register struct tostruct *prevtop; /* r8 => r2 */
116: register long toindex; /* r7 => r1 */
117: static int s;
118:
119: asm(" .text"); /* make sure we're in text space */
120: /*
121: * Check that we are profiling.
122: */
123: if (profiling)
124: goto out;
125: /*
126: * Find the return address for mcount,
127: * and the return address for mcount's caller.
128: */
129: #ifdef lint
130: selfpc = (char *)0;
131: frompcindex = 0;
132: #else
133: ; /* avoid label botch */
134: #ifdef __GNUC__
135: #if defined(vax)
136: Fix Me!!
137: #endif
138: #if defined(tahoe)
139: Fix Me!!
140: #endif
141: #if defined(hp300)
142: /*
143: * selfpc = pc pushed by mcount jsr,
144: * frompcindex = pc pushed by jsr into self.
145: * In GCC the caller's stack frame has already been built so we
146: * have to chase a6 to find caller's raddr. This assumes that all
147: * routines we are profiling were built with GCC and that all
148: * profiled routines use link/unlk.
149: */
150: asm("movl a6@(4),%0" : "=r" (selfpc));
151: asm("movl a6@(0)@(4),%0" : "=r" (frompcindex));
152: #endif
153: #else
154: #if defined(vax)
155: asm(" movl (sp), r11"); /* selfpc = ... (jsb frame) */
156: asm(" movl 16(fp), r10"); /* frompcindex = (calls frame) */
157: #endif
158: #if defined(tahoe)
159: asm(" movl -8(fp),r12"); /* selfpc = callf frame */
160: asm(" movl (fp),r11");
161: asm(" movl -8(r11),r11"); /* frompcindex = 1 callf frame back */
162: #endif
163: #if defined(hp300)
164: asm(" .text"); /* make sure we're in text space */
165: asm(" movl a6@(4),a5"); /* selfpc = pc pushed by mcount jsr */
166: asm(" movl a6@(8),a4"); /* frompcindex = pc pushed by jsr into
167: self, stack frame not yet built */
168: #endif
169: #endif /* not __GNUC__ */
170: #endif /* not lint */
171: /*
172: * Insure that we cannot be recursively invoked.
173: * this requires that splhigh() and splx() below
174: * do NOT call mcount!
175: */
176: #if defined(hp300) && defined(__GNUC__)
177: asm("movw sr,%0" : "=g" (s));
178: asm("movw #0x2700,sr");
179: #else
180: s = splhigh();
181: #endif
182: /*
183: * Check that frompcindex is a reasonable pc value.
184: * For example: signal catchers get called from the stack,
185: * not from text space. too bad.
186: */
187: frompcindex = (u_short *)((long)frompcindex - (long)s_lowpc);
188: if ((u_long)frompcindex > s_textsize)
189: goto done;
190: frompcindex =
191: &froms[((long)frompcindex) / (HASHFRACTION * sizeof (*froms))];
192: toindex = *frompcindex;
193: if (toindex == 0) {
194: /*
195: * First time traversing this arc
196: */
197: toindex = ++tos[0].link;
198: if (toindex >= tolimit)
199: goto overflow;
200: *frompcindex = toindex;
201: top = &tos[toindex];
202: top->selfpc = selfpc;
203: top->count = 1;
204: top->link = 0;
205: goto done;
206: }
207: top = &tos[toindex];
208: if (top->selfpc == selfpc) {
209: /*
210: * Arc at front of chain; usual case.
211: */
212: top->count++;
213: goto done;
214: }
215: /*
216: * Have to go looking down chain for it.
217: * Top points to what we are looking at,
218: * prevtop points to previous top.
219: * We know it is not at the head of the chain.
220: */
221: for (; /* goto done */; ) {
222: if (top->link == 0) {
223: /*
224: * Top is end of the chain and none of the chain
225: * had top->selfpc == selfpc.
226: * So we allocate a new tostruct
227: * and link it to the head of the chain.
228: */
229: toindex = ++tos[0].link;
230: if (toindex >= tolimit)
231: goto overflow;
232: top = &tos[toindex];
233: top->selfpc = selfpc;
234: top->count = 1;
235: top->link = *frompcindex;
236: *frompcindex = toindex;
237: goto done;
238: }
239: /*
240: * Otherwise, check the next arc on the chain.
241: */
242: prevtop = top;
243: top = &tos[top->link];
244: if (top->selfpc == selfpc) {
245: /*
246: * There it is, increment its count and
247: * move it to the head of the chain.
248: */
249: top->count++;
250: toindex = prevtop->link;
251: prevtop->link = top->link;
252: top->link = *frompcindex;
253: *frompcindex = toindex;
254: goto done;
255: }
256:
257: }
258: done:
259: #if defined(hp300) && defined(__GNUC__)
260: asm("movw %0,sr" : : "g" (s));
261: #else
262: splx(s);
263: #endif
264: /* and fall through */
265: out:
266: #if defined(vax)
267: asm(" rsb");
268: #endif
269: return;
270: overflow:
271: profiling = 3;
272: printf("mcount: tos overflow\n");
273: goto out;
274: }
275: asm(".text");
276: asm("#the end of mcount()");
277: asm(".data");
278: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.