2 * Copyright (c) 1983, 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #if !defined(lint) && defined(LIBC_SCCS)
35 static char sccsid
[] = "@(#)gmon.c 8.1 (Berkeley) 6/4/93";
38 #include <sys/param.h>
48 struct gmonparam _gmonparam
= { GMON_PROF_OFF
};
51 /* see profil(2) where this is describe (incorrectly) */
52 #define SCALE_1_TO_1 0x10000L
54 #define ERR(s) write(2, s, sizeof(s) - 1)
56 void moncontrol
__P((int));
57 static int hertz
__P((void));
60 monstartup(lowpc
, highpc
)
66 struct gmonparam
*p
= &_gmonparam
;
69 * round lowpc and highpc to multiples of the density we're using
70 * so the rest of the scaling (here and in gprof) stays in ints.
72 p
->lowpc
= ROUNDDOWN(lowpc
, HISTFRACTION
* sizeof(HISTCOUNTER
));
73 p
->highpc
= ROUNDUP(highpc
, HISTFRACTION
* sizeof(HISTCOUNTER
));
74 p
->textsize
= p
->highpc
- p
->lowpc
;
75 p
->kcountsize
= p
->textsize
/ HISTFRACTION
;
76 p
->hashfraction
= HASHFRACTION
;
77 p
->fromssize
= p
->textsize
/ HASHFRACTION
;
78 p
->tolimit
= p
->textsize
* ARCDENSITY
/ 100;
79 if (p
->tolimit
< MINARCS
)
81 else if (p
->tolimit
> MAXARCS
)
83 p
->tossize
= p
->tolimit
* sizeof(struct tostruct
);
85 cp
= malloc (p
->kcountsize
+ p
->fromssize
+ p
->tossize
);
87 ERR("monstartup: out of memory\n");
90 bzero(cp
, p
->kcountsize
+ p
->fromssize
+ p
->tossize
);
91 p
->tos
= (struct tostruct
*)cp
;
93 p
->kcount
= (u_short
*)cp
;
95 p
->froms
= (u_short
*)cp
;
99 o
= p
->highpc
- p
->lowpc
;
100 if (p
->kcountsize
< o
) {
102 s_scale
= ((float)p
->kcountsize
/ o
) * SCALE_1_TO_1
;
103 #else /* avoid floating point */
104 int quot
= o
/ p
->kcountsize
;
108 else if (quot
>= 0x100)
109 s_scale
= 0x10000 / quot
;
110 else if (o
>= 0x800000)
111 s_scale
= 0x1000000 / (o
/ (p
->kcountsize
>> 8));
113 s_scale
= 0x1000000 / ((o
<< 8) / p
->kcountsize
);
116 s_scale
= SCALE_1_TO_1
;
129 struct rawarc rawarc
;
130 struct gmonparam
*p
= &_gmonparam
;
131 struct gmonhdr gmonhdr
, *hdr
;
137 if (p
->state
== GMON_PROF_ERROR
)
138 ERR("_mcleanup: tos overflow\n");
141 fd
= open("gmon.out", O_CREAT
|O_TRUNC
|O_WRONLY
, 0666);
143 perror("mcount: gmon.out");
147 log
= open("gmon.log", O_CREAT
|O_TRUNC
|O_WRONLY
, 0664);
149 perror("mcount: gmon.log");
152 len
= sprintf(buf
, "[mcleanup1] kcount 0x%x ssiz %d\n",
153 p
->kcount
, p
->kcountsize
);
154 write(log
, buf
, len
);
156 hdr
= (struct gmonhdr
*)&gmonhdr
;
158 hdr
->hpc
= p
->highpc
;
159 hdr
->ncnt
= p
->kcountsize
+ sizeof(gmonhdr
);
160 hdr
->version
= GMONVERSION
;
161 hdr
->profrate
= hertz();
162 write(fd
, (char *)hdr
, sizeof *hdr
);
163 write(fd
, p
->kcount
, p
->kcountsize
);
164 endfrom
= p
->fromssize
/ sizeof(*p
->froms
);
165 for (fromindex
= 0; fromindex
< endfrom
; fromindex
++) {
166 if (p
->froms
[fromindex
] == 0)
170 frompc
+= fromindex
* p
->hashfraction
* sizeof(*p
->froms
);
171 for (toindex
= p
->froms
[fromindex
]; toindex
!= 0;
172 toindex
= p
->tos
[toindex
].link
) {
175 "[mcleanup2] frompc 0x%x selfpc 0x%x count %d\n" ,
176 frompc
, p
->tos
[toindex
].selfpc
,
177 p
->tos
[toindex
].count
);
178 write(log
, buf
, len
);
180 rawarc
.raw_frompc
= frompc
;
181 rawarc
.raw_selfpc
= p
->tos
[toindex
].selfpc
;
182 rawarc
.raw_count
= p
->tos
[toindex
].count
;
183 write(fd
, &rawarc
, sizeof rawarc
);
191 * profiling is what mcount checks to see if
192 * all the data structures are ready.
198 struct gmonparam
*p
= &_gmonparam
;
202 profil(p
->kcount
, p
->kcountsize
, (int)p
->lowpc
,
204 p
->state
= GMON_PROF_ON
;
208 p
->state
= GMON_PROF_OFF
;
213 * discover the tick frequency of the machine
214 * if something goes wrong, we return 0, an impossible hertz.
219 struct itimerval tim
;
221 tim
.it_interval
.tv_sec
= 0;
222 tim
.it_interval
.tv_usec
= 1;
223 tim
.it_value
.tv_sec
= 0;
224 tim
.it_value
.tv_usec
= 0;
225 setitimer(ITIMER_REAL
, &tim
, 0);
226 setitimer(ITIMER_REAL
, 0, &tim
);
227 if (tim
.it_interval
.tv_usec
< 2)
229 return (1000000 / tim
.it_interval
.tv_usec
);