Skip to content

Commit

Permalink
perf script: Refactor sample_flags_to_name() function
Browse files Browse the repository at this point in the history
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: Ian Rogers <irogers@google.com>
Reviewed-by: James Clark <james.clark@linaro.org>
Signed-off-by: Leo Yan <leo.yan@arm.com>
Link: https://lore.kernel.org/r/20250304111240.3378214-3-leo.yan@arm.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
  • Loading branch information
Leo Yan authored and Namhyung Kim committed Mar 5, 2025
1 parent 2b747a8 commit 4d59818
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 31 deletions.
5 changes: 5 additions & 0 deletions tools/perf/util/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 |\
Expand Down
85 changes: 54 additions & 31 deletions tools/perf/util/trace-event-scripting.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

for (i = 0; sample_flags[i].name ; i++) {
if (sample_flags[i].flags == flags)
return sample_flags[i].name;
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)
continue;

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

return NULL;
if (!xf)
return pos;

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" : "");

/* 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;

return pos + ret;
}

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 (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);

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);
}
int 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);
}
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)
Expand Down

0 comments on commit 4d59818

Please sign in to comment.