Commit 3301b3fe authored by Ian Rogers's avatar Ian Rogers Committed by Arnaldo Carvalho de Melo
Browse files

perf list: Simplify cache event printing



The current code computes an array of cache names then sorts and prints
them. Use a strlist to create a list of names that is sorted. Keep the
hybrid names, it is unclear how to generalize it, but drop the
computation of evt_pmus that is never used.

Signed-off-by: default avatarIan Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Caleb Biggers <caleb.biggers@intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kajol Jain <kjain@linux.ibm.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Kang Minchul <tegongkang@gmail.com>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Perry Taylor <perry.taylor@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Sandipan Das <sandipan.das@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Weilin Wang <weilin.wang@intel.com>
Cc: Xin Gao <gaoxin@cdjrlc.com>
Cc: Xing Zhengjun <zhengjun.xing@linux.intel.com>
Link: http://lore.kernel.org/lkml/20221114210723.2749751-7-irogers@google.com


[ Fixed up clash with cf9f67b3 ("perf print-events: Remove redundant comparison with zero")]
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent ca0fe624
Loading
Loading
Loading
Loading
+27 −103
Original line number Diff line number Diff line
@@ -206,135 +206,59 @@ void print_sdt_events(const char *subsys_glob, const char *event_glob,

int print_hwcache_events(const char *event_glob, bool name_only)
{
	unsigned int type, op, i, evt_i = 0, evt_num = 0, npmus = 0;
	char name[64], new_name[128];
	char **evt_list = NULL, **evt_pmus = NULL;
	bool evt_num_known = false;
	struct perf_pmu *pmu = NULL;
	struct strlist *evt_name_list = strlist__new(NULL, NULL);
	struct str_node *nd;

	if (perf_pmu__has_hybrid()) {
		npmus = perf_pmu__hybrid_pmu_num();
		evt_pmus = zalloc(sizeof(char *) * npmus);
		if (!evt_pmus)
			goto out_enomem;
	if (!evt_name_list) {
		pr_debug("Failed to allocate new strlist for hwcache events\n");
		return -ENOMEM;
	}

restart:
	if (evt_num_known) {
		evt_list = zalloc(sizeof(char *) * evt_num);
		if (!evt_list)
			goto out_enomem;
	}

	for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
		for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
	for (int type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
		for (int op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
			/* skip invalid cache type */
			if (!evsel__is_cache_op_valid(type, op))
				continue;

			for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
				unsigned int hybrid_supported = 0, j;
				bool supported;
			for (int i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
				struct perf_pmu *pmu = NULL;
				char name[64];

				__evsel__hw_cache_type_op_res_name(type, op, i, name, sizeof(name));
				if (event_glob != NULL && !strglobmatch(name, event_glob))
					continue;

				if (!perf_pmu__has_hybrid()) {
					if (!is_event_supported(PERF_TYPE_HW_CACHE,
								type | (op << 8) | (i << 16))) {
					if (is_event_supported(PERF_TYPE_HW_CACHE,
							       type | (op << 8) | (i << 16)))
						strlist__add(evt_name_list, name);
					continue;
				}
				} else {
				perf_pmu__for_each_hybrid_pmu(pmu) {
						if (!evt_num_known) {
							evt_num++;
							continue;
						}

						supported = is_event_supported(
							PERF_TYPE_HW_CACHE,
					if (is_event_supported(PERF_TYPE_HW_CACHE,
					    type | (op << 8) | (i << 16) |
							((__u64)pmu->type << PERF_PMU_TYPE_SHIFT));
						if (supported) {
					    ((__u64)pmu->type << PERF_PMU_TYPE_SHIFT))) {
						char new_name[128];
							snprintf(new_name, sizeof(new_name),
								 "%s/%s/", pmu->name, name);
							evt_pmus[hybrid_supported] =
								strdup(new_name);
							hybrid_supported++;
						}
					}

					if (hybrid_supported == 0)
						continue;
				}

				if (!evt_num_known) {
					evt_num++;
					continue;
				}

				if ((hybrid_supported == 0) ||
				    (hybrid_supported == npmus)) {
					evt_list[evt_i] = strdup(name);
					for (j = 0; j < npmus; j++)
						zfree(&evt_pmus[j]);
				} else {
					for (j = 0; j < hybrid_supported; j++) {
						evt_list[evt_i++] = evt_pmus[j];
						evt_pmus[j] = NULL;
							strlist__add(evt_name_list, new_name);
					}
					continue;
				}

				if (evt_list[evt_i] == NULL)
					goto out_enomem;
				evt_i++;
			}
		}
	}

	if (!evt_num_known) {
		evt_num_known = true;
		goto restart;
	}

	for (evt_i = 0; evt_i < evt_num; evt_i++) {
		if (!evt_list[evt_i])
			break;
	}

	evt_num = evt_i;
	qsort(evt_list, evt_num, sizeof(char *), cmp_string);
	evt_i = 0;
	while (evt_i < evt_num) {
	strlist__for_each_entry(nd, evt_name_list) {
		if (name_only) {
			printf("%s ", evt_list[evt_i++]);
			printf("%s ", nd->s);
			continue;
		}
		printf("  %-50s [%s]\n", evt_list[evt_i++],
				event_type_descriptors[PERF_TYPE_HW_CACHE]);
		printf("  %-50s [%s]\n", nd->s, event_type_descriptors[PERF_TYPE_HW_CACHE]);
	}
	if (evt_num && pager_in_use())
	if (!strlist__empty(evt_name_list) && pager_in_use())
		printf("\n");

out_free:
	evt_num = evt_i;
	for (evt_i = 0; evt_i < evt_num; evt_i++)
		zfree(&evt_list[evt_i]);
	zfree(&evt_list);

	for (evt_i = 0; evt_i < npmus; evt_i++)
		zfree(&evt_pmus[evt_i]);
	zfree(&evt_pmus);
	return evt_num;

out_enomem:
	printf("FATAL: not enough memory to print %s\n",
		event_type_descriptors[PERF_TYPE_HW_CACHE]);
	if (evt_list)
		goto out_free;
	return evt_num;
	strlist__delete(evt_name_list);
	return 0;
}

static void print_tool_event(const struct event_symbol *syms, const char *event_glob,