1*5da6aea3SPeter Zijlstra /* SPDX-License-Identifier: GPL-2.0-or-later */ 2*5da6aea3SPeter Zijlstra /* 3*5da6aea3SPeter Zijlstra Interval Trees 4*5da6aea3SPeter Zijlstra (C) 2012 Michel Lespinasse <[email protected]> 5*5da6aea3SPeter Zijlstra 6*5da6aea3SPeter Zijlstra 7*5da6aea3SPeter Zijlstra include/linux/interval_tree_generic.h 8*5da6aea3SPeter Zijlstra */ 9*5da6aea3SPeter Zijlstra 10*5da6aea3SPeter Zijlstra #include <linux/rbtree_augmented.h> 11*5da6aea3SPeter Zijlstra 12*5da6aea3SPeter Zijlstra /* 13*5da6aea3SPeter Zijlstra * Template for implementing interval trees 14*5da6aea3SPeter Zijlstra * 15*5da6aea3SPeter Zijlstra * ITSTRUCT: struct type of the interval tree nodes 16*5da6aea3SPeter Zijlstra * ITRB: name of struct rb_node field within ITSTRUCT 17*5da6aea3SPeter Zijlstra * ITTYPE: type of the interval endpoints 18*5da6aea3SPeter Zijlstra * ITSUBTREE: name of ITTYPE field within ITSTRUCT holding last-in-subtree 19*5da6aea3SPeter Zijlstra * ITSTART(n): start endpoint of ITSTRUCT node n 20*5da6aea3SPeter Zijlstra * ITLAST(n): last endpoint of ITSTRUCT node n 21*5da6aea3SPeter Zijlstra * ITSTATIC: 'static' or empty 22*5da6aea3SPeter Zijlstra * ITPREFIX: prefix to use for the inline tree definitions 23*5da6aea3SPeter Zijlstra * 24*5da6aea3SPeter Zijlstra * Note - before using this, please consider if generic version 25*5da6aea3SPeter Zijlstra * (interval_tree.h) would work for you... 26*5da6aea3SPeter Zijlstra */ 27*5da6aea3SPeter Zijlstra 28*5da6aea3SPeter Zijlstra #define INTERVAL_TREE_DEFINE(ITSTRUCT, ITRB, ITTYPE, ITSUBTREE, \ 29*5da6aea3SPeter Zijlstra ITSTART, ITLAST, ITSTATIC, ITPREFIX) \ 30*5da6aea3SPeter Zijlstra \ 31*5da6aea3SPeter Zijlstra /* Callbacks for augmented rbtree insert and remove */ \ 32*5da6aea3SPeter Zijlstra \ 33*5da6aea3SPeter Zijlstra RB_DECLARE_CALLBACKS_MAX(static, ITPREFIX ## _augment, \ 34*5da6aea3SPeter Zijlstra ITSTRUCT, ITRB, ITTYPE, ITSUBTREE, ITLAST) \ 35*5da6aea3SPeter Zijlstra \ 36*5da6aea3SPeter Zijlstra /* Insert / remove interval nodes from the tree */ \ 37*5da6aea3SPeter Zijlstra \ 38*5da6aea3SPeter Zijlstra ITSTATIC void ITPREFIX ## _insert(ITSTRUCT *node, \ 39*5da6aea3SPeter Zijlstra struct rb_root_cached *root) \ 40*5da6aea3SPeter Zijlstra { \ 41*5da6aea3SPeter Zijlstra struct rb_node **link = &root->rb_root.rb_node, *rb_parent = NULL; \ 42*5da6aea3SPeter Zijlstra ITTYPE start = ITSTART(node), last = ITLAST(node); \ 43*5da6aea3SPeter Zijlstra ITSTRUCT *parent; \ 44*5da6aea3SPeter Zijlstra bool leftmost = true; \ 45*5da6aea3SPeter Zijlstra \ 46*5da6aea3SPeter Zijlstra while (*link) { \ 47*5da6aea3SPeter Zijlstra rb_parent = *link; \ 48*5da6aea3SPeter Zijlstra parent = rb_entry(rb_parent, ITSTRUCT, ITRB); \ 49*5da6aea3SPeter Zijlstra if (parent->ITSUBTREE < last) \ 50*5da6aea3SPeter Zijlstra parent->ITSUBTREE = last; \ 51*5da6aea3SPeter Zijlstra if (start < ITSTART(parent)) \ 52*5da6aea3SPeter Zijlstra link = &parent->ITRB.rb_left; \ 53*5da6aea3SPeter Zijlstra else { \ 54*5da6aea3SPeter Zijlstra link = &parent->ITRB.rb_right; \ 55*5da6aea3SPeter Zijlstra leftmost = false; \ 56*5da6aea3SPeter Zijlstra } \ 57*5da6aea3SPeter Zijlstra } \ 58*5da6aea3SPeter Zijlstra \ 59*5da6aea3SPeter Zijlstra node->ITSUBTREE = last; \ 60*5da6aea3SPeter Zijlstra rb_link_node(&node->ITRB, rb_parent, link); \ 61*5da6aea3SPeter Zijlstra rb_insert_augmented_cached(&node->ITRB, root, \ 62*5da6aea3SPeter Zijlstra leftmost, &ITPREFIX ## _augment); \ 63*5da6aea3SPeter Zijlstra } \ 64*5da6aea3SPeter Zijlstra \ 65*5da6aea3SPeter Zijlstra ITSTATIC void ITPREFIX ## _remove(ITSTRUCT *node, \ 66*5da6aea3SPeter Zijlstra struct rb_root_cached *root) \ 67*5da6aea3SPeter Zijlstra { \ 68*5da6aea3SPeter Zijlstra rb_erase_augmented_cached(&node->ITRB, root, &ITPREFIX ## _augment); \ 69*5da6aea3SPeter Zijlstra } \ 70*5da6aea3SPeter Zijlstra \ 71*5da6aea3SPeter Zijlstra /* \ 72*5da6aea3SPeter Zijlstra * Iterate over intervals intersecting [start;last] \ 73*5da6aea3SPeter Zijlstra * \ 74*5da6aea3SPeter Zijlstra * Note that a node's interval intersects [start;last] iff: \ 75*5da6aea3SPeter Zijlstra * Cond1: ITSTART(node) <= last \ 76*5da6aea3SPeter Zijlstra * and \ 77*5da6aea3SPeter Zijlstra * Cond2: start <= ITLAST(node) \ 78*5da6aea3SPeter Zijlstra */ \ 79*5da6aea3SPeter Zijlstra \ 80*5da6aea3SPeter Zijlstra static ITSTRUCT * \ 81*5da6aea3SPeter Zijlstra ITPREFIX ## _subtree_search(ITSTRUCT *node, ITTYPE start, ITTYPE last) \ 82*5da6aea3SPeter Zijlstra { \ 83*5da6aea3SPeter Zijlstra while (true) { \ 84*5da6aea3SPeter Zijlstra /* \ 85*5da6aea3SPeter Zijlstra * Loop invariant: start <= node->ITSUBTREE \ 86*5da6aea3SPeter Zijlstra * (Cond2 is satisfied by one of the subtree nodes) \ 87*5da6aea3SPeter Zijlstra */ \ 88*5da6aea3SPeter Zijlstra if (node->ITRB.rb_left) { \ 89*5da6aea3SPeter Zijlstra ITSTRUCT *left = rb_entry(node->ITRB.rb_left, \ 90*5da6aea3SPeter Zijlstra ITSTRUCT, ITRB); \ 91*5da6aea3SPeter Zijlstra if (start <= left->ITSUBTREE) { \ 92*5da6aea3SPeter Zijlstra /* \ 93*5da6aea3SPeter Zijlstra * Some nodes in left subtree satisfy Cond2. \ 94*5da6aea3SPeter Zijlstra * Iterate to find the leftmost such node N. \ 95*5da6aea3SPeter Zijlstra * If it also satisfies Cond1, that's the \ 96*5da6aea3SPeter Zijlstra * match we are looking for. Otherwise, there \ 97*5da6aea3SPeter Zijlstra * is no matching interval as nodes to the \ 98*5da6aea3SPeter Zijlstra * right of N can't satisfy Cond1 either. \ 99*5da6aea3SPeter Zijlstra */ \ 100*5da6aea3SPeter Zijlstra node = left; \ 101*5da6aea3SPeter Zijlstra continue; \ 102*5da6aea3SPeter Zijlstra } \ 103*5da6aea3SPeter Zijlstra } \ 104*5da6aea3SPeter Zijlstra if (ITSTART(node) <= last) { /* Cond1 */ \ 105*5da6aea3SPeter Zijlstra if (start <= ITLAST(node)) /* Cond2 */ \ 106*5da6aea3SPeter Zijlstra return node; /* node is leftmost match */ \ 107*5da6aea3SPeter Zijlstra if (node->ITRB.rb_right) { \ 108*5da6aea3SPeter Zijlstra node = rb_entry(node->ITRB.rb_right, \ 109*5da6aea3SPeter Zijlstra ITSTRUCT, ITRB); \ 110*5da6aea3SPeter Zijlstra if (start <= node->ITSUBTREE) \ 111*5da6aea3SPeter Zijlstra continue; \ 112*5da6aea3SPeter Zijlstra } \ 113*5da6aea3SPeter Zijlstra } \ 114*5da6aea3SPeter Zijlstra return NULL; /* No match */ \ 115*5da6aea3SPeter Zijlstra } \ 116*5da6aea3SPeter Zijlstra } \ 117*5da6aea3SPeter Zijlstra \ 118*5da6aea3SPeter Zijlstra ITSTATIC ITSTRUCT * \ 119*5da6aea3SPeter Zijlstra ITPREFIX ## _iter_first(struct rb_root_cached *root, \ 120*5da6aea3SPeter Zijlstra ITTYPE start, ITTYPE last) \ 121*5da6aea3SPeter Zijlstra { \ 122*5da6aea3SPeter Zijlstra ITSTRUCT *node, *leftmost; \ 123*5da6aea3SPeter Zijlstra \ 124*5da6aea3SPeter Zijlstra if (!root->rb_root.rb_node) \ 125*5da6aea3SPeter Zijlstra return NULL; \ 126*5da6aea3SPeter Zijlstra \ 127*5da6aea3SPeter Zijlstra /* \ 128*5da6aea3SPeter Zijlstra * Fastpath range intersection/overlap between A: [a0, a1] and \ 129*5da6aea3SPeter Zijlstra * B: [b0, b1] is given by: \ 130*5da6aea3SPeter Zijlstra * \ 131*5da6aea3SPeter Zijlstra * a0 <= b1 && b0 <= a1 \ 132*5da6aea3SPeter Zijlstra * \ 133*5da6aea3SPeter Zijlstra * ... where A holds the lock range and B holds the smallest \ 134*5da6aea3SPeter Zijlstra * 'start' and largest 'last' in the tree. For the later, we \ 135*5da6aea3SPeter Zijlstra * rely on the root node, which by augmented interval tree \ 136*5da6aea3SPeter Zijlstra * property, holds the largest value in its last-in-subtree. \ 137*5da6aea3SPeter Zijlstra * This allows mitigating some of the tree walk overhead for \ 138*5da6aea3SPeter Zijlstra * for non-intersecting ranges, maintained and consulted in O(1). \ 139*5da6aea3SPeter Zijlstra */ \ 140*5da6aea3SPeter Zijlstra node = rb_entry(root->rb_root.rb_node, ITSTRUCT, ITRB); \ 141*5da6aea3SPeter Zijlstra if (node->ITSUBTREE < start) \ 142*5da6aea3SPeter Zijlstra return NULL; \ 143*5da6aea3SPeter Zijlstra \ 144*5da6aea3SPeter Zijlstra leftmost = rb_entry(root->rb_leftmost, ITSTRUCT, ITRB); \ 145*5da6aea3SPeter Zijlstra if (ITSTART(leftmost) > last) \ 146*5da6aea3SPeter Zijlstra return NULL; \ 147*5da6aea3SPeter Zijlstra \ 148*5da6aea3SPeter Zijlstra return ITPREFIX ## _subtree_search(node, start, last); \ 149*5da6aea3SPeter Zijlstra } \ 150*5da6aea3SPeter Zijlstra \ 151*5da6aea3SPeter Zijlstra ITSTATIC ITSTRUCT * \ 152*5da6aea3SPeter Zijlstra ITPREFIX ## _iter_next(ITSTRUCT *node, ITTYPE start, ITTYPE last) \ 153*5da6aea3SPeter Zijlstra { \ 154*5da6aea3SPeter Zijlstra struct rb_node *rb = node->ITRB.rb_right, *prev; \ 155*5da6aea3SPeter Zijlstra \ 156*5da6aea3SPeter Zijlstra while (true) { \ 157*5da6aea3SPeter Zijlstra /* \ 158*5da6aea3SPeter Zijlstra * Loop invariants: \ 159*5da6aea3SPeter Zijlstra * Cond1: ITSTART(node) <= last \ 160*5da6aea3SPeter Zijlstra * rb == node->ITRB.rb_right \ 161*5da6aea3SPeter Zijlstra * \ 162*5da6aea3SPeter Zijlstra * First, search right subtree if suitable \ 163*5da6aea3SPeter Zijlstra */ \ 164*5da6aea3SPeter Zijlstra if (rb) { \ 165*5da6aea3SPeter Zijlstra ITSTRUCT *right = rb_entry(rb, ITSTRUCT, ITRB); \ 166*5da6aea3SPeter Zijlstra if (start <= right->ITSUBTREE) \ 167*5da6aea3SPeter Zijlstra return ITPREFIX ## _subtree_search(right, \ 168*5da6aea3SPeter Zijlstra start, last); \ 169*5da6aea3SPeter Zijlstra } \ 170*5da6aea3SPeter Zijlstra \ 171*5da6aea3SPeter Zijlstra /* Move up the tree until we come from a node's left child */ \ 172*5da6aea3SPeter Zijlstra do { \ 173*5da6aea3SPeter Zijlstra rb = rb_parent(&node->ITRB); \ 174*5da6aea3SPeter Zijlstra if (!rb) \ 175*5da6aea3SPeter Zijlstra return NULL; \ 176*5da6aea3SPeter Zijlstra prev = &node->ITRB; \ 177*5da6aea3SPeter Zijlstra node = rb_entry(rb, ITSTRUCT, ITRB); \ 178*5da6aea3SPeter Zijlstra rb = node->ITRB.rb_right; \ 179*5da6aea3SPeter Zijlstra } while (prev == rb); \ 180*5da6aea3SPeter Zijlstra \ 181*5da6aea3SPeter Zijlstra /* Check if the node intersects [start;last] */ \ 182*5da6aea3SPeter Zijlstra if (last < ITSTART(node)) /* !Cond1 */ \ 183*5da6aea3SPeter Zijlstra return NULL; \ 184*5da6aea3SPeter Zijlstra else if (start <= ITLAST(node)) /* Cond2 */ \ 185*5da6aea3SPeter Zijlstra return node; \ 186*5da6aea3SPeter Zijlstra } \ 187*5da6aea3SPeter Zijlstra } 188