xref: /dflybsd-src/sys/dev/drm/linux_interval_tree.c (revision 70abac43eccc0459c91599b3fbfd713067d53065)
1*70abac43SMatthew Dillon /*
2*70abac43SMatthew Dillon  * Copyright (c) 2019 Matthew Dillon <dillon@backplane.com>
3*70abac43SMatthew Dillon  * All rights reserved.
4*70abac43SMatthew Dillon  *
5*70abac43SMatthew Dillon  * Redistribution and use in source and binary forms, with or without
6*70abac43SMatthew Dillon  * modification, are permitted provided that the following conditions
7*70abac43SMatthew Dillon  * are met:
8*70abac43SMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
9*70abac43SMatthew Dillon  *    notice unmodified, this list of conditions, and the following
10*70abac43SMatthew Dillon  *    disclaimer.
11*70abac43SMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
12*70abac43SMatthew Dillon  *    notice, this list of conditions and the following disclaimer in the
13*70abac43SMatthew Dillon  *    documentation and/or other materials provided with the distribution.
14*70abac43SMatthew Dillon  *
15*70abac43SMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16*70abac43SMatthew Dillon  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17*70abac43SMatthew Dillon  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18*70abac43SMatthew Dillon  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19*70abac43SMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20*70abac43SMatthew Dillon  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21*70abac43SMatthew Dillon  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22*70abac43SMatthew Dillon  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23*70abac43SMatthew Dillon  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24*70abac43SMatthew Dillon  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*70abac43SMatthew Dillon  */
26*70abac43SMatthew Dillon 
27*70abac43SMatthew Dillon #include <linux/init.h>
28*70abac43SMatthew Dillon #include <linux/interval_tree.h>
29*70abac43SMatthew Dillon #include <linux/module.h>
30*70abac43SMatthew Dillon 
31*70abac43SMatthew Dillon typedef struct interval_tree_node itnode_t;
32*70abac43SMatthew Dillon 
33*70abac43SMatthew Dillon void
interval_tree_insert(struct interval_tree_node * node,struct rb_root * root)34*70abac43SMatthew Dillon interval_tree_insert(struct interval_tree_node *node, struct rb_root *root)
35*70abac43SMatthew Dillon {
36*70abac43SMatthew Dillon 	itnode_t *scan;
37*70abac43SMatthew Dillon 
38*70abac43SMatthew Dillon 	scan = (itnode_t *)root->rb_node;
39*70abac43SMatthew Dillon 	if (scan) {
40*70abac43SMatthew Dillon 		node->next = scan->next;
41*70abac43SMatthew Dillon 		node->atroot = 0;
42*70abac43SMatthew Dillon 		scan->next = node;
43*70abac43SMatthew Dillon 	} else {
44*70abac43SMatthew Dillon 		root->rb_node = (void *)node;
45*70abac43SMatthew Dillon 		node->atroot = 1;
46*70abac43SMatthew Dillon 		node->next = node;
47*70abac43SMatthew Dillon 	}
48*70abac43SMatthew Dillon }
49*70abac43SMatthew Dillon 
50*70abac43SMatthew Dillon void
interval_tree_remove(struct interval_tree_node * node,struct rb_root * root)51*70abac43SMatthew Dillon interval_tree_remove(struct interval_tree_node *node, struct rb_root *root)
52*70abac43SMatthew Dillon {
53*70abac43SMatthew Dillon 	itnode_t *scan;
54*70abac43SMatthew Dillon 
55*70abac43SMatthew Dillon 	scan = (itnode_t *)root->rb_node;
56*70abac43SMatthew Dillon 	KKASSERT(scan != NULL);
57*70abac43SMatthew Dillon 	while (scan->next != node) {
58*70abac43SMatthew Dillon 		scan = scan->next;
59*70abac43SMatthew Dillon 	}
60*70abac43SMatthew Dillon 	scan->next = node->next;
61*70abac43SMatthew Dillon 	if (scan == node) {
62*70abac43SMatthew Dillon 		/*
63*70abac43SMatthew Dillon 		 * Last element is being removed
64*70abac43SMatthew Dillon 		 */
65*70abac43SMatthew Dillon 		root->rb_node = NULL;
66*70abac43SMatthew Dillon 		node->atroot = 0;
67*70abac43SMatthew Dillon 	} else if ((itnode_t *)root->rb_node == node) {
68*70abac43SMatthew Dillon 		/*
69*70abac43SMatthew Dillon 		 * Root pointer is the node being removed, move the root
70*70abac43SMatthew Dillon 		 * pointer.
71*70abac43SMatthew Dillon 		 */
72*70abac43SMatthew Dillon 		node->atroot = 0;
73*70abac43SMatthew Dillon 		scan->atroot = 1;
74*70abac43SMatthew Dillon 		root->rb_node = (void *)scan;
75*70abac43SMatthew Dillon 	}
76*70abac43SMatthew Dillon }
77*70abac43SMatthew Dillon 
78*70abac43SMatthew Dillon struct interval_tree_node *
interval_tree_iter_first(struct rb_root * root,unsigned long start,unsigned long last)79*70abac43SMatthew Dillon interval_tree_iter_first(struct rb_root *root,
80*70abac43SMatthew Dillon                          unsigned long start, unsigned long last)
81*70abac43SMatthew Dillon {
82*70abac43SMatthew Dillon 	itnode_t *scan;
83*70abac43SMatthew Dillon 
84*70abac43SMatthew Dillon 	scan = (itnode_t *)root->rb_node;
85*70abac43SMatthew Dillon 	if (scan) {
86*70abac43SMatthew Dillon 		do {
87*70abac43SMatthew Dillon 			if (start <= scan->last &&
88*70abac43SMatthew Dillon 			    last >= scan->start) {
89*70abac43SMatthew Dillon 				return scan;
90*70abac43SMatthew Dillon 			}
91*70abac43SMatthew Dillon 			scan = scan->next;
92*70abac43SMatthew Dillon 		} while (scan->atroot == 0);
93*70abac43SMatthew Dillon 		scan = NULL;
94*70abac43SMatthew Dillon 	}
95*70abac43SMatthew Dillon 	return scan;
96*70abac43SMatthew Dillon }
97*70abac43SMatthew Dillon 
98*70abac43SMatthew Dillon struct interval_tree_node *
interval_tree_iter_next(struct interval_tree_node * node,unsigned long start,unsigned long last)99*70abac43SMatthew Dillon interval_tree_iter_next(struct interval_tree_node *node,
100*70abac43SMatthew Dillon 			unsigned long start, unsigned long last)
101*70abac43SMatthew Dillon {
102*70abac43SMatthew Dillon 	itnode_t *scan;
103*70abac43SMatthew Dillon 
104*70abac43SMatthew Dillon 	scan = node->next;
105*70abac43SMatthew Dillon 	while (scan->atroot == 0) {
106*70abac43SMatthew Dillon 		if (start <= scan->last &&
107*70abac43SMatthew Dillon 		    last >= scan->start) {
108*70abac43SMatthew Dillon 				return scan;
109*70abac43SMatthew Dillon 		}
110*70abac43SMatthew Dillon 		scan = scan->next;
111*70abac43SMatthew Dillon 	}
112*70abac43SMatthew Dillon 	return NULL;
113*70abac43SMatthew Dillon }
114