Skip to content

Commit c47a559

Browse files
Jin Yaoacmel
authored andcommitted
perf tools: Fix pattern matching for same substring in different PMU type
Some different PMU types may have the same substring. For example, on Icelake server we have PMU types "uncore_imc" and "uncore_imc_free_running". Both PMU types have the substring "uncore_imc". But the parser wrongly thinks they are the same PMU type. We enable an imc event, perf stat -e uncore_imc/event=0xe3/ -a -- sleep 1 Perf actually expands the event to: uncore_imc_0/event=0xe3/ uncore_imc_1/event=0xe3/ uncore_imc_2/event=0xe3/ uncore_imc_3/event=0xe3/ uncore_imc_4/event=0xe3/ uncore_imc_5/event=0xe3/ uncore_imc_6/event=0xe3/ uncore_imc_7/event=0xe3/ uncore_imc_free_running_0/event=0xe3/ uncore_imc_free_running_1/event=0xe3/ uncore_imc_free_running_3/event=0xe3/ uncore_imc_free_running_4/event=0xe3/ That's because the "uncore_imc_free_running" matches the pattern "uncore_imc*". Now we check that the last characters of PMU name is '_<digit>'. For example, for pattern "uncore_imc*", "uncore_imc_0" is parsed ok, but "uncore_imc_free_running_0" fails. Fixes: b2b9d3a ("perf pmu: Support wildcards on pmu name in dynamic pmu events") Signed-off-by: Jin Yao <[email protected]> Reviewed-by: Kan Liang <[email protected]> Acked-by: Jiri Olsa <[email protected]> Cc: Agustin Vega-Frias <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Peter Zijlstra <[email protected]> Link: http://lore.kernel.org/lkml/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent b91e549 commit c47a559

File tree

3 files changed

+37
-2
lines changed

3 files changed

+37
-2
lines changed

tools/perf/util/parse-events.y

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ event_pmu_name opt_pmu_config
316316
if (!strncmp(name, "uncore_", 7) &&
317317
strncmp($1, "uncore_", 7))
318318
name += 7;
319-
if (!fnmatch(pattern, name, 0)) {
319+
if (!perf_pmu__match(pattern, name, $1)) {
320320
if (parse_events_copy_term_list(orig_terms, &terms))
321321
CLEANUP_YYABORT;
322322
if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms, true, false))

tools/perf/util/pmu.c

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <linux/compiler.h>
44
#include <linux/string.h>
55
#include <linux/zalloc.h>
6+
#include <linux/ctype.h>
67
#include <subcmd/pager.h>
78
#include <sys/types.h>
89
#include <errno.h>
@@ -17,6 +18,7 @@
1718
#include <locale.h>
1819
#include <regex.h>
1920
#include <perf/cpumap.h>
21+
#include <fnmatch.h>
2022
#include "debug.h"
2123
#include "evsel.h"
2224
#include "pmu.h"
@@ -740,6 +742,27 @@ struct pmu_events_map *__weak pmu_events_map__find(void)
740742
return perf_pmu__find_map(NULL);
741743
}
742744

745+
static bool perf_pmu__valid_suffix(char *pmu_name, char *tok)
746+
{
747+
char *p;
748+
749+
if (strncmp(pmu_name, tok, strlen(tok)))
750+
return false;
751+
752+
p = pmu_name + strlen(tok);
753+
if (*p == 0)
754+
return true;
755+
756+
if (*p != '_')
757+
return false;
758+
759+
++p;
760+
if (*p == 0 || !isdigit(*p))
761+
return false;
762+
763+
return true;
764+
}
765+
743766
bool pmu_uncore_alias_match(const char *pmu_name, const char *name)
744767
{
745768
char *tmp = NULL, *tok, *str;
@@ -768,7 +791,7 @@ bool pmu_uncore_alias_match(const char *pmu_name, const char *name)
768791
*/
769792
for (; tok; name += strlen(tok), tok = strtok_r(NULL, ",", &tmp)) {
770793
name = strstr(name, tok);
771-
if (!name) {
794+
if (!name || !perf_pmu__valid_suffix((char *)name, tok)) {
772795
res = false;
773796
goto out;
774797
}
@@ -1872,3 +1895,14 @@ bool perf_pmu__has_hybrid(void)
18721895

18731896
return !list_empty(&perf_pmu__hybrid_pmus);
18741897
}
1898+
1899+
int perf_pmu__match(char *pattern, char *name, char *tok)
1900+
{
1901+
if (fnmatch(pattern, name, 0))
1902+
return -1;
1903+
1904+
if (tok && !perf_pmu__valid_suffix(name, tok))
1905+
return -1;
1906+
1907+
return 0;
1908+
}

tools/perf/util/pmu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,5 +133,6 @@ void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config,
133133
char *name);
134134

135135
bool perf_pmu__has_hybrid(void);
136+
int perf_pmu__match(char *pattern, char *name, char *tok);
136137

137138
#endif /* __PMU_H */

0 commit comments

Comments
 (0)