Unverified Commit 49cb18ca authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!11276 [OLK-5.10]perf: Support event alias in form foo-bar-baz

Merge Pull Request from: @zwx1160575 
 
1、Event aliasing for events whose name in the form foo-bar-baz is not
supported, while foo-bar, foo_bar_baz, and other combinations are, i.e.
two hyphens are not supported.
2、Add a test for aliases with hyphens in the name to ensure that the
pmu-events tables are as expects. There should be no reason why these sort
of aliases would be treated differently, but no harm in checking.
3、Add a test which allows us to test parsing an event alias with hyphens.

Since these events typically do not exist on most host systems, add the
alias to the fake pmu.

Function perf_pmu__test_parse_init() has terms added to match known test
aliases.

https://gitee.com/openeuler/kernel/issues/IAMH2B

 
 
Link:https://gitee.com/openeuler/kernel/pulls/11276

 

Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
parents 89a32405 55fe9b1a
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -18,6 +18,22 @@
	    "Invert": "0",
	    "EdgeDetect": "0"
  },
  {
	    "Unit": "CBO",
	    "EventCode": "0xE0",
	    "UMask": "0x00",
	    "EventName": "event-hyphen",
	    "BriefDescription": "UNC_CBO_HYPHEN",
	    "PublicDescription": "UNC_CBO_HYPHEN"
  },
  {
	    "Unit": "CBO",
	    "EventCode": "0xC0",
	    "UMask": "0x00",
	    "EventName": "event-two-hyph",
	    "BriefDescription": "UNC_CBO_TWO_HYPH",
	    "PublicDescription": "UNC_CBO_TWO_HYPH"
  },
  {
	    "EventCode": "0x7",
	    "EventName": "uncore_hisi_l3c.rd_hit_cpipe",
+49 −0
Original line number Diff line number Diff line
@@ -1900,6 +1900,31 @@ static int test_event(struct evlist_test *e)
	return ret;
}

static int test_event_fake_pmu(const char *str)
{
	struct parse_events_error err;
	struct evlist *evlist;
	int ret;

	evlist = evlist__new();
	if (!evlist)
		return -ENOMEM;

	parse_events_error__init(&err);
	perf_pmu__test_parse_init();
	ret = __parse_events(evlist, str, &err, &perf_pmu__fake);
	if (ret) {
		pr_debug("failed to parse event '%s', err %d, str '%s'\n",
			 str, ret, err.str);
		parse_events_error__print(&err, str);
	}

	parse_events_error__exit(&err);
	evlist__delete(evlist);

	return ret;
}

static int test_events(struct evlist_test *events, unsigned cnt)
{
	int ret1, ret2 = 0;
@@ -2026,6 +2051,26 @@ static int test_pmu_events(void)
	return ret;
}

static int test_pmu_events_alias2(void)
{
	static const char events[][30] = {
			"event-hyphen",
			"event-two-hyph",
	};
	unsigned long i;
	int ret = 0;

	for (i = 0; i < ARRAY_SIZE(events); i++) {
		ret = test_event_fake_pmu(&events[i][0]);
		if (ret) {
			pr_err("check_parse_fake %s failed\n", &events[i][0]);
			break;
		}
	}

	return ret;
}

int test__parse_events(struct test *test __maybe_unused, int subtest __maybe_unused)
{
	int ret1, ret2 = 0;
@@ -2048,6 +2093,10 @@ do { \
			return ret;
	}

	ret1 = test_pmu_events_alias2();
	if (!ret2)
		ret2 = ret1;

	ret1 = test_terms(test__terms, ARRAY_SIZE(test__terms));
	if (!ret2)
		ret2 = ret1;
+32 −0
Original line number Diff line number Diff line
@@ -141,6 +141,34 @@ static const struct perf_pmu_test_event unc_cbo_xsnp_response_miss_eviction = {
	.matching_pmu = "uncore_cbox_0",
};

static const struct perf_pmu_test_event uncore_hyphen = {
	.event = {
		.name = "event-hyphen",
		.event = "umask=0x00,event=0xe0",
		.desc = "Unit: uncore_cbox UNC_CBO_HYPHEN",
		.topic = "uncore",
		.long_desc = "UNC_CBO_HYPHEN",
		.pmu = "uncore_cbox",
	},
	.alias_str = "umask=0,event=0xe0",
	.alias_long_desc = "UNC_CBO_HYPHEN",
	.matching_pmu = "uncore_cbox_0",
};

static const struct perf_pmu_test_event uncore_two_hyph = {
	.event = {
		.name = "event-two-hyph",
		.event = "umask=0x00,event=0xc0",
		.desc = "Unit: uncore_cbox UNC_CBO_TWO_HYPH",
		.topic = "uncore",
		.long_desc = "UNC_CBO_TWO_HYPH",
		.pmu = "uncore_cbox",
	},
	.alias_str = "umask=0,event=0xc0",
	.alias_long_desc = "UNC_CBO_TWO_HYPH",
	.matching_pmu = "uncore_cbox_0",
};

static const struct perf_pmu_test_event uncore_hisi_l3c_rd_hit_cpipe = {
	.event = {
		.name = "uncore_hisi_l3c.rd_hit_cpipe",
@@ -186,6 +214,8 @@ static const struct perf_pmu_test_event uncore_imc_cache_hits = {
static const struct perf_pmu_test_event *uncore_events[] = {
	&uncore_hisi_ddrc_flux_wcmd,
	&unc_cbo_xsnp_response_miss_eviction,
	&uncore_hyphen,
	&uncore_two_hyph,
	&uncore_hisi_l3c_rd_hit_cpipe,
	&uncore_imc_free_running_cache_miss,
	&uncore_imc_cache_hits,
@@ -652,6 +682,8 @@ static struct perf_pmu_test_pmu test_pmus[] = {
		},
		.aliases = {
			&unc_cbo_xsnp_response_miss_eviction,
			&uncore_hyphen,
			&uncore_two_hyph,
		},
	},
	{
+118 −41
Original line number Diff line number Diff line
@@ -1567,44 +1567,48 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
}

int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
			       char *str, struct list_head **listp)
			       char *str, struct list_head *head,
			       struct list_head **listp)
{
	struct parse_events_term *term;
	struct list_head *list;
	struct list_head *list = NULL;
	struct perf_pmu *pmu = NULL;
	int ok = 0;
	char *config;

	*listp = NULL;
	/* Add it for all PMUs that support the alias */
	list = malloc(sizeof(struct list_head));
	if (!list)
		return -1;
	INIT_LIST_HEAD(list);
	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
		struct perf_pmu_alias *alias;

		list_for_each_entry(alias, &pmu->aliases, list) {
			if (!strcasecmp(alias->name, str)) {
				struct list_head *head;
				char *config;

	if (!head) {
		head = malloc(sizeof(struct list_head));
		if (!head)
					return -1;
			goto out_err;

		INIT_LIST_HEAD(head);
	}
	config = strdup(str);
	if (!config)
					return -1;
		goto out_err;

	if (parse_events_term__num(&term,
				   PARSE_EVENTS__TERM_TYPE_USER,
				   config, 1, false, &config,
					NULL) < 0) {
					free(list);
		free(config);
					return -1;
		goto out_err;
	}
	list_add_tail(&term->list, head);

	/* Add it for all PMUs that support the alias */
	list = malloc(sizeof(struct list_head));
	if (!list)
		goto out_err;

	INIT_LIST_HEAD(list);
	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
		struct perf_pmu_alias *alias;

		list_for_each_entry(alias, &pmu->aliases, list) {
			if (!strcasecmp(alias->name, str)) {
				if (!parse_events_add_pmu(parse_state, list,
							  pmu->name, head,
							  true, true)) {
@@ -1612,17 +1616,26 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
						 pmu->name, alias->str);
					ok++;
				}

				parse_events_terms__delete(head);
			}
		}
	}
	if (!ok) {
		free(list);
		return -1;

	if (parse_state->fake_pmu) {
		if (!parse_events_add_pmu(parse_state, list, str, head,
					  true, true)) {
			pr_debug("%s -> %s/%s/\n", str, "fake_pmu", str);
			ok++;
		}
	}

out_err:
	if (ok)
		*listp = list;
	return 0;
	else
		free(list);

	parse_events_terms__delete(head);
	return ok ? 0 : -1;
}

int parse_events__modifier_group(struct list_head *list,
@@ -2004,8 +2017,17 @@ static void perf_pmu__parse_init(void)
	pmu = NULL;
	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
		list_for_each_entry(alias, &pmu->aliases, list) {
			if (strchr(alias->name, '-'))
			char *tmp = strchr(alias->name, '-');

			if (tmp) {
				char *tmp2 = NULL;

				tmp2 = strchr(tmp + 1, '-');
				len++;
				if (tmp2)
					len++;
			}

			len++;
		}
	}
@@ -2025,8 +2047,20 @@ static void perf_pmu__parse_init(void)
		list_for_each_entry(alias, &pmu->aliases, list) {
			struct perf_pmu_event_symbol *p = perf_pmu_events_list + len;
			char *tmp = strchr(alias->name, '-');
			char *tmp2 = NULL;

			if (tmp != NULL) {
			if (tmp)
				tmp2 = strchr(tmp + 1, '-');
			if (tmp2) {
				SET_SYMBOL(strndup(alias->name, tmp - alias->name),
						PMU_EVENT_SYMBOL_PREFIX);
				p++;
				tmp++;
				SET_SYMBOL(strndup(tmp, tmp2 - tmp), PMU_EVENT_SYMBOL_SUFFIX);
				p++;
				SET_SYMBOL(strdup(++tmp2), PMU_EVENT_SYMBOL_SUFFIX2);
				len += 3;
			} else if (tmp) {
				SET_SYMBOL(strndup(alias->name, tmp - alias->name),
						PMU_EVENT_SYMBOL_PREFIX);
				p++;
@@ -2053,23 +2087,38 @@ static void perf_pmu__parse_init(void)
 */
int perf_pmu__test_parse_init(void)
{
	struct perf_pmu_event_symbol *list;
	struct perf_pmu_event_symbol *list, *tmp, symbols[] = {
		{(char *)"read", PMU_EVENT_SYMBOL},
		{(char *)"event", PMU_EVENT_SYMBOL_PREFIX},
		{(char *)"two", PMU_EVENT_SYMBOL_SUFFIX},
		{(char *)"hyphen", PMU_EVENT_SYMBOL_SUFFIX},
		{(char *)"hyph", PMU_EVENT_SYMBOL_SUFFIX2},
	};
	unsigned long i, j;

	list = malloc(sizeof(*list) * 1);
	tmp = list = malloc(sizeof(*list) * ARRAY_SIZE(symbols));
	if (!list)
		return -ENOMEM;

	list->type   = PMU_EVENT_SYMBOL;
	list->symbol = strdup("read");

	if (!list->symbol) {
		free(list);
		return -ENOMEM;
	for (i = 0; i < ARRAY_SIZE(symbols); i++, tmp++) {
		tmp->type = symbols[i].type;
		tmp->symbol = strdup(symbols[i].symbol);
		if (!list->symbol)
			goto err_free;
	}

	perf_pmu_events_list = list;
	perf_pmu_events_list_num = 1;
	perf_pmu_events_list_num = ARRAY_SIZE(symbols);

	qsort(perf_pmu_events_list, ARRAY_SIZE(symbols),
	      sizeof(struct perf_pmu_event_symbol), comp_pmu);
	return 0;

err_free:
	for (j = 0, tmp = list; j < i; j++, tmp++)
		free(tmp->symbol);
	free(list);
	return -ENOMEM;
}

enum perf_pmu_event_symbol_type
@@ -2189,6 +2238,19 @@ int __parse_events(struct evlist *evlist, const char *str,
	return ret;
}

void parse_events_error__init(struct parse_events_error *err)
{
	bzero(err, sizeof(*err));
}

void parse_events_error__exit(struct parse_events_error *err)
{
	zfree(&err->str);
	zfree(&err->help);
	zfree(&err->first_str);
	zfree(&err->first_help);
}

#define MAX_WIDTH 1000
static int get_term_width(void)
{
@@ -2253,6 +2315,21 @@ static void __parse_events_print_error(int err_idx, const char *err_str,
	}
}

void parse_events_error__print(struct parse_events_error *err,
			       const char *event)
{
	if (!err->num_errors)
		return;

	__parse_events_print_error(err->idx, err->str, err->help, event);

	if (err->num_errors > 1) {
		fputs("\nInitial error:\n", stderr);
		__parse_events_print_error(err->first_idx, err->first_str,
					err->first_help, event);
	}
}

void parse_events_print_error(struct parse_events_error *err,
			      const char *event)
{
+6 −1
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ enum perf_pmu_event_symbol_type {
	PMU_EVENT_SYMBOL,		/* normal style PMU event */
	PMU_EVENT_SYMBOL_PREFIX,	/* prefix of pre-suf style event */
	PMU_EVENT_SYMBOL_SUFFIX,	/* suffix of pre-suf style event */
	PMU_EVENT_SYMBOL_SUFFIX2,	/* suffix of pre-suf2 style event */
};

struct perf_pmu_event_symbol {
@@ -201,7 +202,7 @@ struct evsel *parse_events__add_event(int idx, struct perf_event_attr *attr,
					char *name, struct perf_pmu *pmu);

int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
			       char *str,
			       char *str, struct list_head *head,
			       struct list_head **listp);

int parse_events_copy_term_list(struct list_head *old,
@@ -241,6 +242,10 @@ char *parse_events_formats_error_string(char *additional_terms);

void parse_events_print_error(struct parse_events_error *err,
			      const char *event);
void parse_events_error__init(struct parse_events_error *err);
void parse_events_error__exit(struct parse_events_error *err);
void parse_events_error__print(struct parse_events_error *err,
			       const char *event);

#ifdef HAVE_LIBELF_SUPPORT
/*
Loading