summaryrefslogtreecommitdiffstats
path: root/usr.sbin/kgmon
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>1995-12-29 15:30:05 +0000
committerbde <bde@FreeBSD.org>1995-12-29 15:30:05 +0000
commit586cc683d875b37dce82c825feb9ccc7d884b35e (patch)
tree9ce1e55534d3d930aead3ff55aeb7fcedbc086a4 /usr.sbin/kgmon
parentff6f507f6bbb3fda77fb14c7201db37bafea7a3f (diff)
downloadFreeBSD-src-586cc683d875b37dce82c825feb9ccc7d884b35e.zip
FreeBSD-src-586cc683d875b37dce82c825feb9ccc7d884b35e.tar.gz
Implemented non-statistical kernel profiling. This is based on
looking at a high resolution clock for each of the following events: function call, function return, interrupt entry, interrupt exit, and interesting branches. The differences between the times of these events are added at appropriate places in a ordinary histogram (as if very fast statistical profiling sampled the pc at those places) so that ordinary gprof can be used to analyze the times. gmon.h: Histogram counters need to be 4 bytes for microsecond resolutions. They will need to be larger for the 586 clock. The comments were vax-centric and wrong even on vaxes. Does anyone disagree? gprof4.c: The standard gprof should support counters of all integral sizes and the size of the counter should be in the gmon header. This hack will do until then. (Use gprof4 -u to examine the results of non-statistical profiling.) config/*: Non-statistical profiling is configured with `config -pp'. `config -p' still gives ordinary profiling. kgmon/*: Non-statistical profiling is enabled with `kgmon -B'. `kgmon -b' still enables ordinary profiling (and distables non-statistical profiling) if non-statistical profiling is configured.
Diffstat (limited to 'usr.sbin/kgmon')
-rw-r--r--usr.sbin/kgmon/kgmon.811
-rw-r--r--usr.sbin/kgmon/kgmon.c37
2 files changed, 36 insertions, 12 deletions
diff --git a/usr.sbin/kgmon/kgmon.8 b/usr.sbin/kgmon/kgmon.8
index 114fea8..4a91582 100644
--- a/usr.sbin/kgmon/kgmon.8
+++ b/usr.sbin/kgmon/kgmon.8
@@ -39,7 +39,7 @@
.Nd generate a dump of the operating system's profile buffers
.Sh SYNOPSIS
.Nm kgmon
-.Op Fl bhpr
+.Op Fl Bbhpr
.Op Fl M core
.Op Fl N system
.Sh DESCRIPTION
@@ -62,8 +62,10 @@ file suitable for later analysis by
.Pp
The options are as follows:
.Bl -tag -width Ds
+.It Fl B
+Resume the collection of high resolution profile data.
.It Fl b
-Resume the collection of profile data.
+Resume the collection of low resolution profile data.
.It Fl h
Stop the collection of profile data.
.It Fl p
@@ -86,6 +88,8 @@ default ``/kernel''.
.El
.Pp
If neither
+.Fl B
+nor
.Fl b
nor
.Fl h
@@ -96,6 +100,9 @@ flag is specified and profile data is being collected,
profiling will be momentarily suspended,
the operating system profile buffers will be dumped,
and profiling will be immediately resumed.
+.Pp
+The profile buffers should be reset when the resolution
+of the profile data is changed.
.Sh FILES
.Bl -tag -width /dev/kmemx -compact
.It Pa /kernel
diff --git a/usr.sbin/kgmon/kgmon.c b/usr.sbin/kgmon/kgmon.c
index 1a2923b..c283f16 100644
--- a/usr.sbin/kgmon/kgmon.c
+++ b/usr.sbin/kgmon/kgmon.c
@@ -69,7 +69,7 @@ struct kvmvars {
struct gmonparam gpm;
};
-int bflag, hflag, kflag, rflag, pflag;
+int Bflag, bflag, hflag, kflag, rflag, pflag;
int debug = 0;
void setprof __P((struct kvmvars *kvp, int state));
void dumpstate __P((struct kvmvars *kvp));
@@ -87,7 +87,7 @@ main(int argc, char **argv)
seteuid(getuid());
kmemf = NULL;
system = NULL;
- while ((ch = getopt(argc, argv, "M:N:bhpr")) != EOF) {
+ while ((ch = getopt(argc, argv, "M:N:Bbhpr")) != EOF) {
switch((char)ch) {
case 'M':
@@ -99,6 +99,10 @@ main(int argc, char **argv)
system = optarg;
break;
+ case 'B':
+ Bflag = 1;
+ break;
+
case 'b':
bflag = 1;
break;
@@ -117,7 +121,7 @@ main(int argc, char **argv)
default:
(void)fprintf(stderr,
- "usage: kgmon [-bhrp] [-M core] [-N system]\n");
+ "usage: kgmon [-Bbhrp] [-M core] [-N system]\n");
exit(1);
}
}
@@ -140,6 +144,8 @@ main(int argc, char **argv)
mode = getprof(&kvmvars);
if (hflag)
disp = GMON_PROF_OFF;
+ else if (Bflag)
+ disp = GMON_PROF_HIRES;
else if (bflag)
disp = GMON_PROF_ON;
else
@@ -151,7 +157,12 @@ main(int argc, char **argv)
if (accessmode == O_RDWR)
setprof(&kvmvars, disp);
(void)fprintf(stdout, "kgmon: kernel profiling is %s.\n",
- disp == GMON_PROF_OFF ? "off" : "running");
+ disp == GMON_PROF_OFF ? "off" :
+ disp == GMON_PROF_HIRES ? "running (high resolution)" :
+ disp == GMON_PROF_ON ? "running" :
+ disp == GMON_PROF_BUSY ? "busy" :
+ disp == GMON_PROF_ERROR ? "off (error)" :
+ "in an unknown state");
return (0);
}
@@ -176,8 +187,9 @@ openfiles(system, kmemf, kvp)
"kgmon: profiling not defined in kernel.\n");
exit(20);
}
- if (!(bflag || hflag || rflag ||
- (pflag && state == GMON_PROF_ON)))
+ if (!(Bflag || bflag || hflag || rflag ||
+ (pflag &&
+ (state == GMON_PROF_HIRES || state == GMON_PROF_ON))))
return (O_RDONLY);
(void)seteuid(0);
if (sysctl(mib, 3, NULL, NULL, &state, size) >= 0)
@@ -186,7 +198,8 @@ openfiles(system, kmemf, kvp)
kern_readonly(state);
return (O_RDONLY);
}
- openmode = (bflag || hflag || pflag || rflag) ? O_RDWR : O_RDONLY;
+ openmode = (Bflag || bflag || hflag || pflag || rflag)
+ ? O_RDWR : O_RDONLY;
kvp->kd = kvm_openfiles(system, kmemf, NULL, openmode, errbuf);
if (kvp->kd == NULL) {
if (openmode == O_RDWR) {
@@ -221,15 +234,17 @@ kern_readonly(mode)
{
(void)fprintf(stderr, "kgmon: kernel read-only: ");
- if (pflag && mode == GMON_PROF_ON)
+ if (pflag && (mode == GMON_PROF_HIRES || mode == GMON_PROF_ON))
(void)fprintf(stderr, "data may be inconsistent\n");
if (rflag)
(void)fprintf(stderr, "-r supressed\n");
+ if (Bflag)
+ (void)fprintf(stderr, "-B supressed\n");
if (bflag)
(void)fprintf(stderr, "-b supressed\n");
if (hflag)
(void)fprintf(stderr, "-h supressed\n");
- rflag = bflag = hflag = 0;
+ rflag = Bflag = bflag = hflag = 0;
}
/*
@@ -324,7 +339,9 @@ dumpstate(kvp)
h.hpc = kvp->gpm.highpc;
h.ncnt = kvp->gpm.kcountsize + sizeof(h);
h.version = GMONVERSION;
- h.profrate = getprofhz(kvp);
+ h.profrate = kvp->gpm.profrate;
+ if (h.profrate == 0)
+ h.profrate = getprofhz(kvp); /* ancient kernel */
fwrite((char *)&h, sizeof(h), 1, fp);
/*
OpenPOWER on IntegriCloud