perf script: Add period data column
[platform/kernel/linux-starfive.git] / tools / perf / builtin-script.c
index 37d2b60..0659dff 100644 (file)
@@ -44,6 +44,7 @@ enum perf_output_field {
        PERF_OUTPUT_ADDR            = 1U << 10,
        PERF_OUTPUT_SYMOFFSET       = 1U << 11,
        PERF_OUTPUT_SRCLINE         = 1U << 12,
+       PERF_OUTPUT_PERIOD          = 1U << 13,
 };
 
 struct output_option {
@@ -63,6 +64,7 @@ struct output_option {
        {.str = "addr",  .field = PERF_OUTPUT_ADDR},
        {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},
        {.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
+       {.str = "period", .field = PERF_OUTPUT_PERIOD},
 };
 
 /* default set to maintain compatibility with current format */
@@ -184,10 +186,6 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
                if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP",
                                            PERF_OUTPUT_IP))
                        return -EINVAL;
-
-               if (!no_callchain &&
-                   !(attr->sample_type & PERF_SAMPLE_CALLCHAIN))
-                       symbol_conf.use_callchain = false;
        }
 
        if (PRINT_FIELD(ADDR) &&
@@ -233,6 +231,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
                                        PERF_OUTPUT_CPU))
                return -EINVAL;
 
+       if (PRINT_FIELD(PERIOD) &&
+               perf_evsel__check_stype(evsel, PERF_SAMPLE_PERIOD, "PERIOD",
+                                       PERF_OUTPUT_PERIOD))
+               return -EINVAL;
+
        return 0;
 }
 
@@ -290,6 +293,19 @@ static int perf_session__check_output_opt(struct perf_session *session)
                set_print_ip_opts(&evsel->attr);
        }
 
+       if (!no_callchain) {
+               bool use_callchain = false;
+
+               evlist__for_each(session->evlist, evsel) {
+                       if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
+                               use_callchain = true;
+                               break;
+                       }
+               }
+               if (!use_callchain)
+                       symbol_conf.use_callchain = false;
+       }
+
        /*
         * set default for tracepoints to print symbols only
         * if callchains are present
@@ -439,6 +455,9 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
 
        print_sample_start(sample, thread, evsel);
 
+       if (PRINT_FIELD(PERIOD))
+               printf("%10" PRIu64 " ", sample->period);
+
        if (PRINT_FIELD(EVNAME)) {
                const char *evname = perf_evsel__name(evsel);
                printf("%s: ", evname ? evname : "[unknown]");
@@ -476,6 +495,11 @@ static int default_start_script(const char *script __maybe_unused,
        return 0;
 }
 
+static int default_flush_script(void)
+{
+       return 0;
+}
+
 static int default_stop_script(void)
 {
        return 0;
@@ -489,6 +513,7 @@ static int default_generate_script(struct pevent *pevent __maybe_unused,
 
 static struct scripting_ops default_scripting_ops = {
        .start_script           = default_start_script,
+       .flush_script           = default_flush_script,
        .stop_script            = default_stop_script,
        .process_event          = process_event,
        .generate_script        = default_generate_script,
@@ -504,6 +529,11 @@ static void setup_scripting(void)
        scripting_ops = &default_scripting_ops;
 }
 
+static int flush_scripting(void)
+{
+       return scripting_ops->flush_script();
+}
+
 static int cleanup_scripting(void)
 {
        pr_debug("\nperf script stopped\n");
@@ -552,7 +582,6 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 
        scripting_ops->process_event(event, sample, evsel, thread, &al);
 
-       evsel->hists.stats.total_period += sample->period;
        return 0;
 }
 
@@ -1524,7 +1553,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
                     "comma separated output fields prepend with 'type:'. "
                     "Valid types: hw,sw,trace,raw. "
                     "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
-                    "addr,symoff", parse_output_fields),
+                    "addr,symoff,period", parse_output_fields),
        OPT_BOOLEAN('a', "all-cpus", &system_wide,
                    "system-wide collection from all CPUs"),
        OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
@@ -1724,7 +1753,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 
        session = perf_session__new(&file, false, &script.tool);
        if (session == NULL)
-               return -ENOMEM;
+               return -1;
 
        if (header || header_only) {
                perf_session__fprintf_info(session, stdout, show_full_info);
@@ -1804,6 +1833,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 
        err = __cmd_script(&script);
 
+       flush_scripting();
+
 out_delete:
        perf_session__delete(session);