Re: [PATCH 1/2] perf, tools: Implement branch_type event parameter

2016-10-13 Thread Jiri Olsa
On Wed, Oct 12, 2016 at 02:02:06PM -0700, Andi Kleen wrote:
> From: Andi Kleen 
> 
> It can be useful to specify branch type state per event, for example
> if we want to collect both software trace points and last branch PMU
> events in a single collection. Currently this doesn't work because
> the software trace point errors out with -b.
> 
> There was already a branch-type parameter to configure branch sample
> types per event in the parser, but it was stubbed out. This patch
> implements the necessary plumbing to actually enable it.
> 
> Now
> 
> perf record -e sched:sched_switch,cpu/cpu-cycles,branch_type=any/ ...
> 
> works
> 
> Signed-off-by: Andi Kleen 

Acked-by: Jiri Olsa 

thanks,
jirka


[PATCH 1/2] perf, tools: Implement branch_type event parameter

2016-10-12 Thread Andi Kleen
From: Andi Kleen 

It can be useful to specify branch type state per event, for example
if we want to collect both software trace points and last branch PMU
events in a single collection. Currently this doesn't work because
the software trace point errors out with -b.

There was already a branch-type parameter to configure branch sample
types per event in the parser, but it was stubbed out. This patch
implements the necessary plumbing to actually enable it.

Now

perf record -e sched:sched_switch,cpu/cpu-cycles,branch_type=any/ ...

works

Signed-off-by: Andi Kleen 
---
 tools/perf/util/evsel.c|  9 
 tools/perf/util/evsel.h|  2 +
 tools/perf/util/parse-branch-options.c | 85 +++---
 tools/perf/util/parse-branch-options.h |  3 +-
 tools/perf/util/parse-events.c | 15 --
 5 files changed, 71 insertions(+), 43 deletions(-)

diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 8bc271141d9d..e58a2fbf3b16 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -28,6 +28,7 @@
 #include "debug.h"
 #include "trace-event.h"
 #include "stat.h"
+#include "util/parse-branch-options.h"
 
 static struct {
bool sample_id_all;
@@ -708,6 +709,14 @@ static void apply_config_terms(struct perf_evsel *evsel,
case PERF_EVSEL__CONFIG_TERM_CALLGRAPH:
callgraph_buf = term->val.callgraph;
break;
+   case PERF_EVSEL__CONFIG_TERM_BRANCH:
+   if (term->val.branch && strcmp(term->val.branch, "no")) 
{
+   perf_evsel__set_sample_bit(evsel, BRANCH_STACK);
+   parse_branch_str(term->val.branch,
+&attr->branch_sample_type);
+   } else
+   perf_evsel__reset_sample_bit(evsel, 
BRANCH_STACK);
+   break;
case PERF_EVSEL__CONFIG_TERM_STACK_USER:
dump_size = term->val.stack_user;
break;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index b1503b0ecdff..8cd7cd227483 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -47,6 +47,7 @@ enum {
PERF_EVSEL__CONFIG_TERM_MAX_STACK,
PERF_EVSEL__CONFIG_TERM_OVERWRITE,
PERF_EVSEL__CONFIG_TERM_DRV_CFG,
+   PERF_EVSEL__CONFIG_TERM_BRANCH,
PERF_EVSEL__CONFIG_TERM_MAX,
 };
 
@@ -63,6 +64,7 @@ struct perf_evsel_config_term {
int max_stack;
boolinherit;
booloverwrite;
+   char*branch;
} val;
 };
 
diff --git a/tools/perf/util/parse-branch-options.c 
b/tools/perf/util/parse-branch-options.c
index afc088dd7d20..3634d6974300 100644
--- a/tools/perf/util/parse-branch-options.c
+++ b/tools/perf/util/parse-branch-options.c
@@ -31,59 +31,51 @@ static const struct branch_mode branch_modes[] = {
BRANCH_END
 };
 
-int
-parse_branch_stack(const struct option *opt, const char *str, int unset)
+int parse_branch_str(const char *str, __u64 *mode)
 {
 #define ONLY_PLM \
(PERF_SAMPLE_BRANCH_USER|\
 PERF_SAMPLE_BRANCH_KERNEL  |\
 PERF_SAMPLE_BRANCH_HV)
 
-   uint64_t *mode = (uint64_t *)opt->value;
+   int ret = 0;
+   char *p, *s;
+   char *os = NULL;
const struct branch_mode *br;
-   char *s, *os = NULL, *p;
-   int ret = -1;
 
-   if (unset)
+   if (str == NULL) {
+   *mode = PERF_SAMPLE_BRANCH_ANY;
return 0;
+   }
 
-   /*
-* cannot set it twice, -b + --branch-filter for instance
-*/
-   if (*mode)
+   /* because str is read-only */
+   s = os = strdup(str);
+   if (!s)
return -1;
 
-   /* str may be NULL in case no arg is passed to -b */
-   if (str) {
-   /* because str is read-only */
-   s = os = strdup(str);
-   if (!s)
-   return -1;
-
-   for (;;) {
-   p = strchr(s, ',');
-   if (p)
-   *p = '\0';
-
-   for (br = branch_modes; br->name; br++) {
-   if (!strcasecmp(s, br->name))
-   break;
-   }
-   if (!br->name) {
-   ui__warning("unknown branch filter %s,"
-   " check man page\n", s);
-   goto error;
-   }
-
-   *mode |= br->mode;
-
-   if (!p)
-   break;
+   for (;;) {
+   p = strchr(s, ',');
+   if (p)
+   *p = '\0';
 
-   s = p + 1;
+   for (b