[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1347263631-23175-4-git-send-email-zheng.z.yan@intel.com>
Date: Mon, 10 Sep 2012 15:53:51 +0800
From: "Yan, Zheng" <zheng.z.yan@...el.com>
To: eranian@...gle.com, a.p.zijlstra@...llo.nl, mingo@...e.hu,
andi@...stfloor.org, jolsa@...hat.com, linux-kernel@...r.kernel.org
Cc: "Yan, Zheng" <zheng.z.yan@...el.com>
Subject: [RFC PATCH 3/3] perf tool: Allow wildcard in PMU name
From: "Yan, Zheng" <zheng.z.yan@...el.com>
Allow wildcard in PMU name, so we can measure events on all
uncore boxes of same type. For example:
Signed-off-by: Yan, Zheng <zheng.z.yan@...el.com>
---
tools/perf/builtin-stat.c | 8 ++-
tools/perf/util/evsel.c | 31 ++++++++--
tools/perf/util/evsel.h | 2 +
tools/perf/util/parse-events.c | 126 ++++++++++++++++++++++++++++++-----------
4 files changed, 128 insertions(+), 39 deletions(-)
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index acdfd24..bebfd8c 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -557,7 +557,8 @@ static int run_perf_stat(int argc __used, const char **argv)
}
} else {
list_for_each_entry(counter, &evsel_list->entries, node) {
- read_counter_aggr(counter);
+ if (!counter->aggr_slave)
+ read_counter_aggr(counter);
perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
evsel_list->threads->nr);
}
@@ -1023,8 +1024,11 @@ static void print_stat(int argc, const char **argv)
list_for_each_entry(counter, &evsel_list->entries, node)
print_counter(counter);
} else {
- list_for_each_entry(counter, &evsel_list->entries, node)
+ list_for_each_entry(counter, &evsel_list->entries, node) {
+ if (counter->aggr_slave)
+ continue;
print_counter_aggr(counter);
+ }
}
if (!csv_output) {
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 7ff3c8f..b99b892 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -54,6 +54,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
evsel->idx = idx;
evsel->attr = *attr;
INIT_LIST_HEAD(&evsel->node);
+ INIT_LIST_HEAD(&evsel->sibling);
hists__init(&evsel->hists);
evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
}
@@ -525,14 +526,13 @@ int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
return 0;
}
-int __perf_evsel__read(struct perf_evsel *evsel,
- int ncpus, int nthreads, bool scale)
+static int read_evsel(struct perf_counts_values *aggr,
+ struct perf_evsel *evsel,
+ int ncpus, int nthreads, bool scale)
{
+ struct perf_counts_values count;
size_t nv = scale ? 3 : 1;
int cpu, thread;
- struct perf_counts_values *aggr = &evsel->counts->aggr, count;
-
- aggr->val = aggr->ena = aggr->run = 0;
for (cpu = 0; cpu < ncpus; cpu++) {
for (thread = 0; thread < nthreads; thread++) {
@@ -550,6 +550,27 @@ int __perf_evsel__read(struct perf_evsel *evsel,
}
}
}
+ return 0;
+}
+
+int __perf_evsel__read(struct perf_evsel *evsel,
+ int ncpus, int nthreads, bool scale)
+{
+ int ret;
+ struct perf_counts_values *aggr = &evsel->counts->aggr;
+ struct perf_evsel *child;
+
+ aggr->val = aggr->ena = aggr->run = 0;
+
+ ret = read_evsel(aggr, evsel, ncpus, nthreads, scale);
+ if (ret)
+ return ret;
+
+ list_for_each_entry(child, &evsel->sibling, node) {
+ ret = read_evsel(aggr, evsel, ncpus, nthreads, scale);
+ if (ret)
+ return ret;
+ }
evsel->counts->scaled = 0;
if (scale) {
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 956c0a0..bcb5a8a 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -46,6 +46,7 @@ struct perf_sample_id {
*/
struct perf_evsel {
struct list_head node;
+ struct list_head sibling;
struct perf_event_attr attr;
char *filter;
struct xyarray *fd;
@@ -69,6 +70,7 @@ struct perf_evsel {
struct cpu_map *cpus;
unsigned int sample_size;
bool supported;
+ bool aggr_slave;
/* parse modifier helper */
int exclude_GH;
struct perf_evsel *leader;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 3aa9be4..32288f2 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -239,14 +239,40 @@ const char *event_type(int type)
return "unknown";
}
+static void free_event_list(struct list_head *list)
+{
+ struct perf_evsel *evsel;
+ while (!list_empty(list)) {
+ evsel = list_entry(list->next, struct perf_evsel, node);
+ list_del(&evsel->node);
+ perf_evsel__delete(evsel);
+ }
+ free(list);
+}
-static int __add_event(struct list_head **_list, int *idx,
- struct perf_event_attr *attr,
- char *name, struct cpu_map *cpus)
+static struct perf_evsel *__add_event(int *idx, struct perf_event_attr *attr,
+ char *name, struct cpu_map *cpus)
{
struct perf_evsel *evsel;
+
+ event_attr_init(attr);
+
+ evsel = perf_evsel__new(attr, (*idx)++);
+ if (!evsel)
+ return NULL;
+
+ evsel->cpus = cpus;
+ if (name)
+ evsel->name = strdup(name);
+ return evsel;
+}
+
+static int add_event(struct list_head **_list, int *idx,
+ struct perf_event_attr *attr, char *name)
+{
struct list_head *list = *_list;
+ struct perf_evsel *evsel;
if (!list) {
list = malloc(sizeof(*list));
@@ -255,28 +281,17 @@ static int __add_event(struct list_head **_list, int *idx,
INIT_LIST_HEAD(list);
}
- event_attr_init(attr);
-
- evsel = perf_evsel__new(attr, (*idx)++);
+ evsel = __add_event(idx, attr, name, NULL);
if (!evsel) {
free(list);
return -ENOMEM;
}
- evsel->cpus = cpus;
- if (name)
- evsel->name = strdup(name);
list_add_tail(&evsel->node, list);
*_list = list;
return 0;
}
-static int add_event(struct list_head **_list, int *idx,
- struct perf_event_attr *attr, char *name)
-{
- return __add_event(_list, idx, attr, name, NULL);
-}
-
static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
{
int i, j;
@@ -593,32 +608,79 @@ static char *pmu_event_name(struct list_head *head_terms)
return NULL;
}
-int parse_events_add_pmu(struct list_head **list, int *idx,
+static int pmu_name_match(char *name, char *pattern)
+{
+ int idx;
+ char *c;
+
+ if (!strcasecmp(name, pattern))
+ return 0;
+
+ c = strchr(pattern, '*');
+ if (!c || c[1] != '\0')
+ return 1;
+
+ idx = c - pattern;
+ if (strncasecmp(name, pattern, idx))
+ return 1;
+
+ for (; name[idx]; idx++) {
+ if (name[idx] < '0' || name[idx] > '9')
+ return 1;
+ }
+ return 0;
+}
+
+int parse_events_add_pmu(struct list_head **_list, int *idx,
char *name, struct list_head *head_config)
{
struct perf_event_attr attr;
- struct perf_pmu *pmu;
+ struct list_head *list;
+ struct perf_pmu *pmu = NULL;
+ struct perf_evsel *evsel, *first = NULL;
+ int orig_idx = *idx;
- pmu = perf_pmu__find(name);
- if (!pmu)
- return -EINVAL;
+ list = malloc(sizeof(*list));
+ if (!list)
+ return -ENOMEM;
+ INIT_LIST_HEAD(list);
- memset(&attr, 0, sizeof(attr));
+ while ((pmu = perf_pmu__scan(pmu))) {
+ if (pmu_name_match(pmu->name, name))
+ continue;
- if (perf_pmu__check_alias(pmu, head_config))
- return -EINVAL;
+ memset(&attr, 0, sizeof(attr));
- /*
- * Configure hardcoded terms first, no need to check
- * return value when called with fail == 0 ;)
- */
- config_attr(&attr, head_config, 0);
+ if (perf_pmu__check_alias(pmu, head_config))
+ return -EINVAL;
- if (perf_pmu__config(pmu, &attr, head_config))
- return -EINVAL;
+ /*
+ * Configure hardcoded terms first, no need to check
+ * return value when called with fail == 0 ;)
+ */
+ config_attr(&attr, head_config, 0);
+
+ if (perf_pmu__config(pmu, &attr, head_config))
+ return -EINVAL;
- return __add_event(list, idx, &attr, pmu_event_name(head_config),
- pmu->cpus);
+ evsel = __add_event(idx, &attr, pmu_event_name(head_config),
+ pmu->cpus);
+ if (!evsel) {
+ *idx = orig_idx;
+ free_event_list(list);
+ return -ENOMEM;
+ }
+ list_add_tail(&evsel->node, list);
+ if (first) {
+ list_add_tail(&evsel->sibling, &first->sibling);
+ evsel->aggr_slave = true;
+ } else {
+ first = evsel;
+ }
+ }
+
+ *_list = list;
+ return 0;
}
int parse_events__modifier_group(struct list_head *list,
--
1.7.11.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists