updates for 4.3
[unix-history] / usr / src / sys / kern / subr_prof.c
... / ...
CommitLineData
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 */
8
9/* last integrated from: gmon.c 4.10 (Berkeley) 1/14/83 */
10
11#ifdef GPROF
12#include "gprof.h"
13#include "param.h"
14#include "systm.h"
15
16/*
17 * Froms is actually a bunch of unsigned shorts indexing tos
18 */
19int profiling = 3;
20u_short *froms;
21struct tostruct *tos = 0;
22long tolimit = 0;
23#ifdef vax
24char *s_lowpc = (char *)0x80000000;
25#endif
26extern char etext;
27char *s_highpc = &etext;
28u_long s_textsize = 0;
29int ssiz;
30u_short *sbuf;
31u_short *kcount;
32
33kmstartup()
34{
35 u_long fromssize, tossize;
36
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));
45 s_textsize = s_highpc - s_lowpc;
46 printf("Profiling kernel, s_textsize=%d [%x..%x]\n",
47 s_textsize, s_lowpc, s_highpc);
48 ssiz = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
49 sbuf = (u_short *)calloc(ssiz);
50 if (sbuf == 0) {
51 printf("No space for monitor buffer(s)\n");
52 return;
53 }
54 blkclr((caddr_t)sbuf, ssiz);
55 fromssize = s_textsize / HASHFRACTION;
56 froms = (u_short *)calloc(fromssize);
57 if (froms == 0) {
58 printf("No space for monitor buffer(s)\n");
59 cfreemem(sbuf, ssiz);
60 sbuf = 0;
61 return;
62 }
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);
71 tos = (struct tostruct *)calloc(tossize);
72 if (tos == 0) {
73 printf("No space for monitor buffer(s)\n");
74 cfreemem(sbuf, ssiz);
75 sbuf = 0;
76 cfreemem(froms, fromssize);
77 froms = 0;
78 return;
79 }
80 blkclr((caddr_t)tos, tossize);
81 tos[0].link = 0;
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
87 /*
88 * profiling is what mcount checks to see if
89 * all the data structures are ready!!!
90 */
91 profiling = 0; /* patch by hand when you're ready */
92#endif
93}
94
95#ifdef vax
96/*
97 * This routine is massaged so that it may be jsb'ed to
98 */
99asm(".text");
100asm("#the beginning of mcount()");
101asm(".data");
102mcount()
103{
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 */
109 static int s;
110
111#ifdef lint
112 selfpc = (char *)0;
113 frompcindex = 0;
114#else not lint
115 /*
116 * find the return address for mcount,
117 * and the return address for mcount's caller.
118 */
119 asm(" .text"); /* make sure we're in text space */
120 asm(" movl (sp), r11"); /* selfpc = ... (jsb frame) */
121 asm(" movl 16(fp), r10"); /* frompcindex = (calls frame) */
122#endif not lint
123 /*
124 * check that we are profiling
125 */
126 if (profiling) {
127 goto out;
128 }
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();
135 /*
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.
139 */
140 frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
141 if ((unsigned long)frompcindex > s_textsize) {
142 goto done;
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) {
153 goto overflow;
154 }
155 *frompcindex = toindex;
156 top = &tos[toindex];
157 top->selfpc = selfpc;
158 top->count = 1;
159 top->link = 0;
160 goto done;
161 }
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];
200 if (top->selfpc == selfpc) {
201 /*
202 * there it is.
203 * increment its count
204 * move it to the head of the chain.
205 */
206 top->count++;
207 toindex = prevtop->link;
208 prevtop->link = top->link;
209 top->link = *frompcindex;
210 *frompcindex = toindex;
211 goto done;
212 }
213
214 }
215done:
216 splx(s);
217 /* and fall through */
218out:
219 asm(" rsb");
220
221overflow:
222 profiling = 3;
223 printf("mcount: tos overflow\n");
224 goto out;
225}
226asm(".text");
227asm("#the end of mcount()");
228asm(".data");
229#endif vax
230#endif GPROF