1*fff3fd8aSMichel Lespinasse #include <linux/init.h> 2*fff3fd8aSMichel Lespinasse #include <linux/interval_tree.h> 3*fff3fd8aSMichel Lespinasse 4*fff3fd8aSMichel Lespinasse /* Callbacks for augmented rbtree insert and remove */ 5*fff3fd8aSMichel Lespinasse 6*fff3fd8aSMichel Lespinasse static inline unsigned long 7*fff3fd8aSMichel Lespinasse compute_subtree_last(struct interval_tree_node *node) 8*fff3fd8aSMichel Lespinasse { 9*fff3fd8aSMichel Lespinasse unsigned long max = node->last, subtree_last; 10*fff3fd8aSMichel Lespinasse if (node->rb.rb_left) { 11*fff3fd8aSMichel Lespinasse subtree_last = rb_entry(node->rb.rb_left, 12*fff3fd8aSMichel Lespinasse struct interval_tree_node, rb)->__subtree_last; 13*fff3fd8aSMichel Lespinasse if (max < subtree_last) 14*fff3fd8aSMichel Lespinasse max = subtree_last; 15*fff3fd8aSMichel Lespinasse } 16*fff3fd8aSMichel Lespinasse if (node->rb.rb_right) { 17*fff3fd8aSMichel Lespinasse subtree_last = rb_entry(node->rb.rb_right, 18*fff3fd8aSMichel Lespinasse struct interval_tree_node, rb)->__subtree_last; 19*fff3fd8aSMichel Lespinasse if (max < subtree_last) 20*fff3fd8aSMichel Lespinasse max = subtree_last; 21*fff3fd8aSMichel Lespinasse } 22*fff3fd8aSMichel Lespinasse return max; 23*fff3fd8aSMichel Lespinasse } 24*fff3fd8aSMichel Lespinasse 25*fff3fd8aSMichel Lespinasse RB_DECLARE_CALLBACKS(static, augment_callbacks, struct interval_tree_node, rb, 26*fff3fd8aSMichel Lespinasse unsigned long, __subtree_last, compute_subtree_last) 27*fff3fd8aSMichel Lespinasse 28*fff3fd8aSMichel Lespinasse /* Insert / remove interval nodes from the tree */ 29*fff3fd8aSMichel Lespinasse 30*fff3fd8aSMichel Lespinasse void interval_tree_insert(struct interval_tree_node *node, 31*fff3fd8aSMichel Lespinasse struct rb_root *root) 32*fff3fd8aSMichel Lespinasse { 33*fff3fd8aSMichel Lespinasse struct rb_node **link = &root->rb_node, *rb_parent = NULL; 34*fff3fd8aSMichel Lespinasse unsigned long start = node->start, last = node->last; 35*fff3fd8aSMichel Lespinasse struct interval_tree_node *parent; 36*fff3fd8aSMichel Lespinasse 37*fff3fd8aSMichel Lespinasse while (*link) { 38*fff3fd8aSMichel Lespinasse rb_parent = *link; 39*fff3fd8aSMichel Lespinasse parent = rb_entry(rb_parent, struct interval_tree_node, rb); 40*fff3fd8aSMichel Lespinasse if (parent->__subtree_last < last) 41*fff3fd8aSMichel Lespinasse parent->__subtree_last = last; 42*fff3fd8aSMichel Lespinasse if (start < parent->start) 43*fff3fd8aSMichel Lespinasse link = &parent->rb.rb_left; 44*fff3fd8aSMichel Lespinasse else 45*fff3fd8aSMichel Lespinasse link = &parent->rb.rb_right; 46*fff3fd8aSMichel Lespinasse } 47*fff3fd8aSMichel Lespinasse 48*fff3fd8aSMichel Lespinasse node->__subtree_last = last; 49*fff3fd8aSMichel Lespinasse rb_link_node(&node->rb, rb_parent, link); 50*fff3fd8aSMichel Lespinasse rb_insert_augmented(&node->rb, root, &augment_callbacks); 51*fff3fd8aSMichel Lespinasse } 52*fff3fd8aSMichel Lespinasse 53*fff3fd8aSMichel Lespinasse void interval_tree_remove(struct interval_tree_node *node, 54*fff3fd8aSMichel Lespinasse struct rb_root *root) 55*fff3fd8aSMichel Lespinasse { 56*fff3fd8aSMichel Lespinasse rb_erase_augmented(&node->rb, root, &augment_callbacks); 57*fff3fd8aSMichel Lespinasse } 58*fff3fd8aSMichel Lespinasse 59*fff3fd8aSMichel Lespinasse /* 60*fff3fd8aSMichel Lespinasse * Iterate over intervals intersecting [start;last] 61*fff3fd8aSMichel Lespinasse * 62*fff3fd8aSMichel Lespinasse * Note that a node's interval intersects [start;last] iff: 63*fff3fd8aSMichel Lespinasse * Cond1: node->start <= last 64*fff3fd8aSMichel Lespinasse * and 65*fff3fd8aSMichel Lespinasse * Cond2: start <= node->last 66*fff3fd8aSMichel Lespinasse */ 67*fff3fd8aSMichel Lespinasse 68*fff3fd8aSMichel Lespinasse static struct interval_tree_node * 69*fff3fd8aSMichel Lespinasse subtree_search(struct interval_tree_node *node, 70*fff3fd8aSMichel Lespinasse unsigned long start, unsigned long last) 71*fff3fd8aSMichel Lespinasse { 72*fff3fd8aSMichel Lespinasse while (true) { 73*fff3fd8aSMichel Lespinasse /* 74*fff3fd8aSMichel Lespinasse * Loop invariant: start <= node->__subtree_last 75*fff3fd8aSMichel Lespinasse * (Cond2 is satisfied by one of the subtree nodes) 76*fff3fd8aSMichel Lespinasse */ 77*fff3fd8aSMichel Lespinasse if (node->rb.rb_left) { 78*fff3fd8aSMichel Lespinasse struct interval_tree_node *left = 79*fff3fd8aSMichel Lespinasse rb_entry(node->rb.rb_left, 80*fff3fd8aSMichel Lespinasse struct interval_tree_node, rb); 81*fff3fd8aSMichel Lespinasse if (start <= left->__subtree_last) { 82*fff3fd8aSMichel Lespinasse /* 83*fff3fd8aSMichel Lespinasse * Some nodes in left subtree satisfy Cond2. 84*fff3fd8aSMichel Lespinasse * Iterate to find the leftmost such node N. 85*fff3fd8aSMichel Lespinasse * If it also satisfies Cond1, that's the match 86*fff3fd8aSMichel Lespinasse * we are looking for. Otherwise, there is no 87*fff3fd8aSMichel Lespinasse * matching interval as nodes to the right of N 88*fff3fd8aSMichel Lespinasse * can't satisfy Cond1 either. 89*fff3fd8aSMichel Lespinasse */ 90*fff3fd8aSMichel Lespinasse node = left; 91*fff3fd8aSMichel Lespinasse continue; 92*fff3fd8aSMichel Lespinasse } 93*fff3fd8aSMichel Lespinasse } 94*fff3fd8aSMichel Lespinasse if (node->start <= last) { /* Cond1 */ 95*fff3fd8aSMichel Lespinasse if (start <= node->last) /* Cond2 */ 96*fff3fd8aSMichel Lespinasse return node; /* node is leftmost match */ 97*fff3fd8aSMichel Lespinasse if (node->rb.rb_right) { 98*fff3fd8aSMichel Lespinasse node = rb_entry(node->rb.rb_right, 99*fff3fd8aSMichel Lespinasse struct interval_tree_node, rb); 100*fff3fd8aSMichel Lespinasse if (start <= node->__subtree_last) 101*fff3fd8aSMichel Lespinasse continue; 102*fff3fd8aSMichel Lespinasse } 103*fff3fd8aSMichel Lespinasse } 104*fff3fd8aSMichel Lespinasse return NULL; /* No match */ 105*fff3fd8aSMichel Lespinasse } 106*fff3fd8aSMichel Lespinasse } 107*fff3fd8aSMichel Lespinasse 108*fff3fd8aSMichel Lespinasse struct interval_tree_node * 109*fff3fd8aSMichel Lespinasse interval_tree_iter_first(struct rb_root *root, 110*fff3fd8aSMichel Lespinasse unsigned long start, unsigned long last) 111*fff3fd8aSMichel Lespinasse { 112*fff3fd8aSMichel Lespinasse struct interval_tree_node *node; 113*fff3fd8aSMichel Lespinasse 114*fff3fd8aSMichel Lespinasse if (!root->rb_node) 115*fff3fd8aSMichel Lespinasse return NULL; 116*fff3fd8aSMichel Lespinasse node = rb_entry(root->rb_node, struct interval_tree_node, rb); 117*fff3fd8aSMichel Lespinasse if (node->__subtree_last < start) 118*fff3fd8aSMichel Lespinasse return NULL; 119*fff3fd8aSMichel Lespinasse return subtree_search(node, start, last); 120*fff3fd8aSMichel Lespinasse } 121*fff3fd8aSMichel Lespinasse 122*fff3fd8aSMichel Lespinasse struct interval_tree_node * 123*fff3fd8aSMichel Lespinasse interval_tree_iter_next(struct interval_tree_node *node, 124*fff3fd8aSMichel Lespinasse unsigned long start, unsigned long last) 125*fff3fd8aSMichel Lespinasse { 126*fff3fd8aSMichel Lespinasse struct rb_node *rb = node->rb.rb_right, *prev; 127*fff3fd8aSMichel Lespinasse 128*fff3fd8aSMichel Lespinasse while (true) { 129*fff3fd8aSMichel Lespinasse /* 130*fff3fd8aSMichel Lespinasse * Loop invariants: 131*fff3fd8aSMichel Lespinasse * Cond1: node->start <= last 132*fff3fd8aSMichel Lespinasse * rb == node->rb.rb_right 133*fff3fd8aSMichel Lespinasse * 134*fff3fd8aSMichel Lespinasse * First, search right subtree if suitable 135*fff3fd8aSMichel Lespinasse */ 136*fff3fd8aSMichel Lespinasse if (rb) { 137*fff3fd8aSMichel Lespinasse struct interval_tree_node *right = 138*fff3fd8aSMichel Lespinasse rb_entry(rb, struct interval_tree_node, rb); 139*fff3fd8aSMichel Lespinasse if (start <= right->__subtree_last) 140*fff3fd8aSMichel Lespinasse return subtree_search(right, start, last); 141*fff3fd8aSMichel Lespinasse } 142*fff3fd8aSMichel Lespinasse 143*fff3fd8aSMichel Lespinasse /* Move up the tree until we come from a node's left child */ 144*fff3fd8aSMichel Lespinasse do { 145*fff3fd8aSMichel Lespinasse rb = rb_parent(&node->rb); 146*fff3fd8aSMichel Lespinasse if (!rb) 147*fff3fd8aSMichel Lespinasse return NULL; 148*fff3fd8aSMichel Lespinasse prev = &node->rb; 149*fff3fd8aSMichel Lespinasse node = rb_entry(rb, struct interval_tree_node, rb); 150*fff3fd8aSMichel Lespinasse rb = node->rb.rb_right; 151*fff3fd8aSMichel Lespinasse } while (prev == rb); 152*fff3fd8aSMichel Lespinasse 153*fff3fd8aSMichel Lespinasse /* Check if the node intersects [start;last] */ 154*fff3fd8aSMichel Lespinasse if (last < node->start) /* !Cond1 */ 155*fff3fd8aSMichel Lespinasse return NULL; 156*fff3fd8aSMichel Lespinasse else if (start <= node->last) /* Cond2 */ 157*fff3fd8aSMichel Lespinasse return node; 158*fff3fd8aSMichel Lespinasse } 159*fff3fd8aSMichel Lespinasse } 160