xref: /linux-6.15/lib/interval_tree.c (revision ceb08ee9)
1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2fff3fd8aSMichel Lespinasse #include <linux/interval_tree.h>
39826a516SMichel Lespinasse #include <linux/interval_tree_generic.h>
485c5e27cSRasmus Villemoes #include <linux/compiler.h>
585c5e27cSRasmus Villemoes #include <linux/export.h>
6fff3fd8aSMichel Lespinasse 
79826a516SMichel Lespinasse #define START(node) ((node)->start)
89826a516SMichel Lespinasse #define LAST(node)  ((node)->last)
9fff3fd8aSMichel Lespinasse 
109826a516SMichel Lespinasse INTERVAL_TREE_DEFINE(struct interval_tree_node, rb,
119826a516SMichel Lespinasse 		     unsigned long, __subtree_last,
129826a516SMichel Lespinasse 		     START, LAST,, interval_tree)
13a88cc108SChris Wilson 
14a88cc108SChris Wilson EXPORT_SYMBOL_GPL(interval_tree_insert);
15a88cc108SChris Wilson EXPORT_SYMBOL_GPL(interval_tree_remove);
16a88cc108SChris Wilson EXPORT_SYMBOL_GPL(interval_tree_iter_first);
17a88cc108SChris Wilson EXPORT_SYMBOL_GPL(interval_tree_iter_next);
185fe93786SJason Gunthorpe 
195fe93786SJason Gunthorpe #ifdef CONFIG_INTERVAL_TREE_SPAN_ITER
205fe93786SJason Gunthorpe /*
215fe93786SJason Gunthorpe  * Roll nodes[1] into nodes[0] by advancing nodes[1] to the end of a contiguous
225fe93786SJason Gunthorpe  * span of nodes. This makes nodes[0]->last the end of that contiguous used span
23*ceb08ee9SWei Yang  * of indexes that started at the original nodes[1]->start.
24*ceb08ee9SWei Yang  *
25*ceb08ee9SWei Yang  * If there is an interior hole, nodes[1] is now the first node starting the
26*ceb08ee9SWei Yang  * next used span. A hole span is between nodes[0]->last and nodes[1]->start.
27*ceb08ee9SWei Yang  *
28*ceb08ee9SWei Yang  * If there is a tailing hole, nodes[1] is now NULL. A hole span is between
29*ceb08ee9SWei Yang  * nodes[0]->last and last_index.
30*ceb08ee9SWei Yang  *
31*ceb08ee9SWei Yang  * If the contiguous used range span to last_index, nodes[1] is set to NULL.
325fe93786SJason Gunthorpe  */
335fe93786SJason Gunthorpe static void
interval_tree_span_iter_next_gap(struct interval_tree_span_iter * state)345fe93786SJason Gunthorpe interval_tree_span_iter_next_gap(struct interval_tree_span_iter *state)
355fe93786SJason Gunthorpe {
365fe93786SJason Gunthorpe 	struct interval_tree_node *cur = state->nodes[1];
375fe93786SJason Gunthorpe 
385fe93786SJason Gunthorpe 	state->nodes[0] = cur;
395fe93786SJason Gunthorpe 	do {
405fe93786SJason Gunthorpe 		if (cur->last > state->nodes[0]->last)
415fe93786SJason Gunthorpe 			state->nodes[0] = cur;
425fe93786SJason Gunthorpe 		cur = interval_tree_iter_next(cur, state->first_index,
435fe93786SJason Gunthorpe 					      state->last_index);
445fe93786SJason Gunthorpe 	} while (cur && (state->nodes[0]->last >= cur->start ||
455fe93786SJason Gunthorpe 			 state->nodes[0]->last + 1 == cur->start));
465fe93786SJason Gunthorpe 	state->nodes[1] = cur;
475fe93786SJason Gunthorpe }
485fe93786SJason Gunthorpe 
interval_tree_span_iter_first(struct interval_tree_span_iter * iter,struct rb_root_cached * itree,unsigned long first_index,unsigned long last_index)495fe93786SJason Gunthorpe void interval_tree_span_iter_first(struct interval_tree_span_iter *iter,
505fe93786SJason Gunthorpe 				   struct rb_root_cached *itree,
515fe93786SJason Gunthorpe 				   unsigned long first_index,
525fe93786SJason Gunthorpe 				   unsigned long last_index)
535fe93786SJason Gunthorpe {
545fe93786SJason Gunthorpe 	iter->first_index = first_index;
555fe93786SJason Gunthorpe 	iter->last_index = last_index;
565fe93786SJason Gunthorpe 	iter->nodes[0] = NULL;
575fe93786SJason Gunthorpe 	iter->nodes[1] =
585fe93786SJason Gunthorpe 		interval_tree_iter_first(itree, first_index, last_index);
595fe93786SJason Gunthorpe 	if (!iter->nodes[1]) {
605fe93786SJason Gunthorpe 		/* No nodes intersect the span, whole span is hole */
615fe93786SJason Gunthorpe 		iter->start_hole = first_index;
625fe93786SJason Gunthorpe 		iter->last_hole = last_index;
635fe93786SJason Gunthorpe 		iter->is_hole = 1;
645fe93786SJason Gunthorpe 		return;
655fe93786SJason Gunthorpe 	}
665fe93786SJason Gunthorpe 	if (iter->nodes[1]->start > first_index) {
675fe93786SJason Gunthorpe 		/* Leading hole on first iteration */
685fe93786SJason Gunthorpe 		iter->start_hole = first_index;
695fe93786SJason Gunthorpe 		iter->last_hole = iter->nodes[1]->start - 1;
705fe93786SJason Gunthorpe 		iter->is_hole = 1;
715fe93786SJason Gunthorpe 		interval_tree_span_iter_next_gap(iter);
725fe93786SJason Gunthorpe 		return;
735fe93786SJason Gunthorpe 	}
745fe93786SJason Gunthorpe 
755fe93786SJason Gunthorpe 	/* Starting inside a used */
765fe93786SJason Gunthorpe 	iter->start_used = first_index;
775fe93786SJason Gunthorpe 	iter->is_hole = 0;
785fe93786SJason Gunthorpe 	interval_tree_span_iter_next_gap(iter);
795fe93786SJason Gunthorpe 	iter->last_used = iter->nodes[0]->last;
805fe93786SJason Gunthorpe 	if (iter->last_used >= last_index) {
815fe93786SJason Gunthorpe 		iter->last_used = last_index;
825fe93786SJason Gunthorpe 		iter->nodes[0] = NULL;
835fe93786SJason Gunthorpe 		iter->nodes[1] = NULL;
845fe93786SJason Gunthorpe 	}
855fe93786SJason Gunthorpe }
865fe93786SJason Gunthorpe EXPORT_SYMBOL_GPL(interval_tree_span_iter_first);
875fe93786SJason Gunthorpe 
interval_tree_span_iter_next(struct interval_tree_span_iter * iter)885fe93786SJason Gunthorpe void interval_tree_span_iter_next(struct interval_tree_span_iter *iter)
895fe93786SJason Gunthorpe {
905fe93786SJason Gunthorpe 	if (!iter->nodes[0] && !iter->nodes[1]) {
915fe93786SJason Gunthorpe 		iter->is_hole = -1;
925fe93786SJason Gunthorpe 		return;
935fe93786SJason Gunthorpe 	}
945fe93786SJason Gunthorpe 
955fe93786SJason Gunthorpe 	if (iter->is_hole) {
965fe93786SJason Gunthorpe 		iter->start_used = iter->last_hole + 1;
975fe93786SJason Gunthorpe 		iter->last_used = iter->nodes[0]->last;
985fe93786SJason Gunthorpe 		if (iter->last_used >= iter->last_index) {
995fe93786SJason Gunthorpe 			iter->last_used = iter->last_index;
1005fe93786SJason Gunthorpe 			iter->nodes[0] = NULL;
1015fe93786SJason Gunthorpe 			iter->nodes[1] = NULL;
1025fe93786SJason Gunthorpe 		}
1035fe93786SJason Gunthorpe 		iter->is_hole = 0;
1045fe93786SJason Gunthorpe 		return;
1055fe93786SJason Gunthorpe 	}
1065fe93786SJason Gunthorpe 
1075fe93786SJason Gunthorpe 	if (!iter->nodes[1]) {
1085fe93786SJason Gunthorpe 		/* Trailing hole */
1095fe93786SJason Gunthorpe 		iter->start_hole = iter->nodes[0]->last + 1;
1105fe93786SJason Gunthorpe 		iter->last_hole = iter->last_index;
1115fe93786SJason Gunthorpe 		iter->nodes[0] = NULL;
1125fe93786SJason Gunthorpe 		iter->is_hole = 1;
1135fe93786SJason Gunthorpe 		return;
1145fe93786SJason Gunthorpe 	}
1155fe93786SJason Gunthorpe 
1165fe93786SJason Gunthorpe 	/* must have both nodes[0] and [1], interior hole */
1175fe93786SJason Gunthorpe 	iter->start_hole = iter->nodes[0]->last + 1;
1185fe93786SJason Gunthorpe 	iter->last_hole = iter->nodes[1]->start - 1;
1195fe93786SJason Gunthorpe 	iter->is_hole = 1;
1205fe93786SJason Gunthorpe 	interval_tree_span_iter_next_gap(iter);
1215fe93786SJason Gunthorpe }
1225fe93786SJason Gunthorpe EXPORT_SYMBOL_GPL(interval_tree_span_iter_next);
1235fe93786SJason Gunthorpe 
1245fe93786SJason Gunthorpe /*
1255fe93786SJason Gunthorpe  * Advance the iterator index to a specific position. The returned used/hole is
1265fe93786SJason Gunthorpe  * updated to start at new_index. This is faster than calling
1275fe93786SJason Gunthorpe  * interval_tree_span_iter_first() as it can avoid full searches in several
1285fe93786SJason Gunthorpe  * cases where the iterator is already set.
1295fe93786SJason Gunthorpe  */
interval_tree_span_iter_advance(struct interval_tree_span_iter * iter,struct rb_root_cached * itree,unsigned long new_index)1305fe93786SJason Gunthorpe void interval_tree_span_iter_advance(struct interval_tree_span_iter *iter,
1315fe93786SJason Gunthorpe 				     struct rb_root_cached *itree,
1325fe93786SJason Gunthorpe 				     unsigned long new_index)
1335fe93786SJason Gunthorpe {
1345fe93786SJason Gunthorpe 	if (iter->is_hole == -1)
1355fe93786SJason Gunthorpe 		return;
1365fe93786SJason Gunthorpe 
1375fe93786SJason Gunthorpe 	iter->first_index = new_index;
1385fe93786SJason Gunthorpe 	if (new_index > iter->last_index) {
1395fe93786SJason Gunthorpe 		iter->is_hole = -1;
1405fe93786SJason Gunthorpe 		return;
1415fe93786SJason Gunthorpe 	}
1425fe93786SJason Gunthorpe 
1435fe93786SJason Gunthorpe 	/* Rely on the union aliasing hole/used */
1445fe93786SJason Gunthorpe 	if (iter->start_hole <= new_index && new_index <= iter->last_hole) {
1455fe93786SJason Gunthorpe 		iter->start_hole = new_index;
1465fe93786SJason Gunthorpe 		return;
1475fe93786SJason Gunthorpe 	}
1485fe93786SJason Gunthorpe 	if (new_index == iter->last_hole + 1)
1495fe93786SJason Gunthorpe 		interval_tree_span_iter_next(iter);
1505fe93786SJason Gunthorpe 	else
1515fe93786SJason Gunthorpe 		interval_tree_span_iter_first(iter, itree, new_index,
1525fe93786SJason Gunthorpe 					      iter->last_index);
1535fe93786SJason Gunthorpe }
1545fe93786SJason Gunthorpe EXPORT_SYMBOL_GPL(interval_tree_span_iter_advance);
1555fe93786SJason Gunthorpe #endif
156