11a59d1b8SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */ 29826a516SMichel Lespinasse /* 39826a516SMichel Lespinasse Interval Trees 49826a516SMichel Lespinasse (C) 2012 Michel Lespinasse <[email protected]> 59826a516SMichel Lespinasse 69826a516SMichel Lespinasse 79826a516SMichel Lespinasse include/linux/interval_tree_generic.h 89826a516SMichel Lespinasse */ 99826a516SMichel Lespinasse 109826a516SMichel Lespinasse #include <linux/rbtree_augmented.h> 119826a516SMichel Lespinasse 129826a516SMichel Lespinasse /* 139826a516SMichel Lespinasse * Template for implementing interval trees 149826a516SMichel Lespinasse * 159826a516SMichel Lespinasse * ITSTRUCT: struct type of the interval tree nodes 169826a516SMichel Lespinasse * ITRB: name of struct rb_node field within ITSTRUCT 179826a516SMichel Lespinasse * ITTYPE: type of the interval endpoints 189826a516SMichel Lespinasse * ITSUBTREE: name of ITTYPE field within ITSTRUCT holding last-in-subtree 199826a516SMichel Lespinasse * ITSTART(n): start endpoint of ITSTRUCT node n 209826a516SMichel Lespinasse * ITLAST(n): last endpoint of ITSTRUCT node n 219826a516SMichel Lespinasse * ITSTATIC: 'static' or empty 229826a516SMichel Lespinasse * ITPREFIX: prefix to use for the inline tree definitions 239826a516SMichel Lespinasse * 24f2686bb4SDavidlohr Bueso * Note - before using this, please consider if generic version 259826a516SMichel Lespinasse * (interval_tree.h) would work for you... 269826a516SMichel Lespinasse */ 279826a516SMichel Lespinasse 289826a516SMichel Lespinasse #define INTERVAL_TREE_DEFINE(ITSTRUCT, ITRB, ITTYPE, ITSUBTREE, \ 299826a516SMichel Lespinasse ITSTART, ITLAST, ITSTATIC, ITPREFIX) \ 309826a516SMichel Lespinasse \ 319826a516SMichel Lespinasse /* Callbacks for augmented rbtree insert and remove */ \ 329826a516SMichel Lespinasse \ 33315cc066SMichel Lespinasse RB_DECLARE_CALLBACKS_MAX(static, ITPREFIX ## _augment, \ 34315cc066SMichel Lespinasse ITSTRUCT, ITRB, ITTYPE, ITSUBTREE, ITLAST) \ 359826a516SMichel Lespinasse \ 369826a516SMichel Lespinasse /* Insert / remove interval nodes from the tree */ \ 379826a516SMichel Lespinasse \ 38f808c13fSDavidlohr Bueso ITSTATIC void ITPREFIX ## _insert(ITSTRUCT *node, \ 39f808c13fSDavidlohr Bueso struct rb_root_cached *root) \ 409826a516SMichel Lespinasse { \ 41f808c13fSDavidlohr Bueso struct rb_node **link = &root->rb_root.rb_node, *rb_parent = NULL; \ 429826a516SMichel Lespinasse ITTYPE start = ITSTART(node), last = ITLAST(node); \ 439826a516SMichel Lespinasse ITSTRUCT *parent; \ 44f808c13fSDavidlohr Bueso bool leftmost = true; \ 459826a516SMichel Lespinasse \ 469826a516SMichel Lespinasse while (*link) { \ 479826a516SMichel Lespinasse rb_parent = *link; \ 489826a516SMichel Lespinasse parent = rb_entry(rb_parent, ITSTRUCT, ITRB); \ 499826a516SMichel Lespinasse if (parent->ITSUBTREE < last) \ 509826a516SMichel Lespinasse parent->ITSUBTREE = last; \ 519826a516SMichel Lespinasse if (start < ITSTART(parent)) \ 529826a516SMichel Lespinasse link = &parent->ITRB.rb_left; \ 53f808c13fSDavidlohr Bueso else { \ 549826a516SMichel Lespinasse link = &parent->ITRB.rb_right; \ 55f808c13fSDavidlohr Bueso leftmost = false; \ 56f808c13fSDavidlohr Bueso } \ 579826a516SMichel Lespinasse } \ 589826a516SMichel Lespinasse \ 599826a516SMichel Lespinasse node->ITSUBTREE = last; \ 609826a516SMichel Lespinasse rb_link_node(&node->ITRB, rb_parent, link); \ 61f808c13fSDavidlohr Bueso rb_insert_augmented_cached(&node->ITRB, root, \ 62f808c13fSDavidlohr Bueso leftmost, &ITPREFIX ## _augment); \ 639826a516SMichel Lespinasse } \ 649826a516SMichel Lespinasse \ 65f808c13fSDavidlohr Bueso ITSTATIC void ITPREFIX ## _remove(ITSTRUCT *node, \ 66f808c13fSDavidlohr Bueso struct rb_root_cached *root) \ 679826a516SMichel Lespinasse { \ 68f808c13fSDavidlohr Bueso rb_erase_augmented_cached(&node->ITRB, root, &ITPREFIX ## _augment); \ 699826a516SMichel Lespinasse } \ 709826a516SMichel Lespinasse \ 719826a516SMichel Lespinasse /* \ 729826a516SMichel Lespinasse * Iterate over intervals intersecting [start;last] \ 739826a516SMichel Lespinasse * \ 749826a516SMichel Lespinasse * Note that a node's interval intersects [start;last] iff: \ 759826a516SMichel Lespinasse * Cond1: ITSTART(node) <= last \ 769826a516SMichel Lespinasse * and \ 779826a516SMichel Lespinasse * Cond2: start <= ITLAST(node) \ 789826a516SMichel Lespinasse */ \ 799826a516SMichel Lespinasse \ 809826a516SMichel Lespinasse static ITSTRUCT * \ 819826a516SMichel Lespinasse ITPREFIX ## _subtree_search(ITSTRUCT *node, ITTYPE start, ITTYPE last) \ 829826a516SMichel Lespinasse { \ 839826a516SMichel Lespinasse while (true) { \ 849826a516SMichel Lespinasse /* \ 859826a516SMichel Lespinasse * Loop invariant: start <= node->ITSUBTREE \ 869826a516SMichel Lespinasse * (Cond2 is satisfied by one of the subtree nodes) \ 879826a516SMichel Lespinasse */ \ 889826a516SMichel Lespinasse if (node->ITRB.rb_left) { \ 899826a516SMichel Lespinasse ITSTRUCT *left = rb_entry(node->ITRB.rb_left, \ 909826a516SMichel Lespinasse ITSTRUCT, ITRB); \ 919826a516SMichel Lespinasse if (start <= left->ITSUBTREE) { \ 929826a516SMichel Lespinasse /* \ 939826a516SMichel Lespinasse * Some nodes in left subtree satisfy Cond2. \ 949826a516SMichel Lespinasse * Iterate to find the leftmost such node N. \ 959826a516SMichel Lespinasse * If it also satisfies Cond1, that's the \ 969826a516SMichel Lespinasse * match we are looking for. Otherwise, there \ 979826a516SMichel Lespinasse * is no matching interval as nodes to the \ 989826a516SMichel Lespinasse * right of N can't satisfy Cond1 either. \ 999826a516SMichel Lespinasse */ \ 1009826a516SMichel Lespinasse node = left; \ 1019826a516SMichel Lespinasse continue; \ 1029826a516SMichel Lespinasse } \ 1039826a516SMichel Lespinasse } \ 1049826a516SMichel Lespinasse if (ITSTART(node) <= last) { /* Cond1 */ \ 1059826a516SMichel Lespinasse if (start <= ITLAST(node)) /* Cond2 */ \ 1069826a516SMichel Lespinasse return node; /* node is leftmost match */ \ 107*19811285SWei Yang node = rb_entry(node->ITRB.rb_right, ITSTRUCT, ITRB); \ 1089826a516SMichel Lespinasse continue; \ 1099826a516SMichel Lespinasse } \ 1109826a516SMichel Lespinasse return NULL; /* No match */ \ 1119826a516SMichel Lespinasse } \ 1129826a516SMichel Lespinasse } \ 1139826a516SMichel Lespinasse \ 1149826a516SMichel Lespinasse ITSTATIC ITSTRUCT * \ 115f808c13fSDavidlohr Bueso ITPREFIX ## _iter_first(struct rb_root_cached *root, \ 116f808c13fSDavidlohr Bueso ITTYPE start, ITTYPE last) \ 1179826a516SMichel Lespinasse { \ 118f808c13fSDavidlohr Bueso ITSTRUCT *node, *leftmost; \ 1199826a516SMichel Lespinasse \ 120f808c13fSDavidlohr Bueso if (!root->rb_root.rb_node) \ 1219826a516SMichel Lespinasse return NULL; \ 122f808c13fSDavidlohr Bueso \ 123f808c13fSDavidlohr Bueso /* \ 124f808c13fSDavidlohr Bueso * Fastpath range intersection/overlap between A: [a0, a1] and \ 125f808c13fSDavidlohr Bueso * B: [b0, b1] is given by: \ 126f808c13fSDavidlohr Bueso * \ 127f808c13fSDavidlohr Bueso * a0 <= b1 && b0 <= a1 \ 128f808c13fSDavidlohr Bueso * \ 129f808c13fSDavidlohr Bueso * ... where A holds the lock range and B holds the smallest \ 130f808c13fSDavidlohr Bueso * 'start' and largest 'last' in the tree. For the later, we \ 131f808c13fSDavidlohr Bueso * rely on the root node, which by augmented interval tree \ 132f808c13fSDavidlohr Bueso * property, holds the largest value in its last-in-subtree. \ 133f808c13fSDavidlohr Bueso * This allows mitigating some of the tree walk overhead for \ 134f808c13fSDavidlohr Bueso * for non-intersecting ranges, maintained and consulted in O(1). \ 135f808c13fSDavidlohr Bueso */ \ 136f808c13fSDavidlohr Bueso node = rb_entry(root->rb_root.rb_node, ITSTRUCT, ITRB); \ 1379826a516SMichel Lespinasse if (node->ITSUBTREE < start) \ 1389826a516SMichel Lespinasse return NULL; \ 139f808c13fSDavidlohr Bueso \ 140f808c13fSDavidlohr Bueso leftmost = rb_entry(root->rb_leftmost, ITSTRUCT, ITRB); \ 141f808c13fSDavidlohr Bueso if (ITSTART(leftmost) > last) \ 142f808c13fSDavidlohr Bueso return NULL; \ 143f808c13fSDavidlohr Bueso \ 1449826a516SMichel Lespinasse return ITPREFIX ## _subtree_search(node, start, last); \ 1459826a516SMichel Lespinasse } \ 1469826a516SMichel Lespinasse \ 1479826a516SMichel Lespinasse ITSTATIC ITSTRUCT * \ 1489826a516SMichel Lespinasse ITPREFIX ## _iter_next(ITSTRUCT *node, ITTYPE start, ITTYPE last) \ 1499826a516SMichel Lespinasse { \ 1509826a516SMichel Lespinasse struct rb_node *rb = node->ITRB.rb_right, *prev; \ 1519826a516SMichel Lespinasse \ 1529826a516SMichel Lespinasse while (true) { \ 1539826a516SMichel Lespinasse /* \ 1549826a516SMichel Lespinasse * Loop invariants: \ 1559826a516SMichel Lespinasse * Cond1: ITSTART(node) <= last \ 1569826a516SMichel Lespinasse * rb == node->ITRB.rb_right \ 1579826a516SMichel Lespinasse * \ 1589826a516SMichel Lespinasse * First, search right subtree if suitable \ 1599826a516SMichel Lespinasse */ \ 1609826a516SMichel Lespinasse if (rb) { \ 1619826a516SMichel Lespinasse ITSTRUCT *right = rb_entry(rb, ITSTRUCT, ITRB); \ 1629826a516SMichel Lespinasse if (start <= right->ITSUBTREE) \ 1639826a516SMichel Lespinasse return ITPREFIX ## _subtree_search(right, \ 1649826a516SMichel Lespinasse start, last); \ 1659826a516SMichel Lespinasse } \ 1669826a516SMichel Lespinasse \ 1679826a516SMichel Lespinasse /* Move up the tree until we come from a node's left child */ \ 1689826a516SMichel Lespinasse do { \ 1699826a516SMichel Lespinasse rb = rb_parent(&node->ITRB); \ 1709826a516SMichel Lespinasse if (!rb) \ 1719826a516SMichel Lespinasse return NULL; \ 1729826a516SMichel Lespinasse prev = &node->ITRB; \ 1739826a516SMichel Lespinasse node = rb_entry(rb, ITSTRUCT, ITRB); \ 1749826a516SMichel Lespinasse rb = node->ITRB.rb_right; \ 1759826a516SMichel Lespinasse } while (prev == rb); \ 1769826a516SMichel Lespinasse \ 1779826a516SMichel Lespinasse /* Check if the node intersects [start;last] */ \ 1789826a516SMichel Lespinasse if (last < ITSTART(node)) /* !Cond1 */ \ 1799826a516SMichel Lespinasse return NULL; \ 1809826a516SMichel Lespinasse else if (start <= ITLAST(node)) /* Cond2 */ \ 1819826a516SMichel Lespinasse return node; \ 1829826a516SMichel Lespinasse } \ 1839826a516SMichel Lespinasse } 184