1 // SPDX-License-Identifier: GPL-2.0-only
2 #include <linux/interval_tree.h>
3 #include <linux/interval_tree_generic.h>
4 #include <linux/compiler.h>
5 #include <linux/export.h>
7 #define START(node) ((node)->start)
8 #define LAST(node) ((node)->last)
10 INTERVAL_TREE_DEFINE(struct interval_tree_node
, rb
,
11 unsigned long, __subtree_last
,
12 START
, LAST
,, interval_tree
)
14 EXPORT_SYMBOL_GPL(interval_tree_insert
);
15 EXPORT_SYMBOL_GPL(interval_tree_remove
);
16 EXPORT_SYMBOL_GPL(interval_tree_iter_first
);
17 EXPORT_SYMBOL_GPL(interval_tree_iter_next
);
19 #ifdef CONFIG_INTERVAL_TREE_SPAN_ITER
21 * Roll nodes[1] into nodes[0] by advancing nodes[1] to the end of a contiguous
22 * span of nodes. This makes nodes[0]->last the end of that contiguous used span
23 * indexes that started at the original nodes[1]->start. nodes[1] is now the
24 * first node starting the next used span. A hole span is between nodes[0]->last
25 * and nodes[1]->start. nodes[1] must be !NULL.
28 interval_tree_span_iter_next_gap(struct interval_tree_span_iter
*state
)
30 struct interval_tree_node
*cur
= state
->nodes
[1];
32 state
->nodes
[0] = cur
;
34 if (cur
->last
> state
->nodes
[0]->last
)
35 state
->nodes
[0] = cur
;
36 cur
= interval_tree_iter_next(cur
, state
->first_index
,
38 } while (cur
&& (state
->nodes
[0]->last
>= cur
->start
||
39 state
->nodes
[0]->last
+ 1 == cur
->start
));
40 state
->nodes
[1] = cur
;
43 void interval_tree_span_iter_first(struct interval_tree_span_iter
*iter
,
44 struct rb_root_cached
*itree
,
45 unsigned long first_index
,
46 unsigned long last_index
)
48 iter
->first_index
= first_index
;
49 iter
->last_index
= last_index
;
50 iter
->nodes
[0] = NULL
;
52 interval_tree_iter_first(itree
, first_index
, last_index
);
53 if (!iter
->nodes
[1]) {
54 /* No nodes intersect the span, whole span is hole */
55 iter
->start_hole
= first_index
;
56 iter
->last_hole
= last_index
;
60 if (iter
->nodes
[1]->start
> first_index
) {
61 /* Leading hole on first iteration */
62 iter
->start_hole
= first_index
;
63 iter
->last_hole
= iter
->nodes
[1]->start
- 1;
65 interval_tree_span_iter_next_gap(iter
);
69 /* Starting inside a used */
70 iter
->start_used
= first_index
;
72 interval_tree_span_iter_next_gap(iter
);
73 iter
->last_used
= iter
->nodes
[0]->last
;
74 if (iter
->last_used
>= last_index
) {
75 iter
->last_used
= last_index
;
76 iter
->nodes
[0] = NULL
;
77 iter
->nodes
[1] = NULL
;
80 EXPORT_SYMBOL_GPL(interval_tree_span_iter_first
);
82 void interval_tree_span_iter_next(struct interval_tree_span_iter
*iter
)
84 if (!iter
->nodes
[0] && !iter
->nodes
[1]) {
90 iter
->start_used
= iter
->last_hole
+ 1;
91 iter
->last_used
= iter
->nodes
[0]->last
;
92 if (iter
->last_used
>= iter
->last_index
) {
93 iter
->last_used
= iter
->last_index
;
94 iter
->nodes
[0] = NULL
;
95 iter
->nodes
[1] = NULL
;
101 if (!iter
->nodes
[1]) {
103 iter
->start_hole
= iter
->nodes
[0]->last
+ 1;
104 iter
->last_hole
= iter
->last_index
;
105 iter
->nodes
[0] = NULL
;
110 /* must have both nodes[0] and [1], interior hole */
111 iter
->start_hole
= iter
->nodes
[0]->last
+ 1;
112 iter
->last_hole
= iter
->nodes
[1]->start
- 1;
114 interval_tree_span_iter_next_gap(iter
);
116 EXPORT_SYMBOL_GPL(interval_tree_span_iter_next
);
119 * Advance the iterator index to a specific position. The returned used/hole is
120 * updated to start at new_index. This is faster than calling
121 * interval_tree_span_iter_first() as it can avoid full searches in several
122 * cases where the iterator is already set.
124 void interval_tree_span_iter_advance(struct interval_tree_span_iter
*iter
,
125 struct rb_root_cached
*itree
,
126 unsigned long new_index
)
128 if (iter
->is_hole
== -1)
131 iter
->first_index
= new_index
;
132 if (new_index
> iter
->last_index
) {
137 /* Rely on the union aliasing hole/used */
138 if (iter
->start_hole
<= new_index
&& new_index
<= iter
->last_hole
) {
139 iter
->start_hole
= new_index
;
142 if (new_index
== iter
->last_hole
+ 1)
143 interval_tree_span_iter_next(iter
);
145 interval_tree_span_iter_first(iter
, itree
, new_index
,
148 EXPORT_SYMBOL_GPL(interval_tree_span_iter_advance
);