tools: perf: metricgroup: add metricgroup for each PMU
If we want to add/print metricgroup, we need get pmu evets map via CPUID string, so it is important to get CPUID string. Now in metricgroup, it passes NULL to perf_pmu__find_map(), will never get the pmu events map on ARM64 platforms, due to get_cpuid_str() implement for ARM64 depending on the cpu info of PMU. The CPUID string will not be same on all CPUs on heterogeneous platforms, adding provision(using pmu->cpus) to find cpuid string from associated CPUs of PMU. The implement of get_cpuid_str() for ARM64 has taken heterogeneous platforms into consideration, but metricgroup has not. So it is necessory to add heterogeneous support for metricgroup. When we want to add/print metricgroup, need iterator each PMU then pass the perf_pmu struct to perf_pmu__find_map(). Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>5.4-rM2-2.2.x-imx-squashed
parent
37231434b2
commit
b8552bd2ea
|
@ -296,83 +296,89 @@ static void metricgroup__print_strlist(struct strlist *metrics, bool raw)
|
|||
void metricgroup__print(bool metrics, bool metricgroups, char *filter,
|
||||
bool raw, bool details)
|
||||
{
|
||||
struct pmu_events_map *map = perf_pmu__find_map(NULL);
|
||||
struct pmu_events_map *map;
|
||||
struct perf_pmu *pmu;
|
||||
struct pmu_event *pe;
|
||||
int i;
|
||||
struct rblist groups;
|
||||
struct rb_node *node, *next;
|
||||
struct strlist *metriclist = NULL;
|
||||
|
||||
if (!map)
|
||||
return;
|
||||
|
||||
if (!metricgroups) {
|
||||
metriclist = strlist__new(NULL, NULL);
|
||||
if (!metriclist)
|
||||
return;
|
||||
}
|
||||
|
||||
rblist__init(&groups);
|
||||
groups.node_new = mep_new;
|
||||
groups.node_cmp = mep_cmp;
|
||||
groups.node_delete = mep_delete;
|
||||
for (i = 0; ; i++) {
|
||||
const char *g;
|
||||
pe = &map->table[i];
|
||||
pmu = NULL;
|
||||
while ((pmu = perf_pmu__scan(pmu)) != NULL) {
|
||||
map = perf_pmu__find_map(pmu);
|
||||
|
||||
if (!pe->name && !pe->metric_group && !pe->metric_name)
|
||||
break;
|
||||
if (!pe->metric_expr)
|
||||
if (!map)
|
||||
continue;
|
||||
g = pe->metric_group;
|
||||
if (!g && pe->metric_name) {
|
||||
if (pe->name)
|
||||
|
||||
rblist__init(&groups);
|
||||
groups.node_new = mep_new;
|
||||
groups.node_cmp = mep_cmp;
|
||||
groups.node_delete = mep_delete;
|
||||
for (i = 0; ; i++) {
|
||||
const char *g;
|
||||
pe = &map->table[i];
|
||||
|
||||
if (!pe->name && !pe->metric_group && !pe->metric_name)
|
||||
break;
|
||||
if (!pe->metric_expr)
|
||||
continue;
|
||||
g = "No_group";
|
||||
}
|
||||
if (g) {
|
||||
char *omg;
|
||||
char *mg = strdup(g);
|
||||
|
||||
if (!mg)
|
||||
return;
|
||||
omg = mg;
|
||||
while ((g = strsep(&mg, ";")) != NULL) {
|
||||
struct mep *me;
|
||||
char *s;
|
||||
|
||||
g = skip_spaces(g);
|
||||
if (*g == 0)
|
||||
g = "No_group";
|
||||
if (filter && !strstr(g, filter))
|
||||
g = pe->metric_group;
|
||||
if (!g && pe->metric_name) {
|
||||
if (pe->name)
|
||||
continue;
|
||||
if (raw)
|
||||
s = (char *)pe->metric_name;
|
||||
else {
|
||||
if (asprintf(&s, "%s\n%*s%s]",
|
||||
pe->metric_name, 8, "[", pe->desc) < 0)
|
||||
return;
|
||||
g = "No_group";
|
||||
}
|
||||
if (g) {
|
||||
char *omg;
|
||||
char *mg = strdup(g);
|
||||
|
||||
if (details) {
|
||||
if (!mg)
|
||||
return;
|
||||
omg = mg;
|
||||
while ((g = strsep(&mg, ";")) != NULL) {
|
||||
struct mep *me;
|
||||
char *s;
|
||||
|
||||
g = skip_spaces(g);
|
||||
if (*g == 0)
|
||||
g = "No_group";
|
||||
if (filter && !strstr(g, filter))
|
||||
continue;
|
||||
if (raw)
|
||||
s = (char *)pe->metric_name;
|
||||
else {
|
||||
if (asprintf(&s, "%s\n%*s%s]",
|
||||
s, 8, "[", pe->metric_expr) < 0)
|
||||
pe->metric_name, 8, "[", pe->desc) < 0)
|
||||
return;
|
||||
|
||||
if (details) {
|
||||
if (asprintf(&s, "%s\n%*s%s]",
|
||||
s, 8, "[", pe->metric_expr) < 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!s)
|
||||
continue;
|
||||
|
||||
if (!metricgroups) {
|
||||
strlist__add(metriclist, s);
|
||||
} else {
|
||||
me = mep_lookup(&groups, g);
|
||||
if (!me)
|
||||
continue;
|
||||
strlist__add(me->metrics, s);
|
||||
}
|
||||
}
|
||||
|
||||
if (!s)
|
||||
continue;
|
||||
|
||||
if (!metricgroups) {
|
||||
strlist__add(metriclist, s);
|
||||
} else {
|
||||
me = mep_lookup(&groups, g);
|
||||
if (!me)
|
||||
continue;
|
||||
strlist__add(me->metrics, s);
|
||||
}
|
||||
free(omg);
|
||||
}
|
||||
free(omg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -397,16 +403,13 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter,
|
|||
}
|
||||
|
||||
static int metricgroup__add_metric(const char *metric, struct strbuf *events,
|
||||
struct pmu_events_map *map,
|
||||
struct list_head *group_list)
|
||||
{
|
||||
struct pmu_events_map *map = perf_pmu__find_map(NULL);
|
||||
struct pmu_event *pe;
|
||||
int ret = -EINVAL;
|
||||
int i, j;
|
||||
|
||||
if (!map)
|
||||
return 0;
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
pe = &map->table[i];
|
||||
|
||||
|
@ -468,6 +471,7 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events,
|
|||
}
|
||||
|
||||
static int metricgroup__add_metric_list(const char *list, struct strbuf *events,
|
||||
struct pmu_events_map *map,
|
||||
struct list_head *group_list)
|
||||
{
|
||||
char *llist, *nlist, *p;
|
||||
|
@ -482,7 +486,7 @@ static int metricgroup__add_metric_list(const char *list, struct strbuf *events,
|
|||
strbuf_addf(events, "%s", "");
|
||||
|
||||
while ((p = strsep(&llist, ",")) != NULL) {
|
||||
ret = metricgroup__add_metric(p, events, group_list);
|
||||
ret = metricgroup__add_metric(p, events, map, group_list);
|
||||
if (ret == -EINVAL) {
|
||||
fprintf(stderr, "Cannot find metric or group `%s'\n",
|
||||
p);
|
||||
|
@ -514,14 +518,25 @@ int metricgroup__parse_groups(const struct option *opt,
|
|||
struct parse_events_error parse_error;
|
||||
struct evlist *perf_evlist = *(struct evlist **)opt->value;
|
||||
struct strbuf extra_events;
|
||||
struct pmu_events_map *map;
|
||||
struct perf_pmu *pmu;
|
||||
LIST_HEAD(group_list);
|
||||
int ret;
|
||||
|
||||
if (metric_events->nr_entries == 0)
|
||||
metricgroup__rblist_init(metric_events);
|
||||
ret = metricgroup__add_metric_list(str, &extra_events, &group_list);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pmu = NULL;
|
||||
while ((pmu = perf_pmu__scan(pmu)) != NULL) {
|
||||
map = perf_pmu__find_map(pmu);
|
||||
if (!map)
|
||||
continue;
|
||||
|
||||
ret = metricgroup__add_metric_list(str, &extra_events, map, &group_list);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
pr_debug("adding %s\n", extra_events.buf);
|
||||
memset(&parse_error, 0, sizeof(struct parse_events_error));
|
||||
ret = parse_events(perf_evlist, extra_events.buf, &parse_error);
|
||||
|
@ -539,22 +554,28 @@ out:
|
|||
|
||||
bool metricgroup__has_metric(const char *metric)
|
||||
{
|
||||
struct pmu_events_map *map = perf_pmu__find_map(NULL);
|
||||
struct pmu_events_map *map;
|
||||
struct perf_pmu *pmu;
|
||||
struct pmu_event *pe;
|
||||
int i;
|
||||
|
||||
if (!map)
|
||||
return false;
|
||||
pmu = NULL;
|
||||
while ((pmu = perf_pmu__scan(pmu)) != NULL) {
|
||||
map = perf_pmu__find_map(pmu);
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
pe = &map->table[i];
|
||||
|
||||
if (!pe->name && !pe->metric_group && !pe->metric_name)
|
||||
break;
|
||||
if (!pe->metric_expr)
|
||||
if (!map)
|
||||
continue;
|
||||
if (match_metric(pe->metric_name, metric))
|
||||
return true;
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
pe = &map->table[i];
|
||||
|
||||
if (!pe->name && !pe->metric_group && !pe->metric_name)
|
||||
break;
|
||||
if (!pe->metric_expr)
|
||||
continue;
|
||||
if (match_metric(pe->metric_name, metric))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue