try to make display narrower
[unix-history] / usr / src / lib / libc / gmon / gmon.c
CommitLineData
586c39b1
DF
1/*
2 * Copyright (c) 1980 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
2ce81398 7#if defined(LIBC_SCCS) && !defined(lint)
44be2432 8static char sccsid[] = "@(#)gmon.c 5.4 (Berkeley) %G%";
2ce81398 9#endif LIBC_SCCS and not lint
50084e08 10
bb9c5045 11#ifdef DEBUG
50084e08 12#include <stdio.h>
bb9c5045 13#endif DEBUG
50084e08 14
ee56ba6f 15#include "gmon.h"
387d0540
PK
16
17 /*
18 * froms is actually a bunch of unsigned shorts indexing tos
19 */
5a9da8d5 20static int profiling = 3;
50084e08
PK
21static unsigned short *froms;
22static struct tostruct *tos = 0;
019e8582 23static long tolimit = 0;
50084e08
PK
24static char *s_lowpc = 0;
25static char *s_highpc = 0;
3a2b18f4 26static unsigned long s_textsize = 0;
50084e08 27
387d0540 28static int ssiz;
37a37eeb 29static char *sbuf;
13c3ba68 30static int s_scale;
37a37eeb
PK
31 /* see profil(2) where this is describe (incorrectly) */
32#define SCALE_1_TO_1 0x10000L
50084e08 33
50084e08
PK
34#define MSG "No space for monitor buffer(s)\n"
35
ee56ba6f 36monstartup(lowpc, highpc)
387d0540
PK
37 char *lowpc;
38 char *highpc;
50084e08 39{
3a2b18f4
PK
40 int monsize;
41 char *buffer;
42 char *sbrk();
b8c5b964 43 extern char *minbrk;
50084e08 44
019e8582
PK
45 /*
46 * round lowpc and highpc to multiples of the density we're using
47 * so the rest of the scaling (here and in gprof) stays in ints.
48 */
49 lowpc = (char *)
50 ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
387d0540 51 s_lowpc = lowpc;
019e8582
PK
52 highpc = (char *)
53 ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
387d0540 54 s_highpc = highpc;
3a2b18f4 55 s_textsize = highpc - lowpc;
019e8582 56 monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
387d0540
PK
57 buffer = sbrk( monsize );
58 if ( buffer == (char *) -1 ) {
44be2432 59 write( 2 , MSG , sizeof(MSG) - 1 );
387d0540
PK
60 return;
61 }
f4d8fa4a 62 froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION );
387d0540 63 if ( froms == (unsigned short *) -1 ) {
44be2432 64 write( 2 , MSG , sizeof(MSG) - 1 );
387d0540
PK
65 froms = 0;
66 return;
67 }
5a9da8d5
KM
68 tolimit = s_textsize * ARCDENSITY / 100;
69 if ( tolimit < MINARCS ) {
70 tolimit = MINARCS;
71 } else if ( tolimit > 65534 ) {
72 tolimit = 65534;
4dff44be 73 }
5a9da8d5 74 tos = (struct tostruct *) sbrk( tolimit * sizeof( struct tostruct ) );
387d0540 75 if ( tos == (struct tostruct *) -1 ) {
44be2432 76 write( 2 , MSG , sizeof(MSG) - 1 );
387d0540
PK
77 froms = 0;
78 tos = 0;
79 return;
80 }
b8c5b964 81 minbrk = sbrk(0);
387d0540 82 tos[0].link = 0;
5a9da8d5 83 monitor( lowpc , highpc , buffer , monsize , tolimit );
50084e08
PK
84}
85
86_mcleanup()
87{
bb9c5045
KM
88 int fd;
89 int fromindex;
f4d8fa4a 90 int endfrom;
bb9c5045
KM
91 char *frompc;
92 int toindex;
93 struct rawarc rawarc;
50084e08 94
bb9c5045
KM
95 fd = creat( "gmon.out" , 0666 );
96 if ( fd < 0 ) {
387d0540 97 perror( "mcount: gmon.out" );
50084e08
PK
98 return;
99 }
387d0540
PK
100# ifdef DEBUG
101 fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
102# endif DEBUG
bb9c5045 103 write( fd , sbuf , ssiz );
f4d8fa4a
KM
104 endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
105 for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) {
50084e08
PK
106 if ( froms[fromindex] == 0 ) {
107 continue;
108 }
f4d8fa4a 109 frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms));
50084e08
PK
110 for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {
111# ifdef DEBUG
22f3ec41
PK
112 fprintf( stderr ,
113 "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
50084e08
PK
114 frompc , tos[toindex].selfpc , tos[toindex].count );
115# endif DEBUG
bb9c5045
KM
116 rawarc.raw_frompc = (unsigned long) frompc;
117 rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
118 rawarc.raw_count = tos[toindex].count;
119 write( fd , &rawarc , sizeof rawarc );
50084e08
PK
120 }
121 }
bb9c5045 122 close( fd );
50084e08
PK
123}
124
019e8582 125asm(".text");
13c3ba68 126asm(".align 2");
019e8582
PK
127asm("#the beginning of mcount()");
128asm(".data");
50084e08
PK
129mcount()
130{
019e8582
PK
131 register char *selfpc; /* r11 => r5 */
132 register unsigned short *frompcindex; /* r10 => r4 */
133 register struct tostruct *top; /* r9 => r3 */
134 register struct tostruct *prevtop; /* r8 => r2 */
135 register long toindex; /* r7 => r1 */
019e8582 136
50084e08 137 /*
785a53a1
PK
138 * find the return address for mcount,
139 * and the return address for mcount's caller.
50084e08 140 */
019e8582
PK
141 asm(" .text"); /* make sure we're in text space */
142 asm(" movl (sp), r11"); /* selfpc = ... (jsb frame) */
143 asm(" movl 16(fp), r10"); /* frompcindex = (calls frame) */
785a53a1
PK
144 /*
145 * check that we are profiling
387d0540 146 * and that we aren't recursively invoked.
785a53a1 147 */
019e8582
PK
148 if (profiling) {
149 goto out;
150 }
5a9da8d5 151 profiling++;
785a53a1
PK
152 /*
153 * check that frompcindex is a reasonable pc value.
154 * for example: signal catchers get called from the stack,
155 * not from text space. too bad.
156 */
019e8582
PK
157 frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
158 if ((unsigned long)frompcindex > s_textsize) {
159 goto done;
50084e08 160 }
019e8582 161 frompcindex =
f4d8fa4a 162 &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
019e8582
PK
163 toindex = *frompcindex;
164 if (toindex == 0) {
165 /*
166 * first time traversing this arc
167 */
168 toindex = ++tos[0].link;
169 if (toindex >= tolimit) {
170 goto overflow;
171 }
172 *frompcindex = toindex;
173 top = &tos[toindex];
174 top->selfpc = selfpc;
175 top->count = 1;
176 top->link = 0;
177 goto done;
50084e08 178 }
019e8582
PK
179 top = &tos[toindex];
180 if (top->selfpc == selfpc) {
181 /*
182 * arc at front of chain; usual case.
183 */
184 top->count++;
185 goto done;
186 }
187 /*
188 * have to go looking down chain for it.
189 * top points to what we are looking at,
190 * prevtop points to previous top.
191 * we know it is not at the head of the chain.
192 */
193 for (; /* goto done */; ) {
194 if (top->link == 0) {
195 /*
196 * top is end of the chain and none of the chain
197 * had top->selfpc == selfpc.
198 * so we allocate a new tostruct
199 * and link it to the head of the chain.
200 */
201 toindex = ++tos[0].link;
202 if (toindex >= tolimit) {
203 goto overflow;
204 }
205 top = &tos[toindex];
206 top->selfpc = selfpc;
207 top->count = 1;
208 top->link = *frompcindex;
209 *frompcindex = toindex;
210 goto done;
211 }
212 /*
213 * otherwise, check the next arc on the chain.
214 */
215 prevtop = top;
216 top = &tos[top->link];
217 if (top->selfpc == selfpc) {
218 /*
219 * there it is.
220 * increment its count
221 * move it to the head of the chain.
222 */
223 top->count++;
224 toindex = prevtop->link;
225 prevtop->link = top->link;
226 top->link = *frompcindex;
227 *frompcindex = toindex;
228 goto done;
229 }
230
50084e08 231 }
785a53a1 232done:
5a9da8d5 233 profiling--;
019e8582 234 /* and fall through */
50084e08 235out:
019e8582 236 asm(" rsb");
50084e08
PK
237
238overflow:
5a9da8d5 239 profiling++; /* halt further profiling */
50084e08 240# define TOLIMIT "mcount: tos overflow\n"
44be2432 241 write(2, TOLIMIT, sizeof(TOLIMIT) - 1);
019e8582 242 goto out;
50084e08 243}
019e8582
PK
244asm(".text");
245asm("#the end of mcount()");
246asm(".data");
50084e08 247
ee56ba6f
KM
248/*VARARGS1*/
249monitor( lowpc , highpc , buf , bufsiz , nfunc )
387d0540 250 char *lowpc;
387d0540 251 char *highpc;
37a37eeb
PK
252 char *buf; /* declared ``short buffer[]'' in monitor(3) */
253 int bufsiz;
ee56ba6f 254 int nfunc; /* not used, available for compatability only */
50084e08 255{
387d0540 256 register o;
50084e08 257
387d0540 258 if ( lowpc == 0 ) {
13c3ba68 259 moncontrol(0);
ee56ba6f 260 _mcleanup();
387d0540
PK
261 return;
262 }
263 sbuf = buf;
264 ssiz = bufsiz;
265 ( (struct phdr *) buf ) -> lpc = lowpc;
266 ( (struct phdr *) buf ) -> hpc = highpc;
267 ( (struct phdr *) buf ) -> ncnt = ssiz;
37a37eeb 268 bufsiz -= sizeof(struct phdr);
387d0540
PK
269 if ( bufsiz <= 0 )
270 return;
37a37eeb 271 o = highpc - lowpc;
387d0540 272 if( bufsiz < o )
37a37eeb 273 s_scale = ( (float) bufsiz / o ) * SCALE_1_TO_1;
387d0540 274 else
37a37eeb 275 s_scale = SCALE_1_TO_1;
13c3ba68
PK
276 moncontrol(1);
277}
278
279/*
280 * Control profiling
281 * profiling is what mcount checks to see if
282 * all the data structures are ready.
283 */
284moncontrol(mode)
285 int mode;
286{
287 if (mode) {
288 /* start */
289 profil(sbuf + sizeof(struct phdr), ssiz - sizeof(struct phdr),
290 s_lowpc, s_scale);
291 profiling = 0;
292 } else {
293 /* stop */
294 profil((char *)0, 0, 0, 0);
295 profiling = 3;
296 }
50084e08 297}