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 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 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 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 */ 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