diff options
author | bde <bde@FreeBSD.org> | 1995-12-29 15:30:05 +0000 |
---|---|---|
committer | bde <bde@FreeBSD.org> | 1995-12-29 15:30:05 +0000 |
commit | 586cc683d875b37dce82c825feb9ccc7d884b35e (patch) | |
tree | 9ce1e55534d3d930aead3ff55aeb7fcedbc086a4 /usr.sbin/kgmon | |
parent | ff6f507f6bbb3fda77fb14c7201db37bafea7a3f (diff) | |
download | FreeBSD-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.8 | 11 | ||||
-rw-r--r-- | usr.sbin/kgmon/kgmon.c | 37 |
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); /* |