2 * call-path.h: Manipulate a tree data structure containing function call paths
3 * Copyright (c) 2014, Intel Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 #include <linux/rbtree.h>
17 #include <linux/list.h>
20 #include "call-path.h"
22 static void call_path__init(struct call_path
*cp
, struct call_path
*parent
,
23 struct symbol
*sym
, u64 ip
, bool in_kernel
)
27 cp
->ip
= sym
? 0 : ip
;
29 cp
->in_kernel
= in_kernel
;
30 RB_CLEAR_NODE(&cp
->rb_node
);
31 cp
->children
= RB_ROOT
;
34 struct call_path_root
*call_path_root__new(void)
36 struct call_path_root
*cpr
;
38 cpr
= zalloc(sizeof(struct call_path_root
));
41 call_path__init(&cpr
->call_path
, NULL
, NULL
, 0, false);
42 INIT_LIST_HEAD(&cpr
->blocks
);
46 void call_path_root__free(struct call_path_root
*cpr
)
48 struct call_path_block
*pos
, *n
;
50 list_for_each_entry_safe(pos
, n
, &cpr
->blocks
, node
) {
57 static struct call_path
*call_path__new(struct call_path_root
*cpr
,
58 struct call_path
*parent
,
59 struct symbol
*sym
, u64 ip
,
62 struct call_path_block
*cpb
;
66 if (cpr
->next
< cpr
->sz
) {
67 cpb
= list_last_entry(&cpr
->blocks
, struct call_path_block
,
70 cpb
= zalloc(sizeof(struct call_path_block
));
73 list_add_tail(&cpb
->node
, &cpr
->blocks
);
74 cpr
->sz
+= CALL_PATH_BLOCK_SIZE
;
77 n
= cpr
->next
++ & CALL_PATH_BLOCK_MASK
;
80 call_path__init(cp
, parent
, sym
, ip
, in_kernel
);
85 struct call_path
*call_path__findnew(struct call_path_root
*cpr
,
86 struct call_path
*parent
,
87 struct symbol
*sym
, u64 ip
, u64 ks
)
90 struct rb_node
*node_parent
= NULL
;
92 bool in_kernel
= ip
>= ks
;
98 return call_path__new(cpr
, parent
, sym
, ip
, in_kernel
);
100 p
= &parent
->children
.rb_node
;
103 cp
= rb_entry(node_parent
, struct call_path
, rb_node
);
105 if (cp
->sym
== sym
&& cp
->ip
== ip
)
108 if (sym
< cp
->sym
|| (sym
== cp
->sym
&& ip
< cp
->ip
))
114 cp
= call_path__new(cpr
, parent
, sym
, ip
, in_kernel
);
118 rb_link_node(&cp
->rb_node
, node_parent
, p
);
119 rb_insert_color(&cp
->rb_node
, &parent
->children
);