Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F149239124
D4151.id10163.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D4151.id10163.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D4151: Support a wider history counter in pmcstat gmon output
Attached
Detach File
Event Timeline
Log In to Comment