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