callchain.c revision e6817ec1d8ab31fc7b01906e305f848542df6413
16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*
26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Copyright (C) 2009-2011, Frederic Weisbecker <fweisbec@gmail.com>
36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *
46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Handle the callchains from the stream in an ad-hoc radix tree and then
56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * sort them in an rbtree.
66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *
76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Using a radix for code path provides a fast retrieval and factorizes
86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * memory use. Also that lets us use the paths in a hierarchical graph view.
96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *
106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */
116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <stdlib.h>
136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <stdio.h>
146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <stdbool.h>
156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <errno.h>
166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <math.h>
176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "util.h"
196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "callchain.h"
206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool ip_callchain__valid(struct ip_callchain *chain,
226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			 const union perf_event *event)
236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	unsigned int chain_size = event->header.size;
256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event;
266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	return chain->nr * sizeof(u64) <= chain_size;
276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define chain_for_each_child(child, parent)	\
306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	list_for_each_entry(child, &parent->children, siblings)
316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define chain_for_each_child_safe(child, next, parent)	\
336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	list_for_each_entry_safe(child, next, &parent->children, siblings)
346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennrb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		    enum chain_mode mode)
386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct rb_node **p = &root->rb_node;
406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct rb_node *parent = NULL;
416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct callchain_node *rnode;
426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	u64 chain_cumul = callchain_cumul_hits(chain);
436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	while (*p) {
456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		u64 rnode_cumul;
466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		parent = *p;
486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		rnode = rb_entry(parent, struct callchain_node, rb_node);
496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		rnode_cumul = callchain_cumul_hits(rnode);
506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		switch (mode) {
526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		case CHAIN_FLAT:
536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			if (rnode->hit < chain->hit)
546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn				p = &(*p)->rb_left;
556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			else
566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn				p = &(*p)->rb_right;
576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			break;
586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		case CHAIN_GRAPH_ABS: /* Falldown */
596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		case CHAIN_GRAPH_REL:
606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			if (rnode_cumul < chain_cumul)
616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn				p = &(*p)->rb_left;
626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			else
636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn				p = &(*p)->rb_right;
646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			break;
656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		case CHAIN_NONE:
666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		default:
676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			break;
686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		}
696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	rb_link_node(&chain->rb_node, parent, p);
726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	rb_insert_color(&chain->rb_node, root);
736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn__sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		  u64 min_hit)
786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct callchain_node *child;
806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	chain_for_each_child(child, node)
826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		__sort_chain_flat(rb_root, child, min_hit);
836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (node->hit && node->hit >= min_hit)
856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		rb_insert_callchain(rb_root, node, CHAIN_FLAT);
866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*
896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Once we get every callchains from the stream, we can now
906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * sort them by hit
916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */
926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennsort_chain_flat(struct rb_root *rb_root, struct callchain_root *root,
946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		u64 min_hit, struct callchain_param *param __used)
956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	__sort_chain_flat(rb_root, &root->node, min_hit);
976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void __sort_chain_graph_abs(struct callchain_node *node,
1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn				   u64 min_hit)
1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct callchain_node *child;
1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	node->rb_root = RB_ROOT;
1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	chain_for_each_child(child, node) {
1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		__sort_chain_graph_abs(child, min_hit);
1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		if (callchain_cumul_hits(child) >= min_hit)
1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			rb_insert_callchain(&node->rb_root, child,
1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn					    CHAIN_GRAPH_ABS);
1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennsort_chain_graph_abs(struct rb_root *rb_root, struct callchain_root *chain_root,
1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		     u64 min_hit, struct callchain_param *param __used)
1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	__sort_chain_graph_abs(&chain_root->node, min_hit);
1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	rb_root->rb_node = chain_root->node.rb_root.rb_node;
1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void __sort_chain_graph_rel(struct callchain_node *node,
1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn				   double min_percent)
1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct callchain_node *child;
1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	u64 min_hit;
1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	node->rb_root = RB_ROOT;
1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	min_hit = ceil(node->children_hit * min_percent);
1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	chain_for_each_child(child, node) {
1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		__sort_chain_graph_rel(child, min_percent);
1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		if (callchain_cumul_hits(child) >= min_hit)
1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			rb_insert_callchain(&node->rb_root, child,
1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn					    CHAIN_GRAPH_REL);
1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennsort_chain_graph_rel(struct rb_root *rb_root, struct callchain_root *chain_root,
1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		     u64 min_hit __used, struct callchain_param *param)
1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	__sort_chain_graph_rel(&chain_root->node, param->min_percent / 100.0);
1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	rb_root->rb_node = chain_root->node.rb_root.rb_node;
1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint callchain_register_param(struct callchain_param *param)
1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	switch (param->mode) {
1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	case CHAIN_GRAPH_ABS:
1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		param->sort = sort_chain_graph_abs;
1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		break;
1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	case CHAIN_GRAPH_REL:
1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		param->sort = sort_chain_graph_rel;
1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		break;
1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	case CHAIN_FLAT:
1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		param->sort = sort_chain_flat;
1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		break;
1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	case CHAIN_NONE:
1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	default:
1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		return -1;
1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	return 0;
1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*
1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Create a child for a parent. If inherit_children, then the new child
1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * will become the new parent of it's parent children
1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */
1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic struct callchain_node *
1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renncreate_child(struct callchain_node *parent, bool inherit_children)
1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct callchain_node *new;
1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	new = zalloc(sizeof(*new));
1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (!new) {
1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		perror("not enough memory to create child for code path tree");
1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		return NULL;
1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	new->parent = parent;
1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	INIT_LIST_HEAD(&new->children);
1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	INIT_LIST_HEAD(&new->val);
1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (inherit_children) {
1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		struct callchain_node *next;
1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		list_splice(&parent->children, &new->children);
1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		INIT_LIST_HEAD(&parent->children);
1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		chain_for_each_child(next, new)
1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			next->parent = new;
1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	list_add_tail(&new->siblings, &parent->children);
1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	return new;
1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*
2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Fill the node with callchain values
2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */
2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennfill_node(struct callchain_node *node, struct callchain_cursor *cursor)
2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct callchain_cursor_node *cursor_node;
2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	node->val_nr = cursor->nr - cursor->pos;
2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (!node->val_nr)
2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		pr_warning("Warning: empty node in callchain tree\n");
2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	cursor_node = callchain_cursor_current(cursor);
2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	while (cursor_node) {
2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		struct callchain_list *call;
2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		call = zalloc(sizeof(*call));
2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		if (!call) {
2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			perror("not enough memory for the code path tree");
2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			return;
2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		}
2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		call->ip = cursor_node->ip;
2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		call->ms.sym = cursor_node->sym;
2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		call->ms.map = cursor_node->map;
2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		list_add_tail(&call->list, &node->val);
2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		callchain_cursor_advance(cursor);
2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		cursor_node = callchain_cursor_current(cursor);
2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennadd_child(struct callchain_node *parent,
2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	  struct callchain_cursor *cursor,
2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	  u64 period)
2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct callchain_node *new;
2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	new = create_child(parent, false);
2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	fill_node(new, cursor);
2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	new->children_hit = 0;
2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	new->hit = period;
2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*
2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Split the parent in two parts (a new child is created) and
2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * give a part of its callchain to the created child.
2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Then create another child to host the given callchain of new branch
2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */
2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennsplit_add_child(struct callchain_node *parent,
2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		struct callchain_cursor *cursor,
2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		struct callchain_list *to_split,
2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		u64 idx_parents, u64 idx_local, u64 period)
2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct callchain_node *new;
2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct list_head *old_tail;
2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	unsigned int idx_total = idx_parents + idx_local;
2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	/* split */
2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	new = create_child(parent, true);
2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	/* split the callchain and move a part to the new child */
2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	old_tail = parent->val.prev;
2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	list_del_range(&to_split->list, old_tail);
2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	new->val.next = &to_split->list;
2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	new->val.prev = old_tail;
2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	to_split->list.prev = &new->val;
2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	old_tail->next = &new->val;
2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	/* split the hits */
2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	new->hit = parent->hit;
2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	new->children_hit = parent->children_hit;
2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	parent->children_hit = callchain_cumul_hits(new);
2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	new->val_nr = parent->val_nr - idx_local;
2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	parent->val_nr = idx_local;
2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	/* create a new child for the new branch if any */
2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (idx_total < cursor->nr) {
2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		parent->hit = 0;
2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		add_child(parent, cursor, period);
2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		parent->children_hit += period;
2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	} else {
2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		parent->hit = period;
2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int
2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennappend_chain(struct callchain_node *root,
2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	     struct callchain_cursor *cursor,
2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	     u64 period);
2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennappend_chain_children(struct callchain_node *root,
2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		      struct callchain_cursor *cursor,
2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		      u64 period)
2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct callchain_node *rnode;
2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	/* lookup in childrens */
3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	chain_for_each_child(rnode, root) {
3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		unsigned int ret = append_chain(rnode, cursor, period);
3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		if (!ret)
3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			goto inc_children_hit;
3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	/* nothing in children, add to the current node */
3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	add_child(root, cursor, period);
3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renninc_children_hit:
3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	root->children_hit += period;
3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int
3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennappend_chain(struct callchain_node *root,
3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	     struct callchain_cursor *cursor,
3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	     u64 period)
3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct callchain_cursor_node *curr_snap = cursor->curr;
3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct callchain_list *cnode;
3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	u64 start = cursor->pos;
3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	bool found = false;
3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	u64 matches;
3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	/*
3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	 * Lookup in the current node
3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	 * If we have a symbol, then compare the start to match
3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	 * anywhere inside a function.
3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	 */
3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	list_for_each_entry(cnode, &root->val, list) {
3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		struct callchain_cursor_node *node;
3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		struct symbol *sym;
3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		node = callchain_cursor_current(cursor);
3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		if (!node)
3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			break;
3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		sym = node->sym;
3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		if (cnode->ms.sym && sym) {
3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			if (cnode->ms.sym->start != sym->start)
3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn				break;
3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		} else if (cnode->ip != node->ip)
3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			break;
3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		if (!found)
3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			found = true;
3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		callchain_cursor_advance(cursor);
3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	/* matches not, relay on the parent */
3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (!found) {
3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		cursor->curr = curr_snap;
3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		cursor->pos = start;
3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		return -1;
3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	matches = cursor->pos - start;
3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	/* we match only a part of the node. Split it and add the new chain */
3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (matches < root->val_nr) {
3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		split_add_child(root, cursor, cnode, start, matches, period);
3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		return 0;
3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	/* we match 100% of the path, increment the hit */
3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (matches == root->val_nr && cursor->pos == cursor->nr) {
3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		root->hit += period;
3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		return 0;
3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	/* We match the node and still have a part remaining */
3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	append_chain_children(root, cursor, period);
3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	return 0;
3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint callchain_append(struct callchain_root *root,
3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		     struct callchain_cursor *cursor,
3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		     u64 period)
3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (!cursor->nr)
3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		return 0;
3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	callchain_cursor_commit(cursor);
3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	append_chain_children(&root->node, cursor, period);
3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (cursor->nr > root->max_depth)
3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		root->max_depth = cursor->nr;
3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	return 0;
3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int
3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennmerge_chain_branch(struct callchain_cursor *cursor,
3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		   struct callchain_node *dst, struct callchain_node *src)
3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct callchain_cursor_node **old_last = cursor->last;
4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct callchain_node *child, *next_child;
4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct callchain_list *list, *next_list;
4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	int old_pos = cursor->nr;
4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	int err = 0;
4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	list_for_each_entry_safe(list, next_list, &src->val, list) {
4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		callchain_cursor_append(cursor, list->ip,
4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn					list->ms.map, list->ms.sym);
4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		list_del(&list->list);
4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		free(list);
4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (src->hit) {
4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		callchain_cursor_commit(cursor);
4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		append_chain_children(dst, cursor, src->hit);
4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	chain_for_each_child_safe(child, next_child, src) {
4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		err = merge_chain_branch(cursor, dst, child);
4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		if (err)
4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			break;
4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		list_del(&child->siblings);
4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		free(child);
4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	cursor->nr = old_pos;
4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	cursor->last = old_last;
4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	return err;
4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint callchain_merge(struct callchain_cursor *cursor,
4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		    struct callchain_root *dst, struct callchain_root *src)
4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	return merge_chain_branch(cursor, &dst->node, &src->node);
4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint callchain_cursor_append(struct callchain_cursor *cursor,
4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			    u64 ip, struct map *map, struct symbol *sym)
4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	struct callchain_cursor_node *node = *cursor->last;
4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	if (!node) {
4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		node = calloc(sizeof(*node), 1);
4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		if (!node)
4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn			return -ENOMEM;
4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		*cursor->last = node;
4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	}
4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	node->ip = ip;
4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	node->map = map;
4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	node->sym = sym;
4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	cursor->nr++;
4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	cursor->last = &node->next;
4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	return 0;
4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn