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