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);
18*5fe93786SJason Gunthorpe
19*5fe93786SJason Gunthorpe #ifdef CONFIG_INTERVAL_TREE_SPAN_ITER
20*5fe93786SJason Gunthorpe /*
21*5fe93786SJason Gunthorpe * Roll nodes[1] into nodes[0] by advancing nodes[1] to the end of a contiguous
22*5fe93786SJason Gunthorpe * span of nodes. This makes nodes[0]->last the end of that contiguous used span
23*5fe93786SJason Gunthorpe * indexes that started at the original nodes[1]->start. nodes[1] is now the
24*5fe93786SJason Gunthorpe * first node starting the next used span. A hole span is between nodes[0]->last
25*5fe93786SJason Gunthorpe * and nodes[1]->start. nodes[1] must be !NULL.
26*5fe93786SJason Gunthorpe */
27*5fe93786SJason Gunthorpe static void
interval_tree_span_iter_next_gap(struct interval_tree_span_iter * state)28*5fe93786SJason Gunthorpe interval_tree_span_iter_next_gap(struct interval_tree_span_iter *state)
29*5fe93786SJason Gunthorpe {
30*5fe93786SJason Gunthorpe struct interval_tree_node *cur = state->nodes[1];
31*5fe93786SJason Gunthorpe
32*5fe93786SJason Gunthorpe state->nodes[0] = cur;
33*5fe93786SJason Gunthorpe do {
34*5fe93786SJason Gunthorpe if (cur->last > state->nodes[0]->last)
35*5fe93786SJason Gunthorpe state->nodes[0] = cur;
36*5fe93786SJason Gunthorpe cur = interval_tree_iter_next(cur, state->first_index,
37*5fe93786SJason Gunthorpe state->last_index);
38*5fe93786SJason Gunthorpe } while (cur && (state->nodes[0]->last >= cur->start ||
39*5fe93786SJason Gunthorpe state->nodes[0]->last + 1 == cur->start));
40*5fe93786SJason Gunthorpe state->nodes[1] = cur;
41*5fe93786SJason Gunthorpe }
42*5fe93786SJason 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)43*5fe93786SJason Gunthorpe void interval_tree_span_iter_first(struct interval_tree_span_iter *iter,
44*5fe93786SJason Gunthorpe struct rb_root_cached *itree,
45*5fe93786SJason Gunthorpe unsigned long first_index,
46*5fe93786SJason Gunthorpe unsigned long last_index)
47*5fe93786SJason Gunthorpe {
48*5fe93786SJason Gunthorpe iter->first_index = first_index;
49*5fe93786SJason Gunthorpe iter->last_index = last_index;
50*5fe93786SJason Gunthorpe iter->nodes[0] = NULL;
51*5fe93786SJason Gunthorpe iter->nodes[1] =
52*5fe93786SJason Gunthorpe interval_tree_iter_first(itree, first_index, last_index);
53*5fe93786SJason Gunthorpe if (!iter->nodes[1]) {
54*5fe93786SJason Gunthorpe /* No nodes intersect the span, whole span is hole */
55*5fe93786SJason Gunthorpe iter->start_hole = first_index;
56*5fe93786SJason Gunthorpe iter->last_hole = last_index;
57*5fe93786SJason Gunthorpe iter->is_hole = 1;
58*5fe93786SJason Gunthorpe return;
59*5fe93786SJason Gunthorpe }
60*5fe93786SJason Gunthorpe if (iter->nodes[1]->start > first_index) {
61*5fe93786SJason Gunthorpe /* Leading hole on first iteration */
62*5fe93786SJason Gunthorpe iter->start_hole = first_index;
63*5fe93786SJason Gunthorpe iter->last_hole = iter->nodes[1]->start - 1;
64*5fe93786SJason Gunthorpe iter->is_hole = 1;
65*5fe93786SJason Gunthorpe interval_tree_span_iter_next_gap(iter);
66*5fe93786SJason Gunthorpe return;
67*5fe93786SJason Gunthorpe }
68*5fe93786SJason Gunthorpe
69*5fe93786SJason Gunthorpe /* Starting inside a used */
70*5fe93786SJason Gunthorpe iter->start_used = first_index;
71*5fe93786SJason Gunthorpe iter->is_hole = 0;
72*5fe93786SJason Gunthorpe interval_tree_span_iter_next_gap(iter);
73*5fe93786SJason Gunthorpe iter->last_used = iter->nodes[0]->last;
74*5fe93786SJason Gunthorpe if (iter->last_used >= last_index) {
75*5fe93786SJason Gunthorpe iter->last_used = last_index;
76*5fe93786SJason Gunthorpe iter->nodes[0] = NULL;
77*5fe93786SJason Gunthorpe iter->nodes[1] = NULL;
78*5fe93786SJason Gunthorpe }
79*5fe93786SJason Gunthorpe }
80*5fe93786SJason Gunthorpe EXPORT_SYMBOL_GPL(interval_tree_span_iter_first);
81*5fe93786SJason Gunthorpe
interval_tree_span_iter_next(struct interval_tree_span_iter * iter)82*5fe93786SJason Gunthorpe void interval_tree_span_iter_next(struct interval_tree_span_iter *iter)
83*5fe93786SJason Gunthorpe {
84*5fe93786SJason Gunthorpe if (!iter->nodes[0] && !iter->nodes[1]) {
85*5fe93786SJason Gunthorpe iter->is_hole = -1;
86*5fe93786SJason Gunthorpe return;
87*5fe93786SJason Gunthorpe }
88*5fe93786SJason Gunthorpe
89*5fe93786SJason Gunthorpe if (iter->is_hole) {
90*5fe93786SJason Gunthorpe iter->start_used = iter->last_hole + 1;
91*5fe93786SJason Gunthorpe iter->last_used = iter->nodes[0]->last;
92*5fe93786SJason Gunthorpe if (iter->last_used >= iter->last_index) {
93*5fe93786SJason Gunthorpe iter->last_used = iter->last_index;
94*5fe93786SJason Gunthorpe iter->nodes[0] = NULL;
95*5fe93786SJason Gunthorpe iter->nodes[1] = NULL;
96*5fe93786SJason Gunthorpe }
97*5fe93786SJason Gunthorpe iter->is_hole = 0;
98*5fe93786SJason Gunthorpe return;
99*5fe93786SJason Gunthorpe }
100*5fe93786SJason Gunthorpe
101*5fe93786SJason Gunthorpe if (!iter->nodes[1]) {
102*5fe93786SJason Gunthorpe /* Trailing hole */
103*5fe93786SJason Gunthorpe iter->start_hole = iter->nodes[0]->last + 1;
104*5fe93786SJason Gunthorpe iter->last_hole = iter->last_index;
105*5fe93786SJason Gunthorpe iter->nodes[0] = NULL;
106*5fe93786SJason Gunthorpe iter->is_hole = 1;
107*5fe93786SJason Gunthorpe return;
108*5fe93786SJason Gunthorpe }
109*5fe93786SJason Gunthorpe
110*5fe93786SJason Gunthorpe /* must have both nodes[0] and [1], interior hole */
111*5fe93786SJason Gunthorpe iter->start_hole = iter->nodes[0]->last + 1;
112*5fe93786SJason Gunthorpe iter->last_hole = iter->nodes[1]->start - 1;
113*5fe93786SJason Gunthorpe iter->is_hole = 1;
114*5fe93786SJason Gunthorpe interval_tree_span_iter_next_gap(iter);
115*5fe93786SJason Gunthorpe }
116*5fe93786SJason Gunthorpe EXPORT_SYMBOL_GPL(interval_tree_span_iter_next);
117*5fe93786SJason Gunthorpe
118*5fe93786SJason Gunthorpe /*
119*5fe93786SJason Gunthorpe * Advance the iterator index to a specific position. The returned used/hole is
120*5fe93786SJason Gunthorpe * updated to start at new_index. This is faster than calling
121*5fe93786SJason Gunthorpe * interval_tree_span_iter_first() as it can avoid full searches in several
122*5fe93786SJason Gunthorpe * cases where the iterator is already set.
123*5fe93786SJason Gunthorpe */
interval_tree_span_iter_advance(struct interval_tree_span_iter * iter,struct rb_root_cached * itree,unsigned long new_index)124*5fe93786SJason Gunthorpe void interval_tree_span_iter_advance(struct interval_tree_span_iter *iter,
125*5fe93786SJason Gunthorpe struct rb_root_cached *itree,
126*5fe93786SJason Gunthorpe unsigned long new_index)
127*5fe93786SJason Gunthorpe {
128*5fe93786SJason Gunthorpe if (iter->is_hole == -1)
129*5fe93786SJason Gunthorpe return;
130*5fe93786SJason Gunthorpe
131*5fe93786SJason Gunthorpe iter->first_index = new_index;
132*5fe93786SJason Gunthorpe if (new_index > iter->last_index) {
133*5fe93786SJason Gunthorpe iter->is_hole = -1;
134*5fe93786SJason Gunthorpe return;
135*5fe93786SJason Gunthorpe }
136*5fe93786SJason Gunthorpe
137*5fe93786SJason Gunthorpe /* Rely on the union aliasing hole/used */
138*5fe93786SJason Gunthorpe if (iter->start_hole <= new_index && new_index <= iter->last_hole) {
139*5fe93786SJason Gunthorpe iter->start_hole = new_index;
140*5fe93786SJason Gunthorpe return;
141*5fe93786SJason Gunthorpe }
142*5fe93786SJason Gunthorpe if (new_index == iter->last_hole + 1)
143*5fe93786SJason Gunthorpe interval_tree_span_iter_next(iter);
144*5fe93786SJason Gunthorpe else
145*5fe93786SJason Gunthorpe interval_tree_span_iter_first(iter, itree, new_index,
146*5fe93786SJason Gunthorpe iter->last_index);
147*5fe93786SJason Gunthorpe }
148*5fe93786SJason Gunthorpe EXPORT_SYMBOL_GPL(interval_tree_span_iter_advance);
149*5fe93786SJason Gunthorpe #endif
150