aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/pmcstat
diff options
context:
space:
mode:
authorSimon J. Gerraty <sjg@FreeBSD.org>2014-08-19 06:50:54 +0000
committerSimon J. Gerraty <sjg@FreeBSD.org>2014-08-19 06:50:54 +0000
commitee7b0571c2c18bdec848ed2044223cc88db29bd8 (patch)
treeb04f4bd7cd887f50e7d98af35f46b9834ff86c80 /usr.sbin/pmcstat
parentffda191e301f128a62c152fde92b692548367fca (diff)
parent15fc2873832ea5b9b639e701bbbf2e73af8b6a88 (diff)
downloadsrc-ee7b0571c2c18bdec848ed2044223cc88db29bd8.tar.gz
src-ee7b0571c2c18bdec848ed2044223cc88db29bd8.zip
Merge head from 7/28
Notes
Notes: svn path=/projects/bmake/; revision=270164
Diffstat (limited to 'usr.sbin/pmcstat')
-rw-r--r--usr.sbin/pmcstat/Makefile4
-rw-r--r--usr.sbin/pmcstat/Makefile.depend1
-rw-r--r--usr.sbin/pmcstat/pmcstat.812
-rw-r--r--usr.sbin/pmcstat/pmcstat.c44
-rw-r--r--usr.sbin/pmcstat/pmcstat.h4
-rw-r--r--usr.sbin/pmcstat/pmcstat_log.c6
6 files changed, 59 insertions, 12 deletions
diff --git a/usr.sbin/pmcstat/Makefile b/usr.sbin/pmcstat/Makefile
index b8c8081b6f61..78cde444948e 100644
--- a/usr.sbin/pmcstat/Makefile
+++ b/usr.sbin/pmcstat/Makefile
@@ -5,8 +5,8 @@
PROG= pmcstat
MAN= pmcstat.8
-DPADD= ${LIBELF} ${LIBKVM} ${LIBPMC} ${LIBM} ${LIBNCURSES}
-LDADD= -lelf -lkvm -lpmc -lm -lncurses
+DPADD= ${LIBELF} ${LIBKVM} ${LIBPMC} ${LIBM} ${LIBNCURSESW}
+LDADD= -lelf -lkvm -lpmc -lm -lncursesw
SRCS= pmcstat.c pmcstat.h pmcstat_log.c \
pmcpl_callgraph.c pmcpl_gprof.c pmcpl_annotate.c \
diff --git a/usr.sbin/pmcstat/Makefile.depend b/usr.sbin/pmcstat/Makefile.depend
index 063d52f4ddc5..f382224b173e 100644
--- a/usr.sbin/pmcstat/Makefile.depend
+++ b/usr.sbin/pmcstat/Makefile.depend
@@ -14,7 +14,6 @@ DIRDEPS = \
lib/libkvm \
lib/libpmc \
lib/msun \
- lib/ncurses/ncurses \
lib/ncurses/ncursesw \
diff --git a/usr.sbin/pmcstat/pmcstat.8 b/usr.sbin/pmcstat/pmcstat.8
index 97a2f626ca6d..6662d43c21d9 100644
--- a/usr.sbin/pmcstat/pmcstat.8
+++ b/usr.sbin/pmcstat/pmcstat.8
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 29, 2014
+.Dd May 16, 2014
.Dt PMCSTAT 8
.Os
.Sh NAME
@@ -52,6 +52,7 @@
.Op Fl f Ar pluginopt
.Op Fl g
.Op Fl k Ar kerneldir
+.Op Fl l Ar secs
.Op Fl m Ar pathname
.Op Fl n Ar rate
.Op Fl o Ar outputfile
@@ -274,6 +275,13 @@ This directory specifies where
should look for the kernel and its modules.
The default is
.Pa /boot/kernel .
+.It Fl l Ar secs
+Set system-wide performance measurement duration for
+.Ar secs
+seconds.
+The argument
+.Ar secs
+may be a fractional value.
.It Fl m Ar pathname
Print the sampled PCs with the name, the start and ending addresses
of the function within they live.
@@ -463,7 +471,7 @@ utility first appeared in
It is
.Ud
.Sh AUTHORS
-.An Joseph Koshy Aq jkoshy@FreeBSD.org
+.An Joseph Koshy Aq Mt jkoshy@FreeBSD.org
.Sh BUGS
The
.Nm
diff --git a/usr.sbin/pmcstat/pmcstat.c b/usr.sbin/pmcstat/pmcstat.c
index ae93b9387da2..a045706dda13 100644
--- a/usr.sbin/pmcstat/pmcstat.c
+++ b/usr.sbin/pmcstat/pmcstat.c
@@ -509,6 +509,7 @@ pmcstat_show_usage(void)
"\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"
+ "\t -l secs\t set duration time\n"
"\t -m file\t print sampled PCs to \"file\"\n"
"\t -n rate\t set sampling rate\n"
"\t -o file\t send print output to \"file\"\n"
@@ -551,6 +552,7 @@ main(int argc, char **argv)
{
cpuset_t cpumask;
double interval;
+ double duration;
int hcpu, option, npmc, ncpu;
int c, check_driver_stats, current_sampling_count;
int do_callchain, do_descendants, do_logproccsw, do_logprocexit;
@@ -600,6 +602,7 @@ main(int argc, char **argv)
args.pa_toptty = 0;
args.pa_topcolor = 0;
args.pa_mergepmc = 0;
+ args.pa_duration = 0.0;
STAILQ_INIT(&args.pa_events);
SLIST_INIT(&args.pa_targets);
bzero(&ds_start, sizeof(ds_start));
@@ -618,7 +621,7 @@ main(int argc, char **argv)
CPU_SET(hcpu, &cpumask);
while ((option = getopt(argc, argv,
- "CD:EF:G:M:NO:P:R:S:TWa:c:df:gk:m:n:o:p:qr:s:t:vw:z:")) != -1)
+ "CD:EF:G:M:NO:P:R:S:TWa:c:df:gk:l:m:n:o:p:qr:s:t:vw:z:")) != -1)
switch (option) {
case 'a': /* Annotate + callgraph */
args.pa_flags |= FLAG_DO_ANNOTATE;
@@ -692,6 +695,15 @@ main(int argc, char **argv)
args.pa_flags |= FLAG_HAS_KERNELPATH;
break;
+ case 'l': /* time duration in seconds */
+ duration = strtod(optarg, &end);
+ if (*end != '\0' || duration <= 0)
+ errx(EX_USAGE, "ERROR: Illegal duration time "
+ "value \"%s\".", optarg);
+ args.pa_flags |= FLAG_HAS_DURATION;
+ args.pa_duration = duration;
+ break;
+
case 'm':
args.pa_flags |= FLAG_DO_ANNOTATE;
args.pa_plugin = PMCSTAT_PL_ANNOTATE;
@@ -922,6 +934,12 @@ main(int argc, char **argv)
errx(EX_USAGE,
"ERROR: options -O and -R are mutually exclusive.");
+ /* disallow -T and -l together */
+ if ((args.pa_flags & FLAG_HAS_DURATION) &&
+ (args.pa_flags & FLAG_DO_TOP))
+ errx(EX_USAGE, "ERROR: options -T and -l are mutually "
+ "exclusive.");
+
/* -m option is allowed with -R only. */
if (args.pa_flags & FLAG_DO_ANNOTATE && args.pa_inputpath == NULL)
errx(EX_USAGE, "ERROR: option %s requires an input file",
@@ -1279,6 +1297,20 @@ main(int argc, char **argv)
"ERROR: Cannot register kevent for timer");
}
+ /*
+ * Setup a duration timer if we have sampling mode PMCs and
+ * a duration time is set
+ */
+ if ((args.pa_flags & FLAG_HAS_SAMPLING_PMCS) &&
+ (args.pa_flags & FLAG_HAS_DURATION)) {
+ EV_SET(&kev, 0, EVFILT_TIMER, EV_ADD, 0,
+ args.pa_duration * 1000, NULL);
+
+ if (kevent(pmcstat_kq, &kev, 1, NULL, 0, NULL) < 0)
+ err(EX_OSERR, "ERROR: Cannot register kevent for "
+ "time duration");
+ }
+
/* attach PMCs to the target process, starting it if specified */
if (args.pa_flags & FLAG_HAS_COMMANDLINE)
pmcstat_create_process();
@@ -1355,7 +1387,7 @@ main(int argc, char **argv)
/*
* loop till either the target process (if any) exits, or we
- * are killed by a SIGINT.
+ * are killed by a SIGINT or we reached the time duration.
*/
runstate = PMCSTAT_RUNNING;
do_print = do_read = 0;
@@ -1422,7 +1454,13 @@ main(int argc, char **argv)
break;
- case EVFILT_TIMER: /* print out counting PMCs */
+ case EVFILT_TIMER:
+ /* time duration reached, exit */
+ if (args.pa_flags & FLAG_HAS_DURATION) {
+ runstate = PMCSTAT_FINISHED;
+ break;
+ }
+ /* print out counting PMCs */
if ((args.pa_flags & FLAG_DO_TOP) &&
pmc_flush_logfile() == 0)
do_read = 1;
diff --git a/usr.sbin/pmcstat/pmcstat.h b/usr.sbin/pmcstat/pmcstat.h
index c8ec14de19c9..29dfeb790fa2 100644
--- a/usr.sbin/pmcstat/pmcstat.h
+++ b/usr.sbin/pmcstat/pmcstat.h
@@ -54,13 +54,14 @@
#define FLAG_DO_TOP 0x00010000 /* -T */
#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 DEFAULT_SAMPLE_COUNT 65536
#define DEFAULT_WAIT_INTERVAL 5.0
#define DEFAULT_DISPLAY_HEIGHT 256 /* file virtual height */
#define DEFAULT_DISPLAY_WIDTH 1024 /* file virtual width */
#define DEFAULT_BUFFER_SIZE 4096
-#define DEFAULT_CALLGRAPH_DEPTH 4
+#define DEFAULT_CALLGRAPH_DEPTH 16
#define PRINT_HEADER_PREFIX "# "
#define READPIPEFD 0
@@ -149,6 +150,7 @@ struct pmcstat_args {
int pa_toptty; /* output to tty or file */
int pa_topcolor; /* terminal support color */
int pa_mergepmc; /* merge PMC with same name */
+ double pa_duration; /* time duration */
int pa_argc;
char **pa_argv;
STAILQ_HEAD(, pmcstat_ev) pa_events;
diff --git a/usr.sbin/pmcstat/pmcstat_log.c b/usr.sbin/pmcstat/pmcstat_log.c
index f0e493959acb..40de320f17a1 100644
--- a/usr.sbin/pmcstat/pmcstat_log.c
+++ b/usr.sbin/pmcstat/pmcstat_log.c
@@ -307,10 +307,10 @@ pmcstat_stats_reset(int reset_global)
static int
pmcstat_string_compute_hash(const char *s)
{
- int hash;
+ unsigned hash;
- for (hash = 0; *s; s++)
- hash ^= *s;
+ for (hash = 2166136261; *s; s++)
+ hash = (hash ^ *s) * 16777619;
return (hash & PMCSTAT_HASH_MASK);
}