1 // SPDX-License-Identifier: GPL-2.0-only
3 * call-path.h: Manipulate a tree data structure containing function call paths
4 * Copyright (c) 2014, Intel Corporation.
7 #include <linux/rbtree.h>
8 #include <linux/list.h>
9 #include <linux/zalloc.h>
12 #include "call-path.h"
14 static void call_path__init(struct call_path
*cp
, struct call_path
*parent
,
15 struct symbol
*sym
, u64 ip
, bool in_kernel
)
19 cp
->ip
= sym
? 0 : ip
;
21 cp
->in_kernel
= in_kernel
;
22 RB_CLEAR_NODE(&cp
->rb_node
);
23 cp
->children
= RB_ROOT
;
26 struct call_path_root
*call_path_root__new(void)
28 struct call_path_root
*cpr
;
30 cpr
= zalloc(sizeof(struct call_path_root
));
33 call_path__init(&cpr
->call_path
, NULL
, NULL
, 0, false);
34 INIT_LIST_HEAD(&cpr
->blocks
);
38 void call_path_root__free(struct call_path_root
*cpr
)
40 struct call_path_block
*pos
, *n
;
42 list_for_each_entry_safe(pos
, n
, &cpr
->blocks
, node
) {
43 list_del_init(&pos
->node
);
49 static struct call_path
*call_path__new(struct call_path_root
*cpr
,
50 struct call_path
*parent
,
51 struct symbol
*sym
, u64 ip
,
54 struct call_path_block
*cpb
;
58 if (cpr
->next
< cpr
->sz
) {
59 cpb
= list_last_entry(&cpr
->blocks
, struct call_path_block
,
62 cpb
= zalloc(sizeof(struct call_path_block
));
65 list_add_tail(&cpb
->node
, &cpr
->blocks
);
66 cpr
->sz
+= CALL_PATH_BLOCK_SIZE
;
69 n
= cpr
->next
++ & CALL_PATH_BLOCK_MASK
;
72 call_path__init(cp
, parent
, sym
, ip
, in_kernel
);
77 struct call_path
*call_path__findnew(struct call_path_root
*cpr
,
78 struct call_path
*parent
,
79 struct symbol
*sym
, u64 ip
, u64 ks
)
82 struct rb_node
*node_parent
= NULL
;
84 bool in_kernel
= ip
>= ks
;
90 return call_path__new(cpr
, parent
, sym
, ip
, in_kernel
);
92 p
= &parent
->children
.rb_node
;
95 cp
= rb_entry(node_parent
, struct call_path
, rb_node
);
97 if (cp
->sym
== sym
&& cp
->ip
== ip
)
100 if (sym
< cp
->sym
|| (sym
== cp
->sym
&& ip
< cp
->ip
))
106 cp
= call_path__new(cpr
, parent
, sym
, ip
, in_kernel
);
110 rb_link_node(&cp
->rb_node
, node_parent
, p
);
111 rb_insert_color(&cp
->rb_node
, &parent
->children
);