]> git.karo-electronics.de Git - linux-beck.git/blobdiff - tools/perf/util/callchain.h
perf callchain: Feed callchains into a cursor
[linux-beck.git] / tools / perf / util / callchain.h
index c15fb8c24ad2b87388e97cd6346cfdebaac11dd5..d74a19af4a44583606df38477aadade005174633 100644 (file)
@@ -49,6 +49,27 @@ struct callchain_list {
        struct list_head        list;
 };
 
+/*
+ * A callchain cursor is a single linked list that
+ * let one feed a callchain progressively.
+ * It keeps persitent allocated entries to minimize
+ * allocations.
+ */
+struct callchain_cursor_node {
+       u64                             ip;
+       struct map                      *map;
+       struct symbol                   *sym;
+       struct callchain_cursor_node    *next;
+};
+
+struct callchain_cursor {
+       u64                             nr;
+       struct callchain_cursor_node    *first;
+       struct callchain_cursor_node    **last;
+       u64                             pos;
+       struct callchain_cursor_node    *curr;
+};
+
 static inline void callchain_init(struct callchain_root *root)
 {
        INIT_LIST_HEAD(&root->node.brothers);
@@ -67,9 +88,48 @@ static inline u64 cumul_hits(struct callchain_node *node)
 }
 
 int register_callchain_param(struct callchain_param *param);
-int callchain_append(struct callchain_root *root, struct ip_callchain *chain,
-                    struct map_symbol *syms, u64 period);
-int callchain_merge(struct callchain_root *dst, struct callchain_root *src);
+int callchain_append(struct callchain_root *root,
+                    struct callchain_cursor *cursor,
+                    u64 period);
+
+int callchain_merge(struct callchain_cursor *cursor,
+                   struct callchain_root *dst, struct callchain_root *src);
 
 bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event);
+
+/*
+ * Initialize a cursor before adding entries inside, but keep
+ * the previously allocated entries as a cache.
+ */
+static inline void callchain_cursor_reset(struct callchain_cursor *cursor)
+{
+       cursor->nr = 0;
+       cursor->last = &cursor->first;
+}
+
+int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
+                           struct map *map, struct symbol *sym);
+
+/* Close a cursor writing session. Initialize for the reader */
+static inline void callchain_cursor_commit(struct callchain_cursor *cursor)
+{
+       cursor->curr = cursor->first;
+       cursor->pos = 0;
+}
+
+/* Cursor reading iteration helpers */
+static inline struct callchain_cursor_node *
+callchain_cursor_current(struct callchain_cursor *cursor)
+{
+       if (cursor->pos == cursor->nr)
+               return NULL;
+
+       return cursor->curr;
+}
+
+static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
+{
+       cursor->curr = cursor->curr->next;
+       cursor->pos++;
+}
 #endif /* __PERF_CALLCHAIN_H */