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