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