perf util: Add evsel__taskstate() to parse the task state info instead
authorZe Gao <zegao2021@gmail.com>
Mon, 22 Jan 2024 07:08:58 +0000 (02:08 -0500)
committerNamhyung Kim <namhyung@kernel.org>
Tue, 23 Jan 2024 07:02:37 +0000 (23:02 -0800)
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 <zegao@tencent.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: https://lore.kernel.org/r/20240122070859.1394479-5-zegao@tencent.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
tools/perf/util/evsel.c
tools/perf/util/evsel.h

index e08294c51cd437fc8518fef9bcb8e74f8f6da28c..4d14f14f2506c8ddff1fe18c6ae4fd0c990f93c2 100644 (file)
@@ -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,
index efbb6e848287f3f6b4f9f0aca779b2a6590ec42f..517cff431de2002eee9cc4f279a9f3f0578cf7da 100644 (file)
@@ -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)
 {