Commit 4d598188 authored by Leo Yan's avatar Leo Yan Committed by Namhyung Kim
Browse files

perf script: Refactor sample_flags_to_name() function



When generating a string for sample flags, the sample_flags_to_name()
function lacks the ability to parse the trace start bit or trace end bit.
Therefore, the function is invoked multiple times after clearing its
unsupported bits.

This commit improves the sample_flags_to_name() function to parse sample
flags in one go for three kinds of information:
- The prefix info for trace start, trace end, etc.
- Branch types.
- Extra info for transaction and interrupt related info.

As a result, the code is simplified to call the sample_flags_to_name()
only once.  No expectation for any changes in the perf script output.

Reviewed-by: default avatarIan Rogers <irogers@google.com>
Reviewed-by: default avatarJames Clark <james.clark@linaro.org>
Signed-off-by: default avatarLeo Yan <leo.yan@arm.com>
Link: https://lore.kernel.org/r/20250304111240.3378214-3-leo.yan@arm.com


Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
parent 2b747a86
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -71,6 +71,11 @@ enum {

#define PERF_IP_FLAG_CHARS "bcrosyiABExghDt"

#define PERF_ADDITIONAL_STATE_MASK	\
	(PERF_IP_FLAG_IN_TX |		\
	 PERF_IP_FLAG_INTR_DISABLE |	\
	 PERF_IP_FLAG_INTR_TOGGLE)

#define PERF_BRANCH_MASK		(\
	PERF_IP_FLAG_BRANCH		|\
	PERF_IP_FLAG_CALL		|\
+54 −31
Original line number Diff line number Diff line
@@ -313,49 +313,72 @@ static const struct {
	{0, NULL}
};

static const char *sample_flags_to_name(u32 flags)
static int sample_flags_to_name(u32 flags, char *str, size_t size)
{
	int i;
	const char *prefix;
	int pos = 0, ret;
	u32 xf = flags & PERF_ADDITIONAL_STATE_MASK;
	char xs[16] = { 0 };

	/* Clear additional state bits */
	flags &= ~PERF_ADDITIONAL_STATE_MASK;

	if (flags & PERF_IP_FLAG_TRACE_BEGIN)
		prefix = "tr strt ";
	else if (flags & PERF_IP_FLAG_TRACE_END)
		prefix = "tr end  ";
	else
		prefix = "";

	ret = snprintf(str + pos, size - pos, "%s", prefix);
	if (ret < 0)
		return ret;
	pos += ret;

	flags &= ~(PERF_IP_FLAG_TRACE_BEGIN | PERF_IP_FLAG_TRACE_END);

	for (i = 0; sample_flags[i].name; i++) {
		if (sample_flags[i].flags == flags)
			return sample_flags[i].name;
	}
		if (sample_flags[i].flags != flags)
			continue;

	return NULL;
		ret = snprintf(str + pos, size - pos, "%s", sample_flags[i].name);
		if (ret < 0)
			return ret;
		pos += ret;
		break;
	}

int perf_sample__sprintf_flags(u32 flags, char *str, size_t sz)
{
	u32 xf = PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_INTR_DISABLE |
		 PERF_IP_FLAG_INTR_TOGGLE;
	const char *chars = PERF_IP_FLAG_CHARS;
	const size_t n = strlen(PERF_IP_FLAG_CHARS);
	const char *name = NULL;
	size_t i, pos = 0;
	char xs[16] = {0};
	if (!xf)
		return pos;

	if (flags & xf)
	snprintf(xs, sizeof(xs), "(%s%s%s)",
		 flags & PERF_IP_FLAG_IN_TX ? "x" : "",
		 flags & PERF_IP_FLAG_INTR_DISABLE ? "D" : "",
		 flags & PERF_IP_FLAG_INTR_TOGGLE ? "t" : "");

	name = sample_flags_to_name(flags & ~xf);
	if (name)
		return snprintf(str, sz, "%-15s%6s", name, xs);
	/* Right align the string if its length is less than the limit */
	if ((pos + strlen(xs)) < SAMPLE_FLAGS_STR_ALIGNED_SIZE)
		ret = snprintf(str + pos, size - pos, "%*s",
			       (int)(SAMPLE_FLAGS_STR_ALIGNED_SIZE - ret), xs);
	else
		ret = snprintf(str + pos, size - pos, " %s", xs);
	if (ret < 0)
		return ret;

	if (flags & PERF_IP_FLAG_TRACE_BEGIN) {
		name = sample_flags_to_name(flags & ~(xf | PERF_IP_FLAG_TRACE_BEGIN));
		if (name)
			return snprintf(str, sz, "tr strt %-7s%6s", name, xs);
	return pos + ret;
}

	if (flags & PERF_IP_FLAG_TRACE_END) {
		name = sample_flags_to_name(flags & ~(xf | PERF_IP_FLAG_TRACE_END));
		if (name)
			return snprintf(str, sz, "tr end  %-7s%6s", name, xs);
	}
int perf_sample__sprintf_flags(u32 flags, char *str, size_t sz)
{
	const char *chars = PERF_IP_FLAG_CHARS;
	const size_t n = strlen(PERF_IP_FLAG_CHARS);
	size_t i, pos = 0;
	int ret;

	ret = sample_flags_to_name(flags, str, sz);
	if (ret > 0)
		return ret;

	for (i = 0; i < n; i++, flags >>= 1) {
		if ((flags & 1) && pos < sz)