* Copyright (c) 1983, 1992, 1993
* The Regents of the University of California. All rights reserved.
* %sccs.include.redist.c%
#if !defined(lint) && defined(LIBC_SCCS)
static char sccsid
[] = "@(#)gmon.c 8.1 (Berkeley) %G%";
extern char *minbrk
asm ("minbrk");
struct gmonparam _gmonparam
= { GMON_PROF_OFF
};
/* see profil(2) where this is describe (incorrectly) */
#define SCALE_1_TO_1 0x10000L
#define ERR(s) write(2, s, sizeof(s))
void moncontrol
__P((int));
static int hertz
__P((void));
monstartup(lowpc
, highpc
)
struct gmonparam
*p
= &_gmonparam
;
* round lowpc and highpc to multiples of the density we're using
* so the rest of the scaling (here and in gprof) stays in ints.
p
->lowpc
= ROUNDDOWN(lowpc
, HISTFRACTION
* sizeof(HISTCOUNTER
));
p
->highpc
= ROUNDUP(highpc
, HISTFRACTION
* sizeof(HISTCOUNTER
));
p
->textsize
= p
->highpc
- p
->lowpc
;
p
->kcountsize
= p
->textsize
/ HISTFRACTION
;
p
->hashfraction
= HASHFRACTION
;
p
->fromssize
= p
->textsize
/ HASHFRACTION
;
p
->tolimit
= p
->textsize
* ARCDENSITY
/ 100;
if (p
->tolimit
< MINARCS
)
else if (p
->tolimit
> MAXARCS
)
p
->tossize
= p
->tolimit
* sizeof(struct tostruct
);
cp
= sbrk(p
->kcountsize
+ p
->fromssize
+ p
->tossize
);
ERR("monstartup: out of memory\n");
bzero(cp
, p
->kcountsize
+ p
->fromssize
+ p
->tossize
);
p
->tos
= (struct tostruct
*)cp
;
p
->kcount
= (u_short
*)cp
;
p
->froms
= (u_short
*)cp
;
o
= p
->highpc
- p
->lowpc
;
s_scale
= ((float)p
->kcountsize
/ o
) * SCALE_1_TO_1
;
#else /* avoid floating point */
int quot
= o
/ p
->kcountsize
;
s_scale
= 0x10000 / quot
;
s_scale
= 0x1000000 / (o
/ (p
->kcountsize
>> 8));
s_scale
= 0x1000000 / ((o
<< 8) / p
->kcountsize
);
struct gmonparam
*p
= &_gmonparam
;
struct gmonhdr gmonhdr
, *hdr
;
struct clockinfo clockinfo
;
if (p
->state
== GMON_PROF_ERROR
)
ERR("_mcleanup: tos overflow\n");
size
= sizeof(clockinfo
);
if (sysctl(mib
, 2, &clockinfo
, &size
, NULL
, 0) < 0) {
clockinfo
.profhz
= hertz();
} else if (clockinfo
.profhz
== 0) {
clockinfo
.profhz
= clockinfo
.hz
;
clockinfo
.profhz
= hertz();
fd
= open("gmon.out", O_CREAT
|O_TRUNC
|O_WRONLY
, 0666);
perror("mcount: gmon.out");
log
= open("gmon.log", O_CREAT
|O_TRUNC
|O_WRONLY
, 0664);
perror("mcount: gmon.log");
len
= sprintf(buf
, "[mcleanup1] kcount 0x%x ssiz %d\n",
p
->kcount
, p
->kcountsize
);
hdr
= (struct gmonhdr
*)&gmonhdr
;
hdr
->ncnt
= p
->kcountsize
+ sizeof(gmonhdr
);
hdr
->version
= GMONVERSION
;
hdr
->profrate
= clockinfo
.profhz
;
write(fd
, (char *)hdr
, sizeof *hdr
);
write(fd
, p
->kcount
, p
->kcountsize
);
endfrom
= p
->fromssize
/ sizeof(*p
->froms
);
for (fromindex
= 0; fromindex
< endfrom
; fromindex
++) {
if (p
->froms
[fromindex
] == 0)
frompc
+= fromindex
* p
->hashfraction
* sizeof(*p
->froms
);
for (toindex
= p
->froms
[fromindex
]; toindex
!= 0;
toindex
= p
->tos
[toindex
].link
) {
"[mcleanup2] frompc 0x%x selfpc 0x%x count %d\n" ,
frompc
, p
->tos
[toindex
].selfpc
,
rawarc
.raw_frompc
= frompc
;
rawarc
.raw_selfpc
= p
->tos
[toindex
].selfpc
;
rawarc
.raw_count
= p
->tos
[toindex
].count
;
write(fd
, &rawarc
, sizeof rawarc
);
* profiling is what mcount checks to see if
* all the data structures are ready.
struct gmonparam
*p
= &_gmonparam
;
profil((char *)p
->kcount
, p
->kcountsize
, (int)p
->lowpc
,
profil((char *)0, 0, 0, 0);
p
->state
= GMON_PROF_OFF
;
* discover the tick frequency of the machine
* if something goes wrong, we return 0, an impossible hertz.
tim
.it_interval
.tv_sec
= 0;
tim
.it_interval
.tv_usec
= 1;
tim
.it_value
.tv_usec
= 0;
setitimer(ITIMER_REAL
, &tim
, 0);
setitimer(ITIMER_REAL
, 0, &tim
);
if (tim
.it_interval
.tv_usec
< 2)
return (1000000 / tim
.it_interval
.tv_usec
);