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