From df8bc77e4a6b2d29bab0a092e1ed30fcabdea35e Mon Sep 17 00:00:00 2001 From: Ze Gao Date: Mon, 22 Jan 2024 02:08:58 -0500 Subject: perf util: Add evsel__taskstate() to parse the task state info instead Now that we have the __prinf_flags() parsing routines, we add a new helper evsel__taskstate() to extract the task state info from the recorded data. Signed-off-by: Ze Gao Cc: Steven Rostedt Link: https://lore.kernel.org/r/20240122070859.1394479-5-zegao@tencent.com Signed-off-by: Namhyung Kim --- tools/perf/util/evsel.c | 36 +++++++++++++++++++++++++++++++++++- tools/perf/util/evsel.h | 1 + 2 files changed, 36 insertions(+), 1 deletion(-) (limited to 'tools/perf/util') diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index e08294c51cd4..4d14f14f2506 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -2939,7 +2939,7 @@ search_op(struct tep_format_field *prev_state_field, struct tep_print_arg *arg) return sym; } -static __maybe_unused const char *get_states(struct tep_format_field *prev_state_field) +static const char *get_states(struct tep_format_field *prev_state_field) { struct tep_print_flag_sym *sym; struct tep_print_arg *arg; @@ -2963,6 +2963,40 @@ static __maybe_unused const char *get_states(struct tep_format_field *prev_state } return NULL; } + +char evsel__taskstate(struct evsel *evsel, struct perf_sample *sample, const char *name) +{ + static struct tep_format_field *prev_state_field; + static const char *states; + struct tep_format_field *field; + unsigned long long val; + unsigned int bit; + char state = '?'; /* '?' denotes unknown task state */ + + field = evsel__field(evsel, name); + + if (!field) + return state; + + if (!states || field != prev_state_field) { + states = get_states(field); + if (!states) + return state; + prev_state_field = field; + } + + /* + * Note since the kernel exposes TASK_REPORT_MAX to userspace + * to denote the 'preempted' state, we might as welll report + * 'R' for this case, which make senses to users as well. + * + * We can change this if we have a good reason in the future. + */ + val = evsel__intval(evsel, sample, name); + bit = val ? ffs(val) : 0; + state = (!bit || bit > strlen(states)) ? 'R' : states[bit-1]; + return state; +} #endif bool evsel__fallback(struct evsel *evsel, struct target *target, int err, diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index efbb6e848287..517cff431de2 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -339,6 +339,7 @@ struct perf_sample; void *evsel__rawptr(struct evsel *evsel, struct perf_sample *sample, const char *name); u64 evsel__intval(struct evsel *evsel, struct perf_sample *sample, const char *name); u64 evsel__intval_common(struct evsel *evsel, struct perf_sample *sample, const char *name); +char evsel__taskstate(struct evsel *evsel, struct perf_sample *sample, const char *name); static inline char *evsel__strval(struct evsel *evsel, struct perf_sample *sample, const char *name) { -- cgit