use ex scripts instead of /lib/cpp.
[unix-history] / usr / src / lib / libc / gmon / gmon.c
CommitLineData
e725d5e5 1static char *sccsid = "@(#)gmon.c 4.7 (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;
14static unsigned short tolimit = 0;
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
387d0540
PK
34 s_lowpc = lowpc;
35 s_highpc = highpc;
3a2b18f4 36 s_textsize = highpc - lowpc;
e725d5e5 37 monsize = (s_textsize + 1) / 2 + sizeof(struct phdr);
387d0540
PK
38 buffer = sbrk( monsize );
39 if ( buffer == (char *) -1 ) {
40 write( 2 , MSG , sizeof(MSG) );
41 return;
42 }
3a2b18f4 43 froms = (unsigned short *) sbrk( s_textsize );
387d0540
PK
44 if ( froms == (unsigned short *) -1 ) {
45 write( 2 , MSG , sizeof(MSG) );
46 froms = 0;
47 return;
48 }
4dff44be
KM
49 limit = s_textsize * DENSITY / 100;
50 if ( limit < MINCNT ) {
51 limit = MINCNT;
52 } else if ( limit > 65534 ) {
53 limit = 65534;
54 }
55 tos = (struct tostruct *) sbrk( limit * sizeof( struct tostruct ) );
387d0540
PK
56 if ( tos == (struct tostruct *) -1 ) {
57 write( 2 , MSG , sizeof(MSG) );
58 froms = 0;
59 tos = 0;
60 return;
61 }
387d0540 62 tos[0].link = 0;
3a2b18f4
PK
63 /*
64 * tolimit is what mcount checks to see if
65 * all the data structures are ready!!!
66 * make sure it won't overflow.
67 */
4dff44be 68 tolimit = limit;
ee56ba6f 69 monitor( lowpc , highpc , buffer , monsize , tolimit );
50084e08
PK
70}
71
72_mcleanup()
73{
bb9c5045
KM
74 int fd;
75 int fromindex;
76 char *frompc;
77 int toindex;
78 struct rawarc rawarc;
50084e08 79
bb9c5045
KM
80 fd = creat( "gmon.out" , 0666 );
81 if ( fd < 0 ) {
387d0540 82 perror( "mcount: gmon.out" );
50084e08
PK
83 return;
84 }
387d0540
PK
85# ifdef DEBUG
86 fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
87# endif DEBUG
bb9c5045 88 write( fd , sbuf , ssiz );
3a2b18f4 89 for ( fromindex = 0 ; fromindex < s_textsize>>1 ; fromindex++ ) {
50084e08
PK
90 if ( froms[fromindex] == 0 ) {
91 continue;
92 }
93 frompc = s_lowpc + (fromindex<<1);
94 for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {
95# ifdef DEBUG
22f3ec41
PK
96 fprintf( stderr ,
97 "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
50084e08
PK
98 frompc , tos[toindex].selfpc , tos[toindex].count );
99# endif DEBUG
bb9c5045
KM
100 rawarc.raw_frompc = (unsigned long) frompc;
101 rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
102 rawarc.raw_count = tos[toindex].count;
103 write( fd , &rawarc , sizeof rawarc );
50084e08
PK
104 }
105 }
bb9c5045 106 close( fd );
50084e08
PK
107}
108
387d0540
PK
109 /*
110 * This routine is massaged so that it may be jsb'ed to
111 */
50084e08
PK
112asm("#define _mcount mcount");
113mcount()
114{
115 register char *selfpc; /* r11 */
116 register unsigned short *frompcindex; /* r10 */
117 register struct tostruct *top; /* r9 */
785a53a1 118 static int profiling = 0;
50084e08 119
bb9c5045 120 asm( " forgot to run ex script on gcrt0.s" );
50084e08
PK
121 asm( "#define r11 r5" );
122 asm( "#define r10 r4" );
123 asm( "#define r9 r3" );
124#ifdef lint
125 selfpc = (char *) 0;
126 frompcindex = 0;
127#else not lint
128 /*
785a53a1
PK
129 * find the return address for mcount,
130 * and the return address for mcount's caller.
50084e08
PK
131 */
132 asm(" movl (sp), r11"); /* selfpc = ... (jsb frame) */
133 asm(" movl 16(fp), r10"); /* frompcindex = (calls frame) */
134#endif not lint
785a53a1
PK
135 /*
136 * check that we are profiling
387d0540 137 * and that we aren't recursively invoked.
785a53a1 138 */
3a2b18f4 139 if ( tolimit == 0 ) {
387d0540
PK
140 goto out;
141 }
142 if ( profiling ) {
50084e08
PK
143 goto out;
144 }
785a53a1
PK
145 profiling = 1;
146 /*
147 * check that frompcindex is a reasonable pc value.
148 * for example: signal catchers get called from the stack,
149 * not from text space. too bad.
150 */
3a2b18f4
PK
151 frompcindex = (unsigned short *) ( (long) frompcindex - (long) s_lowpc );
152 if ( (unsigned long) frompcindex > s_textsize ) {
785a53a1
PK
153 goto done;
154 }
3a2b18f4 155 frompcindex = &froms[ ( (long) frompcindex ) >> 1 ];
50084e08
PK
156 if ( *frompcindex == 0 ) {
157 *frompcindex = ++tos[0].link;
158 if ( *frompcindex >= tolimit ) {
159 goto overflow;
160 }
161 top = &tos[ *frompcindex ];
162 top->selfpc = selfpc;
163 top->count = 0;
164 top->link = 0;
165 } else {
166 top = &tos[ *frompcindex ];
167 }
785a53a1 168 for ( ; /* goto done */ ; top = &tos[ top -> link ] ) {
50084e08
PK
169 if ( top -> selfpc == selfpc ) {
170 top -> count++;
785a53a1 171 goto done;
50084e08
PK
172 }
173 if ( top -> link == 0 ) {
174 top -> link = ++tos[0].link;
175 if ( top -> link >= tolimit )
176 goto overflow;
177 top = &tos[ top -> link ];
178 top -> selfpc = selfpc;
179 top -> count = 1;
180 top -> link = 0;
785a53a1 181 goto done;
50084e08
PK
182 }
183 }
785a53a1
PK
184done:
185 profiling = 0;
186 /* and fall through */
50084e08
PK
187out:
188 asm( " rsb" );
189 asm( "#undef r11" );
190 asm( "#undef r10" );
191 asm( "#undef r9" );
192 asm( "#undef _mcount");
193
194overflow:
3a2b18f4 195 tolimit = 0;
50084e08
PK
196# define TOLIMIT "mcount: tos overflow\n"
197 write( 2 , TOLIMIT , sizeof( TOLIMIT ) );
50084e08
PK
198 goto out;
199}
200
ee56ba6f
KM
201/*VARARGS1*/
202monitor( lowpc , highpc , buf , bufsiz , nfunc )
387d0540 203 char *lowpc;
387d0540
PK
204 char *highpc;
205 int *buf, bufsiz;
ee56ba6f 206 int nfunc; /* not used, available for compatability only */
50084e08 207{
387d0540 208 register o;
50084e08 209
387d0540
PK
210 if ( lowpc == 0 ) {
211 profil( (char *) 0 , 0 , 0 , 0 );
ee56ba6f 212 _mcleanup();
387d0540
PK
213 return;
214 }
215 sbuf = buf;
216 ssiz = bufsiz;
217 ( (struct phdr *) buf ) -> lpc = lowpc;
218 ( (struct phdr *) buf ) -> hpc = highpc;
219 ( (struct phdr *) buf ) -> ncnt = ssiz;
220 o = sizeof(struct phdr);
221 buf = (int *) ( ( (int) buf ) + o );
222 bufsiz -= o;
223 if ( bufsiz <= 0 )
224 return;
ef7f2ecf 225 o = ( ( (char *) highpc - (char *) lowpc) );
387d0540 226 if( bufsiz < o )
ef7f2ecf 227 o = ( (float) bufsiz / o ) * 65536;
387d0540 228 else
ef7f2ecf 229 o = 65536;
387d0540 230 profil( buf , bufsiz , lowpc , o );
50084e08 231}
0bbf4774
KM
232
233/*
234 * This is a stub for the "brk" system call, which we want to
63238688
KM
235 * catch so that it will not deallocate our data space.
236 * (of which the program is not aware)
0bbf4774 237 */
63238688
KM
238asm("#define _curbrk curbrk");
239extern char *curbrk;
240
0bbf4774 241brk(addr)
63238688 242 char *addr;
0bbf4774 243{
63238688
KM
244
245 if (addr < minsbrk)
246 addr = minsbrk;
247 asm(" chmk $17");
ee56ba6f
KM
248 asm(" jcc 1f");
249 asm(" jmp cerror");
250asm("1:");
63238688
KM
251 curbrk = addr;
252 return (0);
0bbf4774 253}