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