Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[firefly-linux-kernel-4.4.55.git] / tools / perf / builtin-report.c
index fc251005dd3d9ce954f4e382517f305b7dc3070d..96b5a7fee4bbe45a0f2558fb243e706ad65b8567 100644 (file)
@@ -8,6 +8,7 @@
 #include "builtin.h"
 
 #include "util/util.h"
+#include "util/cache.h"
 
 #include "util/annotate.h"
 #include "util/color.h"
@@ -54,6 +55,16 @@ struct perf_report {
        DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
 };
 
+static int perf_report_config(const char *var, const char *value, void *cb)
+{
+       if (!strcmp(var, "report.group")) {
+               symbol_conf.event_group = perf_config_bool(var, value);
+               return 0;
+       }
+
+       return perf_default_config(var, value, cb);
+}
+
 static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
                                        struct addr_location *al,
                                        struct perf_sample *sample,
@@ -299,6 +310,21 @@ static size_t hists__fprintf_nr_sample_events(struct hists *self,
        char unit;
        unsigned long nr_samples = self->stats.nr_events[PERF_RECORD_SAMPLE];
        u64 nr_events = self->stats.total_period;
+       struct perf_evsel *evsel = hists_to_evsel(self);
+       char buf[512];
+       size_t size = sizeof(buf);
+
+       if (symbol_conf.event_group && evsel->nr_members > 1) {
+               struct perf_evsel *pos;
+
+               perf_evsel__group_desc(evsel, buf, size);
+               evname = buf;
+
+               for_each_group_member(pos, evsel) {
+                       nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
+                       nr_events += pos->hists.stats.total_period;
+               }
+       }
 
        nr_samples = convert_unit(nr_samples, &unit);
        ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
@@ -319,6 +345,10 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
                struct hists *hists = &pos->hists;
                const char *evname = perf_evsel__name(pos);
 
+               if (symbol_conf.event_group &&
+                   !perf_evsel__is_group_leader(pos))
+                       continue;
+
                hists__fprintf_nr_sample_events(hists, evname, stdout);
                hists__fprintf(hists, true, 0, 0, stdout);
                fprintf(stdout, "\n\n");
@@ -372,7 +402,7 @@ static int __cmd_report(struct perf_report *rep)
        if (ret)
                goto out_delete;
 
-       kernel_map = session->host_machine.vmlinux_maps[MAP__FUNCTION];
+       kernel_map = session->machines.host.vmlinux_maps[MAP__FUNCTION];
        kernel_kmap = map__kmap(kernel_map);
        if (kernel_map == NULL ||
            (kernel_map->dso->hit &&
@@ -416,8 +446,16 @@ static int __cmd_report(struct perf_report *rep)
                        hists->symbol_filter_str = rep->symbol_filter_str;
 
                hists__collapse_resort(hists);
-               hists__output_resort(hists);
                nr_samples += hists->stats.nr_events[PERF_RECORD_SAMPLE];
+
+               /* Non-group events are considered as leader */
+               if (symbol_conf.event_group &&
+                   !perf_evsel__is_group_leader(pos)) {
+                       struct hists *leader_hists = &pos->leader->hists;
+
+                       hists__match(leader_hists, hists);
+                       hists__link(leader_hists, hists);
+               }
        }
 
        if (nr_samples == 0) {
@@ -425,11 +463,22 @@ static int __cmd_report(struct perf_report *rep)
                goto out_delete;
        }
 
+       list_for_each_entry(pos, &session->evlist->entries, node)
+               hists__output_resort(&pos->hists);
+
        if (use_browser > 0) {
                if (use_browser == 1) {
-                       perf_evlist__tui_browse_hists(session->evlist, help,
-                                                     NULL,
-                                                     &session->header.env);
+                       ret = perf_evlist__tui_browse_hists(session->evlist,
+                                                       help,
+                                                       NULL,
+                                                       &session->header.env);
+                       /*
+                        * Usually "ret" is the last pressed key, and we only
+                        * care if the key notifies us to switch data file.
+                        */
+                       if (ret != K_SWITCH_INPUT_DATA)
+                               ret = 0;
+
                } else if (use_browser == 2) {
                        perf_evlist__gtk_browse_hists(session->evlist, help,
                                                      NULL);
@@ -595,8 +644,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
        OPT_BOOLEAN(0, "stdio", &report.use_stdio,
                    "Use the stdio interface"),
        OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
-                  "sort by key(s): pid, comm, dso, symbol, parent, dso_to,"
-                  " dso_from, symbol_to, symbol_from, mispredict"),
+                  "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline,"
+                  " dso_to, dso_from, symbol_to, symbol_from, mispredict"),
        OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
                    "Show sample percentage for different cpu modes"),
        OPT_STRING('p', "parent", &parent_pattern, "regex",
@@ -638,6 +687,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
                   "Specify disassembler style (e.g. -M intel for intel syntax)"),
        OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
                    "Show a column with the sum of periods"),
+       OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
+                   "Show event group information together"),
        OPT_CALLBACK_NOOPT('b', "branch-stack", &sort__branch_mode, "",
                    "use branch records for histogram filling", parse_branch_mode),
        OPT_STRING(0, "objdump", &objdump_path, "path",
@@ -645,6 +696,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
        OPT_END()
        };
 
+       perf_config(perf_report_config, NULL);
+
        argc = parse_options(argc, argv, options, report_usage, 0);
 
        if (report.use_stdio)
@@ -663,6 +716,16 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
                else
                        input_name = "perf.data";
        }
+
+       if (strcmp(input_name, "-") != 0)
+               setup_browser(true);
+       else {
+               use_browser = 0;
+               perf_hpp__column_enable(PERF_HPP__OVERHEAD);
+               perf_hpp__init();
+       }
+
+repeat:
        session = perf_session__new(input_name, O_RDONLY,
                                    report.force, false, &report.tool);
        if (session == NULL)
@@ -688,14 +751,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 
        }
 
-       if (strcmp(input_name, "-") != 0)
-               setup_browser(true);
-       else {
-               use_browser = 0;
-               perf_hpp__init();
-       }
-
-       setup_sorting(report_usage, options);
+       if (setup_sorting() < 0)
+               usage_with_options(report_usage, options);
 
        /*
         * Only in the newt browser we are doing integrated annotation,
@@ -763,6 +820,12 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
        }
 
        ret = __cmd_report(&report);
+       if (ret == K_SWITCH_INPUT_DATA) {
+               perf_session__delete(session);
+               goto repeat;
+       } else
+               ret = 0;
+
 error:
        perf_session__delete(session);
        return ret;