xref: /kvmtool/util/rbtree-interval.c (revision ffc83de3572f96c484b199d743ed4fbf8ce1caba)
1e358b4fbSSasha Levin #include <kvm/rbtree-interval.h>
2e358b4fbSSasha Levin #include <stddef.h>
3495fbd4eSSasha Levin #include <errno.h>
4e358b4fbSSasha Levin 
5e358b4fbSSasha Levin struct rb_int_node *rb_int_search_single(struct rb_root *root, u64 point)
6e358b4fbSSasha Levin {
7e358b4fbSSasha Levin 	struct rb_node *node = root->rb_node;
8e358b4fbSSasha Levin 
9e358b4fbSSasha Levin 	while (node) {
10e358b4fbSSasha Levin 		struct rb_int_node *cur = rb_int(node);
11e358b4fbSSasha Levin 
12*ffc83de3SMichel Lespinasse 		if (point < cur->low)
13e358b4fbSSasha Levin 			node = node->rb_left;
14*ffc83de3SMichel Lespinasse 		else if (cur->high <= point)
15e358b4fbSSasha Levin 			node = node->rb_right;
16*ffc83de3SMichel Lespinasse 		else
17*ffc83de3SMichel Lespinasse 			return cur;
18e358b4fbSSasha Levin 	}
19e358b4fbSSasha Levin 
20e358b4fbSSasha Levin 	return NULL;
21e358b4fbSSasha Levin }
22e358b4fbSSasha Levin 
23e358b4fbSSasha Levin struct rb_int_node *rb_int_search_range(struct rb_root *root, u64 low, u64 high)
24e358b4fbSSasha Levin {
25e358b4fbSSasha Levin 	struct rb_int_node *range;
26e358b4fbSSasha Levin 
27e358b4fbSSasha Levin 	range = rb_int_search_single(root, low);
28e358b4fbSSasha Levin 	if (range == NULL)
29e358b4fbSSasha Levin 		return NULL;
30e358b4fbSSasha Levin 
31e358b4fbSSasha Levin 	/* We simply verify that 'high' is smaller than the end of the range where 'low' is located */
32e358b4fbSSasha Levin 	if (range->high < high)
33e358b4fbSSasha Levin 		return NULL;
34e358b4fbSSasha Levin 
35e358b4fbSSasha Levin 	return range;
36e358b4fbSSasha Levin }
37e358b4fbSSasha Levin 
3886824900SIngo Molnar /*
3986824900SIngo Molnar  * Update a node after it has been linked into the tree:
4086824900SIngo Molnar  */
4186824900SIngo Molnar static void propagate_callback(struct rb_node *node, struct rb_node *stop)
42e358b4fbSSasha Levin {
43c59e43aaSKirill A. Shutemov 	struct rb_int_node *i_node;
44e358b4fbSSasha Levin 
45c59e43aaSKirill A. Shutemov 	if (node == stop)
46c59e43aaSKirill A. Shutemov 		return;
47c59e43aaSKirill A. Shutemov 
48c59e43aaSKirill A. Shutemov 	i_node = rb_int(node);
49e358b4fbSSasha Levin 	i_node->max_high = i_node->high;
50e358b4fbSSasha Levin 
51e358b4fbSSasha Levin 	if (node->rb_left)
529f112becSSasha Levin 		i_node->max_high = max(i_node->max_high, rb_int(node->rb_left)->max_high);
53e358b4fbSSasha Levin 	if (node->rb_right)
549f112becSSasha Levin 		i_node->max_high = max(i_node->max_high, rb_int(node->rb_right)->max_high);
55e358b4fbSSasha Levin }
56e358b4fbSSasha Levin 
5786824900SIngo Molnar /*
5886824900SIngo Molnar  * Copy the extra data to a new node:
5986824900SIngo Molnar  */
6086824900SIngo Molnar static void copy_callback(struct rb_node *node_old, struct rb_node *node_new)
6186824900SIngo Molnar {
6286824900SIngo Molnar 	struct rb_int_node *i_node_old = rb_int(node_old);
6386824900SIngo Molnar 	struct rb_int_node *i_node_new = rb_int(node_new);
6486824900SIngo Molnar 
6586824900SIngo Molnar 	i_node_new->low		= i_node_old->low;
6686824900SIngo Molnar 	i_node_new->high	= i_node_old->high;
6786824900SIngo Molnar 
6886824900SIngo Molnar 	i_node_new->max_high	= i_node_old->max_high;
6986824900SIngo Molnar }
7086824900SIngo Molnar 
7186824900SIngo Molnar /*
7286824900SIngo Molnar  * Update after tree rotation:
7386824900SIngo Molnar  */
7486824900SIngo Molnar static void rotate_callback(struct rb_node *node_old, struct rb_node *node_new)
7586824900SIngo Molnar {
7686824900SIngo Molnar 	propagate_callback(node_old, NULL);
7786824900SIngo Molnar 	propagate_callback(node_new, NULL);
7886824900SIngo Molnar }
7986824900SIngo Molnar 
8086824900SIngo Molnar /*
8186824900SIngo Molnar  * All augmented rbtree callbacks:
8286824900SIngo Molnar  */
8386824900SIngo Molnar struct rb_augment_callbacks callbacks = {
8486824900SIngo Molnar 	.propagate	= propagate_callback,
8586824900SIngo Molnar 	.copy		= copy_callback,
8686824900SIngo Molnar 	.rotate		= rotate_callback,
8786824900SIngo Molnar };
8886824900SIngo Molnar 
89e358b4fbSSasha Levin int rb_int_insert(struct rb_root *root, struct rb_int_node *i_node)
90e358b4fbSSasha Levin {
9186824900SIngo Molnar 	struct rb_node **node = &root->rb_node, *parent = NULL;
92e358b4fbSSasha Levin 
93e358b4fbSSasha Levin 	while (*node) {
943e64a4a4SMichel Lespinasse 		struct rb_int_node *cur = rb_int(*node);
95e358b4fbSSasha Levin 
96e358b4fbSSasha Levin 		parent = *node;
973e64a4a4SMichel Lespinasse 		if (i_node->high <= cur->low)
983e64a4a4SMichel Lespinasse 			node = &cur->node.rb_left;
993e64a4a4SMichel Lespinasse 		else if (cur->high <= i_node->low)
1003e64a4a4SMichel Lespinasse 			node = &cur->node.rb_right;
101e358b4fbSSasha Levin 		else
102495fbd4eSSasha Levin 			return -EEXIST;
103e358b4fbSSasha Levin 	}
104e358b4fbSSasha Levin 
105e358b4fbSSasha Levin 	rb_link_node(&i_node->node, parent, node);
10686824900SIngo Molnar 	rb_insert_augmented(&i_node->node, root, &callbacks);
107e358b4fbSSasha Levin 
108495fbd4eSSasha Levin 	return 0;
109e358b4fbSSasha Levin }
110e358b4fbSSasha Levin 
111e358b4fbSSasha Levin void rb_int_erase(struct rb_root *root, struct rb_int_node *node)
112e358b4fbSSasha Levin {
11386824900SIngo Molnar 	rb_erase_augmented(&node->node, root, &callbacks);
114e358b4fbSSasha Levin }
115