1 1.14 riastrad /* $NetBSD: interval_tree.h,v 1.14 2023/05/01 09:41:55 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad /*- 4 1.1 riastrad * Copyright (c) 2018 The NetBSD Foundation, Inc. 5 1.1 riastrad * All rights reserved. 6 1.1 riastrad * 7 1.1 riastrad * This code is derived from software contributed to The NetBSD Foundation 8 1.1 riastrad * by Taylor R. Campbell. 9 1.1 riastrad * 10 1.1 riastrad * Redistribution and use in source and binary forms, with or without 11 1.1 riastrad * modification, are permitted provided that the following conditions 12 1.1 riastrad * are met: 13 1.1 riastrad * 1. Redistributions of source code must retain the above copyright 14 1.1 riastrad * notice, this list of conditions and the following disclaimer. 15 1.1 riastrad * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 riastrad * notice, this list of conditions and the following disclaimer in the 17 1.1 riastrad * documentation and/or other materials provided with the distribution. 18 1.1 riastrad * 19 1.1 riastrad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 riastrad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 riastrad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 riastrad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 riastrad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 riastrad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 riastrad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 riastrad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 riastrad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 riastrad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 riastrad * POSSIBILITY OF SUCH DAMAGE. 30 1.1 riastrad */ 31 1.1 riastrad 32 1.12 riastrad /* 33 1.12 riastrad * XXX WARNING: This does not actually implement interval trees -- it 34 1.12 riastrad * only implements trees of intervals. In particular, it does not 35 1.12 riastrad * support finding all intervals that contain a given point, or that 36 1.12 riastrad * intersect with a given interval. Another way to look at it is that 37 1.12 riastrad * this is an interval tree restricted to nonoverlapping intervals. 38 1.12 riastrad */ 39 1.12 riastrad 40 1.1 riastrad #ifndef _LINUX_INTERVAL_TREE_H_ 41 1.1 riastrad #define _LINUX_INTERVAL_TREE_H_ 42 1.1 riastrad 43 1.9 riastrad #include <linux/rbtree.h> 44 1.6 riastrad 45 1.1 riastrad struct interval_tree_node { 46 1.13 riastrad struct rb_node rb; 47 1.1 riastrad unsigned long start; /* inclusive */ 48 1.1 riastrad unsigned long last; /* inclusive */ 49 1.1 riastrad }; 50 1.1 riastrad 51 1.1 riastrad static inline int 52 1.1 riastrad interval_tree_compare_nodes(void *cookie, const void *va, const void *vb) 53 1.1 riastrad { 54 1.1 riastrad const struct interval_tree_node *na = va; 55 1.1 riastrad const struct interval_tree_node *nb = vb; 56 1.1 riastrad 57 1.1 riastrad if (na->start < nb->start) 58 1.1 riastrad return -1; 59 1.1 riastrad if (na->start > nb->start) 60 1.1 riastrad return +1; 61 1.1 riastrad if (na->last < nb->last) 62 1.1 riastrad return -1; 63 1.1 riastrad if (na->last > nb->last) 64 1.1 riastrad return +1; 65 1.1 riastrad return 0; 66 1.1 riastrad } 67 1.1 riastrad 68 1.1 riastrad static inline int 69 1.1 riastrad interval_tree_compare_key(void *cookie, const void *vn, const void *vk) 70 1.1 riastrad { 71 1.2 riastrad const struct interval_tree_node *n = vn; 72 1.1 riastrad const unsigned long *k = vk; 73 1.1 riastrad 74 1.5 riastrad if (n->start < *k) 75 1.1 riastrad return -1; 76 1.5 riastrad if (*k < n->start) 77 1.1 riastrad return +1; 78 1.1 riastrad return 0; 79 1.1 riastrad } 80 1.1 riastrad 81 1.2 riastrad static const rb_tree_ops_t interval_tree_ops = { 82 1.3 riastrad .rbto_compare_nodes = interval_tree_compare_nodes, 83 1.3 riastrad .rbto_compare_key = interval_tree_compare_key, 84 1.13 riastrad .rbto_node_offset = offsetof(struct interval_tree_node, rb), 85 1.1 riastrad }; 86 1.1 riastrad 87 1.1 riastrad static inline void 88 1.11 riastrad interval_tree_init(struct rb_root_cached *root) 89 1.6 riastrad { 90 1.6 riastrad 91 1.11 riastrad rb_tree_init(&root->rb_root.rbr_tree, &interval_tree_ops); 92 1.6 riastrad } 93 1.6 riastrad 94 1.6 riastrad static inline void 95 1.11 riastrad interval_tree_insert(struct interval_tree_node *node, 96 1.11 riastrad struct rb_root_cached *root) 97 1.1 riastrad { 98 1.1 riastrad struct interval_tree_node *collision __diagused; 99 1.1 riastrad 100 1.11 riastrad collision = rb_tree_insert_node(&root->rb_root.rbr_tree, node); 101 1.1 riastrad KASSERT(collision == node); 102 1.1 riastrad } 103 1.1 riastrad 104 1.1 riastrad static inline void 105 1.11 riastrad interval_tree_remove(struct interval_tree_node *node, 106 1.11 riastrad struct rb_root_cached *root) 107 1.1 riastrad { 108 1.1 riastrad 109 1.11 riastrad rb_tree_remove_node(&root->rb_root.rbr_tree, node); 110 1.1 riastrad } 111 1.1 riastrad 112 1.2 riastrad static inline struct interval_tree_node * 113 1.11 riastrad interval_tree_iter_first(struct rb_root_cached *root, unsigned long start, 114 1.1 riastrad unsigned long last) 115 1.1 riastrad { 116 1.2 riastrad struct interval_tree_node *node; 117 1.1 riastrad 118 1.11 riastrad node = rb_tree_find_node_geq(&root->rb_root.rbr_tree, &start); 119 1.1 riastrad if (node == NULL) 120 1.1 riastrad return NULL; 121 1.1 riastrad if (last < node->start) 122 1.1 riastrad return NULL; 123 1.14 riastrad KASSERT(node->start <= last); 124 1.14 riastrad KASSERT(node->last >= start); 125 1.1 riastrad 126 1.1 riastrad return node; 127 1.1 riastrad } 128 1.1 riastrad 129 1.1 riastrad /* 130 1.1 riastrad * XXX Linux's interval_tree_iter_next doesn't take the root as an 131 1.1 riastrad * argument, which makes this difficult. So we'll just patch those 132 1.1 riastrad * uses. 133 1.1 riastrad */ 134 1.2 riastrad static inline struct interval_tree_node * 135 1.11 riastrad interval_tree_iter_next(struct rb_root_cached *root, 136 1.11 riastrad struct interval_tree_node *node, unsigned long start, unsigned long last) 137 1.1 riastrad { 138 1.2 riastrad struct interval_tree_node *next; 139 1.1 riastrad 140 1.1 riastrad KASSERT(node != NULL); 141 1.11 riastrad next = rb_tree_iterate(&root->rb_root.rbr_tree, node, RB_DIR_RIGHT); 142 1.1 riastrad if (next == NULL) 143 1.1 riastrad return NULL; 144 1.8 tnn if (last < next->start) 145 1.1 riastrad return NULL; 146 1.14 riastrad KASSERT(next->start <= last); 147 1.14 riastrad KASSERT(next->last >= start); 148 1.7 riastrad 149 1.7 riastrad return next; 150 1.1 riastrad } 151 1.1 riastrad 152 1.1 riastrad #endif /* _LINUX_INTERVAL_TREE_H_ */ 153