perf c2c report: Add sort_entry dimension support
authorJiri Olsa <jolsa@kernel.org>
Thu, 22 Sep 2016 15:36:42 +0000 (17:36 +0200)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 19 Oct 2016 16:18:31 +0000 (13:18 -0300)
Allow to reuse 'struct sort_entry' objects within c2c dimension support.

In case the 'struct sort_entry' object meets the need of c2c report we
will use it directly in following patches.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Joe Mario <jmario@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1474558645-19956-15-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-c2c.c

index 63c0e2d8d2d8a6838c7cade3c688696e3366847b..6b58b537bc9dd036e0516c5036d89bf47421b702 100644 (file)
@@ -9,6 +9,7 @@
 #include "hist.h"
 #include "tool.h"
 #include "data.h"
+#include "sort.h"
 
 struct c2c_hists {
        struct hists            hists;
@@ -47,6 +48,7 @@ struct c2c_dimension {
        struct c2c_header        header;
        const char              *name;
        int                      width;
+       struct sort_entry       *se;
 
        int64_t (*cmp)(struct perf_hpp_fmt *fmt,
                       struct hist_entry *, struct hist_entry *);
@@ -66,34 +68,47 @@ static int c2c_width(struct perf_hpp_fmt *fmt,
                     struct hists *hists __maybe_unused)
 {
        struct c2c_fmt *c2c_fmt;
+       struct c2c_dimension *dim;
 
        c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
-       return c2c_fmt->dim->width;
+       dim = c2c_fmt->dim;
+
+       return dim->se ? hists__col_len(hists, dim->se->se_width_idx) :
+                        c2c_fmt->dim->width;
 }
 
 static int c2c_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
-                     struct hists *hists __maybe_unused, int line, int *span)
+                     struct hists *hists, int line, int *span)
 {
+       struct perf_hpp_list *hpp_list = hists->hpp_list;
        struct c2c_fmt *c2c_fmt;
        struct c2c_dimension *dim;
-       int len = c2c_width(fmt, hpp, hists);
-       const char *text;
+       const char *text = NULL;
+       int width = c2c_width(fmt, hpp, hists);
 
        c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
        dim = c2c_fmt->dim;
 
-       text = dim->header.line[line].text;
-       if (text == NULL)
-               text = "";
-
-       if (*span) {
-               (*span)--;
-               return 0;
+       if (dim->se) {
+               text = dim->header.line[line].text;
+               /* Use the last line from sort_entry if not defined. */
+               if (!text && (line == hpp_list->nr_header_lines - 1))
+                       text = dim->se->se_header;
        } else {
-               *span = dim->header.line[line].span;
+               text = dim->header.line[line].text;
+
+               if (*span) {
+                       (*span)--;
+                       return 0;
+               } else {
+                       *span = dim->header.line[line].span;
+               }
        }
 
-       return scnprintf(hpp->buf, hpp->size, "%*s", len, text);
+       if (text == NULL)
+               text = "";
+
+       return scnprintf(hpp->buf, hpp->size, "%*s", width, text);
 }
 
 static struct c2c_dimension *dimensions[] = {
@@ -130,6 +145,39 @@ static struct c2c_dimension *get_dimension(const char *name)
        return NULL;
 }
 
+static int c2c_se_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+                       struct hist_entry *he)
+{
+       struct c2c_fmt *c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
+       struct c2c_dimension *dim = c2c_fmt->dim;
+       size_t len = fmt->user_len;
+
+       if (!len)
+               len = hists__col_len(he->hists, dim->se->se_width_idx);
+
+       return dim->se->se_snprintf(he, hpp->buf, hpp->size, len);
+}
+
+static int64_t c2c_se_cmp(struct perf_hpp_fmt *fmt,
+                         struct hist_entry *a, struct hist_entry *b)
+{
+       struct c2c_fmt *c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
+       struct c2c_dimension *dim = c2c_fmt->dim;
+
+       return dim->se->se_cmp(a, b);
+}
+
+static int64_t c2c_se_collapse(struct perf_hpp_fmt *fmt,
+                              struct hist_entry *a, struct hist_entry *b)
+{
+       struct c2c_fmt *c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
+       struct c2c_dimension *dim = c2c_fmt->dim;
+       int64_t (*collapse_fn)(struct hist_entry *, struct hist_entry *);
+
+       collapse_fn = dim->se->se_collapse ?: dim->se->se_cmp;
+       return collapse_fn(a, b);
+}
+
 static struct c2c_fmt *get_format(const char *name)
 {
        struct c2c_dimension *dim = get_dimension(name);
@@ -149,12 +197,12 @@ static struct c2c_fmt *get_format(const char *name)
        INIT_LIST_HEAD(&fmt->list);
        INIT_LIST_HEAD(&fmt->sort_list);
 
-       fmt->cmp        = dim->cmp;
-       fmt->sort       = dim->cmp;
-       fmt->entry      = dim->entry;
+       fmt->cmp        = dim->se ? c2c_se_cmp   : dim->cmp;
+       fmt->sort       = dim->se ? c2c_se_cmp   : dim->cmp;
+       fmt->entry      = dim->se ? c2c_se_entry : dim->entry;
        fmt->header     = c2c_header;
        fmt->width      = c2c_width;
-       fmt->collapse   = dim->cmp;
+       fmt->collapse   = dim->se ? c2c_se_collapse : dim->cmp;
        fmt->equal      = fmt_equal;
        fmt->free       = fmt_free;