summaryrefslogtreecommitdiffstats
path: root/usr.sbin/pmcstat
diff options
context:
space:
mode:
authorgnn <gnn@FreeBSD.org>2014-05-16 03:18:09 +0000
committergnn <gnn@FreeBSD.org>2014-05-16 03:18:09 +0000
commitf767e17c966bc9dfe3cbd4a4c8f8468562f91420 (patch)
treeb2505759124495787be8d0ce5bff178281d2656f /usr.sbin/pmcstat
parent0e1c93d3c1a464c1bcbd9ba493241df58a7d10ad (diff)
downloadFreeBSD-src-f767e17c966bc9dfe3cbd4a4c8f8468562f91420.zip
FreeBSD-src-f767e17c966bc9dfe3cbd4a4c8f8468562f91420.tar.gz
Add a command line argument (-l) to end event collection after some
number of seconds. The number of seconds may be a fraction. Submitted by: Julien Charbon <jcharbon@versign.com> MFC after: 2 weeks Relnotes: yes
Diffstat (limited to 'usr.sbin/pmcstat')
-rw-r--r--usr.sbin/pmcstat/pmcstat.88
-rw-r--r--usr.sbin/pmcstat/pmcstat.c44
-rw-r--r--usr.sbin/pmcstat/pmcstat.h2
3 files changed, 51 insertions, 3 deletions
diff --git a/usr.sbin/pmcstat/pmcstat.8 b/usr.sbin/pmcstat/pmcstat.8
index 97a2f62..66d2960 100644
--- a/usr.sbin/pmcstat/pmcstat.8
+++ b/usr.sbin/pmcstat/pmcstat.8
@@ -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.
diff --git a/usr.sbin/pmcstat/pmcstat.c b/usr.sbin/pmcstat/pmcstat.c
index ae93b93..a045706 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 c8ec14d..a3738c1 100644
--- a/usr.sbin/pmcstat/pmcstat.h
+++ b/usr.sbin/pmcstat/pmcstat.h
@@ -54,6 +54,7 @@
#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
@@ -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;
OpenPOWER on IntegriCloud