Page MenuHomeFreeBSD

D4151.id10163.diff
No OneTemporary

D4151.id10163.diff

Index: usr.sbin/pmcstat/pmcpl_gprof.c
===================================================================
--- usr.sbin/pmcstat/pmcpl_gprof.c
+++ usr.sbin/pmcstat/pmcpl_gprof.c
@@ -74,6 +74,12 @@
#include "pmcpl_callgraph.h"
#include "pmcpl_gprof.h"
+typedef uint64_t WIDEHISTCOUNTER;
+
+static HISTCOUNTER hc_max;
+static WIDEHISTCOUNTER whc_max;
+static int hc_sz=0;
+
/*
* struct pmcstat_gmonfile tracks a given 'gmon.out' file. These
* files are mmap()'ed in as needed.
@@ -99,6 +105,7 @@
struct pmcstat_image *_image);
static pmcstat_interned_string pmcstat_gmon_create_name(const char *_sd,
struct pmcstat_image *_img, pmc_id_t _pmcid);
+static void pmcstat_gmon_histcounter_size(void);
static void pmcstat_gmon_map_file(struct pmcstat_gmonfile *_pgf);
static void pmcstat_gmon_unmap_file(struct pmcstat_gmonfile *_pgf);
@@ -106,6 +113,32 @@
pmcstat_image *_i, pmc_id_t _id);
/*
+ * Determine the correct histcounter size and the maximum, based on
+ * the flags the user passed.
+ */
+
+static void
+pmcstat_gmon_histcounter_size() {
+
+ /* Determine the correct histcounter size and maximum. */
+ if (args.pa_flags & FLAG_DO_WIDE_GPROF_HC) {
+ hc_sz = sizeof(WIDEHISTCOUNTER);
+ if ((WIDEHISTCOUNTER) 0 < (WIDEHISTCOUNTER) -1)
+ whc_max = (WIDEHISTCOUNTER) -1;
+ else
+ whc_max = (WIDEHISTCOUNTER) ~((WIDEHISTCOUNTER) 1 <<
+ ((sizeof(WIDEHISTCOUNTER) * CHAR_BIT) - 1));
+ } else {
+ hc_sz = sizeof(HISTCOUNTER);
+ if ((HISTCOUNTER) 0 < (HISTCOUNTER) -1)
+ hc_max = (HISTCOUNTER) -1;
+ else
+ hc_max = (HISTCOUNTER) ~((HISTCOUNTER) 1 <<
+ ((sizeof(HISTCOUNTER) * CHAR_BIT) - 1));
+ }
+}
+
+/*
* Create a gmon.out file and size it.
*/
@@ -126,11 +159,15 @@
gm.lpc = image->pi_start;
gm.hpc = image->pi_end;
- gm.ncnt = (pgf->pgf_nbuckets * sizeof(HISTCOUNTER)) +
- sizeof(struct gmonhdr);
+ gm.ncnt = (pgf->pgf_nbuckets * hc_sz) + sizeof(struct gmonhdr);
gm.version = GMONVERSION;
gm.profrate = 0; /* use ticks */
- gm.histcounter_type = 0; /* compatibility with moncontrol() */
+ if (args.pa_flags & FLAG_DO_WIDE_GPROF_HC) {
+ gm.histcounter_type = hc_sz * CHAR_BIT;
+ if (!((WIDEHISTCOUNTER) 0 < (WIDEHISTCOUNTER) -1))
+ gm.histcounter_type *= (-1);
+ } else
+ gm.histcounter_type = 0; /* compatibility with moncontrol() */
gm.spare[0] = gm.spare[1] = 0;
/* Write out the gmon header */
@@ -400,6 +437,7 @@
struct pmcstat_gmonfile *pgf;
uintfptr_t bucket;
HISTCOUNTER *hc;
+ WIDEHISTCOUNTER *whc;
pmc_id_t pmcid;
(void) nsamples; (void) usermode; (void) cpu;
@@ -437,6 +475,9 @@
*/
pgf = pmcstat_image_find_gmonfile(image, pmcid);
if (pgf == NULL) {
+ if (hc_sz == 0)
+ pmcstat_gmon_histcounter_size();
+
if ((pgf = calloc(1, sizeof(*pgf))) == NULL)
err(EX_OSERR, "ERROR:");
@@ -448,7 +489,7 @@
pgf->pgf_nbuckets = (image->pi_end - image->pi_start) /
FUNCTION_ALIGNMENT; /* see <machine/profile.h> */
pgf->pgf_ndatabytes = sizeof(struct gmonhdr) +
- pgf->pgf_nbuckets * sizeof(HISTCOUNTER);
+ pgf->pgf_nbuckets * hc_sz;
pgf->pgf_nsamples = 0;
pgf->pgf_file = NULL;
@@ -474,14 +515,25 @@
assert(bucket < pgf->pgf_nbuckets);
- hc = (HISTCOUNTER *) ((uintptr_t) pgf->pgf_gmondata +
- sizeof(struct gmonhdr));
-
- /* saturating add */
- if (hc[bucket] < 0xFFFFU) /* XXX tie this to sizeof(HISTCOUNTER) */
- hc[bucket]++;
- else /* mark that an overflow occurred */
- pgf->pgf_overflow = 1;
+ if (args.pa_flags & FLAG_DO_WIDE_GPROF_HC) {
+ whc = (WIDEHISTCOUNTER *) ((uintptr_t) pgf->pgf_gmondata +
+ sizeof(struct gmonhdr));
+
+ /* saturating add */
+ if (whc[bucket] < whc_max)
+ whc[bucket]++;
+ else /* mark that an overflow occurred */
+ pgf->pgf_overflow = 1;
+ } else {
+ hc = (HISTCOUNTER *) ((uintptr_t) pgf->pgf_gmondata +
+ sizeof(struct gmonhdr));
+
+ /* saturating add */
+ if (hc[bucket] < hc_max)
+ hc[bucket]++;
+ else /* mark that an overflow occurred */
+ pgf->pgf_overflow = 1;
+ }
pgf->pgf_nsamples++;
}
Index: usr.sbin/pmcstat/pmcstat.h
===================================================================
--- usr.sbin/pmcstat/pmcstat.h
+++ usr.sbin/pmcstat/pmcstat.h
@@ -55,6 +55,7 @@
#define FLAG_DO_ANALYSIS 0x00020000 /* -g or -G or -m or -T */
#define FLAGS_HAS_CPUMASK 0x00040000 /* -c */
#define FLAG_HAS_DURATION 0x00080000 /* -l secs */
+#define FLAG_DO_WIDE_GPROF_HC 0x00100000 /* -e */
#define DEFAULT_SAMPLE_COUNT 65536
#define DEFAULT_WAIT_INTERVAL 5.0
Index: usr.sbin/pmcstat/pmcstat.8
===================================================================
--- usr.sbin/pmcstat/pmcstat.8
+++ usr.sbin/pmcstat/pmcstat.8
@@ -49,6 +49,7 @@
.Op Fl a Ar pathname
.Op Fl c Ar cpu-spec
.Op Fl d
+.Op Fl e
.Op Fl f Ar pluginopt
.Op Fl g
.Op Fl k Ar kerneldir
@@ -260,6 +261,12 @@
.Fl P ,
or
.Fl S ) .
+.It Fl e
+Specify that gprof profile files will use a wide history counter.
+This will produce files in a format compatible with FreeBSD's
+.Xr gprof 1
+program; however, other tools that do not fully parse a BSD-style
+gprof header may have trouble parsing these files.
.It Fl f Ar pluginopt
Pass option string to the active plugin.
.br
Index: usr.sbin/pmcstat/pmcstat.c
===================================================================
--- usr.sbin/pmcstat/pmcstat.c
+++ usr.sbin/pmcstat/pmcstat.c
@@ -506,6 +506,7 @@
"\t -a file\t print sampled PCs and callgraph to \"file\"\n"
"\t -c cpu-list\t set cpus for subsequent system-wide PMCs\n"
"\t -d\t\t (toggle) track descendants\n"
+ "\t -e\t\t use wide history counter for gprof(1) output\n"
"\t -f spec\t pass \"spec\" to as plugin option\n"
"\t -g\t\t produce gprof(1) compatible profiles\n"
"\t -k dir\t\t set the path to the kernel\n"
@@ -627,7 +628,7 @@
CPU_COPY(&rootmask, &cpumask);
while ((option = getopt(argc, argv,
- "CD:EF:G:M:NO:P:R:S:TWa:c:df:gk:l:m:n:o:p:qr:s:t:vw:z:")) != -1)
+ "CD:EF:G:M:NO:P:R:S:TWa:c:def:gk:l:m:n:o:p:qr:s:t:vw:z:")) != -1)
switch (option) {
case 'a': /* Annotate + callgraph */
args.pa_flags |= FLAG_DO_ANNOTATE;
@@ -668,6 +669,10 @@
args.pa_required |= FLAG_HAS_PROCESS_PMCS;
break;
+ case 'e': /* wide gprof metrics */
+ args.pa_flags |= FLAG_DO_WIDE_GPROF_HC;
+ break;
+
case 'F': /* produce a system-wide calltree */
args.pa_flags |= FLAG_DO_CALLGRAPHS;
args.pa_plugin = PMCSTAT_PL_CALLTREE;
@@ -1022,6 +1027,13 @@
"ERROR: options -g/-G/-m/-T require sampling PMCs or -R to be specified."
);
+ /* check if -e was specified without -g */
+ if ((args.pa_flags & FLAG_DO_WIDE_GPROF_HC) &&
+ !(args.pa_flags & FLAG_DO_GPROF))
+ errx(EX_USAGE,
+"ERROR: option -e requires gprof mode to be specified."
+ );
+
/* check if -O was spuriously specified */
if ((args.pa_flags & FLAG_HAS_OUTPUT_LOGFILE) &&
(args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) == 0)

File Metadata

Mime Type
text/plain
Expires
Tue, Mar 24, 5:48 AM (6 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30229627
Default Alt Text
D4151.id10163.diff (6 KB)

Event Timeline