1*5da6aea3SPeter Zijlstra /* SPDX-License-Identifier: GPL-2.0-or-later */
2*5da6aea3SPeter Zijlstra /*
3*5da6aea3SPeter Zijlstra   Interval Trees
4*5da6aea3SPeter Zijlstra   (C) 2012  Michel Lespinasse <[email protected]>
5*5da6aea3SPeter Zijlstra 
6*5da6aea3SPeter Zijlstra 
7*5da6aea3SPeter Zijlstra   include/linux/interval_tree_generic.h
8*5da6aea3SPeter Zijlstra */
9*5da6aea3SPeter Zijlstra 
10*5da6aea3SPeter Zijlstra #include <linux/rbtree_augmented.h>
11*5da6aea3SPeter Zijlstra 
12*5da6aea3SPeter Zijlstra /*
13*5da6aea3SPeter Zijlstra  * Template for implementing interval trees
14*5da6aea3SPeter Zijlstra  *
15*5da6aea3SPeter Zijlstra  * ITSTRUCT:   struct type of the interval tree nodes
16*5da6aea3SPeter Zijlstra  * ITRB:       name of struct rb_node field within ITSTRUCT
17*5da6aea3SPeter Zijlstra  * ITTYPE:     type of the interval endpoints
18*5da6aea3SPeter Zijlstra  * ITSUBTREE:  name of ITTYPE field within ITSTRUCT holding last-in-subtree
19*5da6aea3SPeter Zijlstra  * ITSTART(n): start endpoint of ITSTRUCT node n
20*5da6aea3SPeter Zijlstra  * ITLAST(n):  last endpoint of ITSTRUCT node n
21*5da6aea3SPeter Zijlstra  * ITSTATIC:   'static' or empty
22*5da6aea3SPeter Zijlstra  * ITPREFIX:   prefix to use for the inline tree definitions
23*5da6aea3SPeter Zijlstra  *
24*5da6aea3SPeter Zijlstra  * Note - before using this, please consider if generic version
25*5da6aea3SPeter Zijlstra  * (interval_tree.h) would work for you...
26*5da6aea3SPeter Zijlstra  */
27*5da6aea3SPeter Zijlstra 
28*5da6aea3SPeter Zijlstra #define INTERVAL_TREE_DEFINE(ITSTRUCT, ITRB, ITTYPE, ITSUBTREE,		      \
29*5da6aea3SPeter Zijlstra 			     ITSTART, ITLAST, ITSTATIC, ITPREFIX)	      \
30*5da6aea3SPeter Zijlstra 									      \
31*5da6aea3SPeter Zijlstra /* Callbacks for augmented rbtree insert and remove */			      \
32*5da6aea3SPeter Zijlstra 									      \
33*5da6aea3SPeter Zijlstra RB_DECLARE_CALLBACKS_MAX(static, ITPREFIX ## _augment,			      \
34*5da6aea3SPeter Zijlstra 			 ITSTRUCT, ITRB, ITTYPE, ITSUBTREE, ITLAST)	      \
35*5da6aea3SPeter Zijlstra 									      \
36*5da6aea3SPeter Zijlstra /* Insert / remove interval nodes from the tree */			      \
37*5da6aea3SPeter Zijlstra 									      \
38*5da6aea3SPeter Zijlstra ITSTATIC void ITPREFIX ## _insert(ITSTRUCT *node,			      \
39*5da6aea3SPeter Zijlstra 				  struct rb_root_cached *root)	 	      \
40*5da6aea3SPeter Zijlstra {									      \
41*5da6aea3SPeter Zijlstra 	struct rb_node **link = &root->rb_root.rb_node, *rb_parent = NULL;    \
42*5da6aea3SPeter Zijlstra 	ITTYPE start = ITSTART(node), last = ITLAST(node);		      \
43*5da6aea3SPeter Zijlstra 	ITSTRUCT *parent;						      \
44*5da6aea3SPeter Zijlstra 	bool leftmost = true;						      \
45*5da6aea3SPeter Zijlstra 									      \
46*5da6aea3SPeter Zijlstra 	while (*link) {							      \
47*5da6aea3SPeter Zijlstra 		rb_parent = *link;					      \
48*5da6aea3SPeter Zijlstra 		parent = rb_entry(rb_parent, ITSTRUCT, ITRB);		      \
49*5da6aea3SPeter Zijlstra 		if (parent->ITSUBTREE < last)				      \
50*5da6aea3SPeter Zijlstra 			parent->ITSUBTREE = last;			      \
51*5da6aea3SPeter Zijlstra 		if (start < ITSTART(parent))				      \
52*5da6aea3SPeter Zijlstra 			link = &parent->ITRB.rb_left;			      \
53*5da6aea3SPeter Zijlstra 		else {							      \
54*5da6aea3SPeter Zijlstra 			link = &parent->ITRB.rb_right;			      \
55*5da6aea3SPeter Zijlstra 			leftmost = false;				      \
56*5da6aea3SPeter Zijlstra 		}							      \
57*5da6aea3SPeter Zijlstra 	}								      \
58*5da6aea3SPeter Zijlstra 									      \
59*5da6aea3SPeter Zijlstra 	node->ITSUBTREE = last;						      \
60*5da6aea3SPeter Zijlstra 	rb_link_node(&node->ITRB, rb_parent, link);			      \
61*5da6aea3SPeter Zijlstra 	rb_insert_augmented_cached(&node->ITRB, root,			      \
62*5da6aea3SPeter Zijlstra 				   leftmost, &ITPREFIX ## _augment);	      \
63*5da6aea3SPeter Zijlstra }									      \
64*5da6aea3SPeter Zijlstra 									      \
65*5da6aea3SPeter Zijlstra ITSTATIC void ITPREFIX ## _remove(ITSTRUCT *node,			      \
66*5da6aea3SPeter Zijlstra 				  struct rb_root_cached *root)		      \
67*5da6aea3SPeter Zijlstra {									      \
68*5da6aea3SPeter Zijlstra 	rb_erase_augmented_cached(&node->ITRB, root, &ITPREFIX ## _augment);  \
69*5da6aea3SPeter Zijlstra }									      \
70*5da6aea3SPeter Zijlstra 									      \
71*5da6aea3SPeter Zijlstra /*									      \
72*5da6aea3SPeter Zijlstra  * Iterate over intervals intersecting [start;last]			      \
73*5da6aea3SPeter Zijlstra  *									      \
74*5da6aea3SPeter Zijlstra  * Note that a node's interval intersects [start;last] iff:		      \
75*5da6aea3SPeter Zijlstra  *   Cond1: ITSTART(node) <= last					      \
76*5da6aea3SPeter Zijlstra  * and									      \
77*5da6aea3SPeter Zijlstra  *   Cond2: start <= ITLAST(node)					      \
78*5da6aea3SPeter Zijlstra  */									      \
79*5da6aea3SPeter Zijlstra 									      \
80*5da6aea3SPeter Zijlstra static ITSTRUCT *							      \
81*5da6aea3SPeter Zijlstra ITPREFIX ## _subtree_search(ITSTRUCT *node, ITTYPE start, ITTYPE last)	      \
82*5da6aea3SPeter Zijlstra {									      \
83*5da6aea3SPeter Zijlstra 	while (true) {							      \
84*5da6aea3SPeter Zijlstra 		/*							      \
85*5da6aea3SPeter Zijlstra 		 * Loop invariant: start <= node->ITSUBTREE		      \
86*5da6aea3SPeter Zijlstra 		 * (Cond2 is satisfied by one of the subtree nodes)	      \
87*5da6aea3SPeter Zijlstra 		 */							      \
88*5da6aea3SPeter Zijlstra 		if (node->ITRB.rb_left) {				      \
89*5da6aea3SPeter Zijlstra 			ITSTRUCT *left = rb_entry(node->ITRB.rb_left,	      \
90*5da6aea3SPeter Zijlstra 						  ITSTRUCT, ITRB);	      \
91*5da6aea3SPeter Zijlstra 			if (start <= left->ITSUBTREE) {			      \
92*5da6aea3SPeter Zijlstra 				/*					      \
93*5da6aea3SPeter Zijlstra 				 * Some nodes in left subtree satisfy Cond2.  \
94*5da6aea3SPeter Zijlstra 				 * Iterate to find the leftmost such node N.  \
95*5da6aea3SPeter Zijlstra 				 * If it also satisfies Cond1, that's the     \
96*5da6aea3SPeter Zijlstra 				 * match we are looking for. Otherwise, there \
97*5da6aea3SPeter Zijlstra 				 * is no matching interval as nodes to the    \
98*5da6aea3SPeter Zijlstra 				 * right of N can't satisfy Cond1 either.     \
99*5da6aea3SPeter Zijlstra 				 */					      \
100*5da6aea3SPeter Zijlstra 				node = left;				      \
101*5da6aea3SPeter Zijlstra 				continue;				      \
102*5da6aea3SPeter Zijlstra 			}						      \
103*5da6aea3SPeter Zijlstra 		}							      \
104*5da6aea3SPeter Zijlstra 		if (ITSTART(node) <= last) {		/* Cond1 */	      \
105*5da6aea3SPeter Zijlstra 			if (start <= ITLAST(node))	/* Cond2 */	      \
106*5da6aea3SPeter Zijlstra 				return node;	/* node is leftmost match */  \
107*5da6aea3SPeter Zijlstra 			if (node->ITRB.rb_right) {			      \
108*5da6aea3SPeter Zijlstra 				node = rb_entry(node->ITRB.rb_right,	      \
109*5da6aea3SPeter Zijlstra 						ITSTRUCT, ITRB);	      \
110*5da6aea3SPeter Zijlstra 				if (start <= node->ITSUBTREE)		      \
111*5da6aea3SPeter Zijlstra 					continue;			      \
112*5da6aea3SPeter Zijlstra 			}						      \
113*5da6aea3SPeter Zijlstra 		}							      \
114*5da6aea3SPeter Zijlstra 		return NULL;	/* No match */				      \
115*5da6aea3SPeter Zijlstra 	}								      \
116*5da6aea3SPeter Zijlstra }									      \
117*5da6aea3SPeter Zijlstra 									      \
118*5da6aea3SPeter Zijlstra ITSTATIC ITSTRUCT *							      \
119*5da6aea3SPeter Zijlstra ITPREFIX ## _iter_first(struct rb_root_cached *root,			      \
120*5da6aea3SPeter Zijlstra 			ITTYPE start, ITTYPE last)			      \
121*5da6aea3SPeter Zijlstra {									      \
122*5da6aea3SPeter Zijlstra 	ITSTRUCT *node, *leftmost;					      \
123*5da6aea3SPeter Zijlstra 									      \
124*5da6aea3SPeter Zijlstra 	if (!root->rb_root.rb_node)					      \
125*5da6aea3SPeter Zijlstra 		return NULL;						      \
126*5da6aea3SPeter Zijlstra 									      \
127*5da6aea3SPeter Zijlstra 	/*								      \
128*5da6aea3SPeter Zijlstra 	 * Fastpath range intersection/overlap between A: [a0, a1] and	      \
129*5da6aea3SPeter Zijlstra 	 * B: [b0, b1] is given by:					      \
130*5da6aea3SPeter Zijlstra 	 *								      \
131*5da6aea3SPeter Zijlstra 	 *         a0 <= b1 && b0 <= a1					      \
132*5da6aea3SPeter Zijlstra 	 *								      \
133*5da6aea3SPeter Zijlstra 	 *  ... where A holds the lock range and B holds the smallest	      \
134*5da6aea3SPeter Zijlstra 	 * 'start' and largest 'last' in the tree. For the later, we	      \
135*5da6aea3SPeter Zijlstra 	 * rely on the root node, which by augmented interval tree	      \
136*5da6aea3SPeter Zijlstra 	 * property, holds the largest value in its last-in-subtree.	      \
137*5da6aea3SPeter Zijlstra 	 * This allows mitigating some of the tree walk overhead for	      \
138*5da6aea3SPeter Zijlstra 	 * for non-intersecting ranges, maintained and consulted in O(1).     \
139*5da6aea3SPeter Zijlstra 	 */								      \
140*5da6aea3SPeter Zijlstra 	node = rb_entry(root->rb_root.rb_node, ITSTRUCT, ITRB);		      \
141*5da6aea3SPeter Zijlstra 	if (node->ITSUBTREE < start)					      \
142*5da6aea3SPeter Zijlstra 		return NULL;						      \
143*5da6aea3SPeter Zijlstra 									      \
144*5da6aea3SPeter Zijlstra 	leftmost = rb_entry(root->rb_leftmost, ITSTRUCT, ITRB);		      \
145*5da6aea3SPeter Zijlstra 	if (ITSTART(leftmost) > last)					      \
146*5da6aea3SPeter Zijlstra 		return NULL;						      \
147*5da6aea3SPeter Zijlstra 									      \
148*5da6aea3SPeter Zijlstra 	return ITPREFIX ## _subtree_search(node, start, last);		      \
149*5da6aea3SPeter Zijlstra }									      \
150*5da6aea3SPeter Zijlstra 									      \
151*5da6aea3SPeter Zijlstra ITSTATIC ITSTRUCT *							      \
152*5da6aea3SPeter Zijlstra ITPREFIX ## _iter_next(ITSTRUCT *node, ITTYPE start, ITTYPE last)	      \
153*5da6aea3SPeter Zijlstra {									      \
154*5da6aea3SPeter Zijlstra 	struct rb_node *rb = node->ITRB.rb_right, *prev;		      \
155*5da6aea3SPeter Zijlstra 									      \
156*5da6aea3SPeter Zijlstra 	while (true) {							      \
157*5da6aea3SPeter Zijlstra 		/*							      \
158*5da6aea3SPeter Zijlstra 		 * Loop invariants:					      \
159*5da6aea3SPeter Zijlstra 		 *   Cond1: ITSTART(node) <= last			      \
160*5da6aea3SPeter Zijlstra 		 *   rb == node->ITRB.rb_right				      \
161*5da6aea3SPeter Zijlstra 		 *							      \
162*5da6aea3SPeter Zijlstra 		 * First, search right subtree if suitable		      \
163*5da6aea3SPeter Zijlstra 		 */							      \
164*5da6aea3SPeter Zijlstra 		if (rb) {						      \
165*5da6aea3SPeter Zijlstra 			ITSTRUCT *right = rb_entry(rb, ITSTRUCT, ITRB);	      \
166*5da6aea3SPeter Zijlstra 			if (start <= right->ITSUBTREE)			      \
167*5da6aea3SPeter Zijlstra 				return ITPREFIX ## _subtree_search(right,     \
168*5da6aea3SPeter Zijlstra 								start, last); \
169*5da6aea3SPeter Zijlstra 		}							      \
170*5da6aea3SPeter Zijlstra 									      \
171*5da6aea3SPeter Zijlstra 		/* Move up the tree until we come from a node's left child */ \
172*5da6aea3SPeter Zijlstra 		do {							      \
173*5da6aea3SPeter Zijlstra 			rb = rb_parent(&node->ITRB);			      \
174*5da6aea3SPeter Zijlstra 			if (!rb)					      \
175*5da6aea3SPeter Zijlstra 				return NULL;				      \
176*5da6aea3SPeter Zijlstra 			prev = &node->ITRB;				      \
177*5da6aea3SPeter Zijlstra 			node = rb_entry(rb, ITSTRUCT, ITRB);		      \
178*5da6aea3SPeter Zijlstra 			rb = node->ITRB.rb_right;			      \
179*5da6aea3SPeter Zijlstra 		} while (prev == rb);					      \
180*5da6aea3SPeter Zijlstra 									      \
181*5da6aea3SPeter Zijlstra 		/* Check if the node intersects [start;last] */		      \
182*5da6aea3SPeter Zijlstra 		if (last < ITSTART(node))		/* !Cond1 */	      \
183*5da6aea3SPeter Zijlstra 			return NULL;					      \
184*5da6aea3SPeter Zijlstra 		else if (start <= ITLAST(node))		/* Cond2 */	      \
185*5da6aea3SPeter Zijlstra 			return node;					      \
186*5da6aea3SPeter Zijlstra 	}								      \
187*5da6aea3SPeter Zijlstra }
188