1dbc920bdSVladimir Kondratyev /*- 2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3dbc920bdSVladimir Kondratyev * 4dbc920bdSVladimir Kondratyev * Copyright (c) 2019 Mark Kettenis <kettenis@OpenBSD.org> 5dbc920bdSVladimir Kondratyev * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org> 6dbc920bdSVladimir Kondratyev * 7dbc920bdSVladimir Kondratyev * Redistribution and use in source and binary forms, with or without 8dbc920bdSVladimir Kondratyev * modification, are permitted provided that the following conditions 9dbc920bdSVladimir Kondratyev * are met: 10dbc920bdSVladimir Kondratyev * 1. Redistributions of source code must retain the above copyright 11dbc920bdSVladimir Kondratyev * notice unmodified, this list of conditions, and the following 12dbc920bdSVladimir Kondratyev * disclaimer. 13dbc920bdSVladimir Kondratyev * 2. Redistributions in binary form must reproduce the above copyright 14dbc920bdSVladimir Kondratyev * notice, this list of conditions and the following disclaimer in the 15dbc920bdSVladimir Kondratyev * documentation and/or other materials provided with the distribution. 16dbc920bdSVladimir Kondratyev * 17dbc920bdSVladimir Kondratyev * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18dbc920bdSVladimir Kondratyev * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19dbc920bdSVladimir Kondratyev * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20dbc920bdSVladimir Kondratyev * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21dbc920bdSVladimir Kondratyev * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22dbc920bdSVladimir Kondratyev * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23dbc920bdSVladimir Kondratyev * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24dbc920bdSVladimir Kondratyev * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25dbc920bdSVladimir Kondratyev * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26dbc920bdSVladimir Kondratyev * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27dbc920bdSVladimir Kondratyev */ 28dbc920bdSVladimir Kondratyev 29dbc920bdSVladimir Kondratyev #include <linux/rbtree.h> 30dbc920bdSVladimir Kondratyev 31dbc920bdSVladimir Kondratyev #define INTERVAL_TREE_DEFINE(type, field, valtype, dummy, START, LAST, \ 32dbc920bdSVladimir Kondratyev attr, name) \ 33dbc920bdSVladimir Kondratyev __IT_DEFINE_ITER_FROM(type, field, valtype, START, LAST, name) \ 34dbc920bdSVladimir Kondratyev __IT_DEFINE_ITER_FIRST(type, valtype, attr, name) \ 35dbc920bdSVladimir Kondratyev __IT_DEFINE_ITER_NEXT(type, field, valtype, attr, name) \ 36dbc920bdSVladimir Kondratyev __IT_DEFINE_INSERT(type, field, START, attr, name) \ 37dbc920bdSVladimir Kondratyev __IT_DEFINE_REMOVE(type, field, attr, name) 38dbc920bdSVladimir Kondratyev 39dbc920bdSVladimir Kondratyev #define __IT_DEFINE_ITER_FROM(type, field, valtype, START, LAST, name) \ 40dbc920bdSVladimir Kondratyev static inline type * \ 41dbc920bdSVladimir Kondratyev name##_iter_from(struct rb_node *rb, valtype start, valtype last) \ 42dbc920bdSVladimir Kondratyev { \ 43dbc920bdSVladimir Kondratyev type *node; \ 44dbc920bdSVladimir Kondratyev \ 45dbc920bdSVladimir Kondratyev while (rb != NULL) { \ 46dbc920bdSVladimir Kondratyev node = rb_entry(rb, type, field); \ 47dbc920bdSVladimir Kondratyev if (LAST(node) >= start && START(node) <= last) \ 48dbc920bdSVladimir Kondratyev return (node); \ 49dbc920bdSVladimir Kondratyev else if (START(node) > last) \ 50dbc920bdSVladimir Kondratyev break; \ 51dbc920bdSVladimir Kondratyev rb = rb_next(rb); \ 52dbc920bdSVladimir Kondratyev } \ 53dbc920bdSVladimir Kondratyev return (NULL); \ 54dbc920bdSVladimir Kondratyev } 55dbc920bdSVladimir Kondratyev 56dbc920bdSVladimir Kondratyev #define __IT_DEFINE_ITER_FIRST(type, valtype, attr, name) \ 57dbc920bdSVladimir Kondratyev attr type * \ 58dbc920bdSVladimir Kondratyev name##_iter_first(struct rb_root_cached *root, valtype start, valtype last) \ 59dbc920bdSVladimir Kondratyev { \ 60dbc920bdSVladimir Kondratyev return (name##_iter_from(rb_first_cached(root), start, last)); \ 61dbc920bdSVladimir Kondratyev } 62dbc920bdSVladimir Kondratyev 63dbc920bdSVladimir Kondratyev #define __IT_DEFINE_ITER_NEXT(type, field, valtype, attr, name) \ 64dbc920bdSVladimir Kondratyev attr type * \ 65dbc920bdSVladimir Kondratyev name##_iter_next(type *node, valtype start, valtype last) \ 66dbc920bdSVladimir Kondratyev { \ 67dbc920bdSVladimir Kondratyev return (name##_iter_from(rb_next(&node->field), start, last)); \ 68dbc920bdSVladimir Kondratyev } 69dbc920bdSVladimir Kondratyev 70dbc920bdSVladimir Kondratyev #define __IT_DEFINE_INSERT(type, field, START, attr, name) \ 71dbc920bdSVladimir Kondratyev attr void \ 72dbc920bdSVladimir Kondratyev name##_insert(type *node, struct rb_root_cached *root) \ 73dbc920bdSVladimir Kondratyev { \ 74dbc920bdSVladimir Kondratyev struct rb_node **iter = &root->rb_root.rb_node; \ 75dbc920bdSVladimir Kondratyev struct rb_node *parent = NULL; \ 76dbc920bdSVladimir Kondratyev type *iter_node; \ 77dbc920bdSVladimir Kondratyev bool min_entry = true; \ 78dbc920bdSVladimir Kondratyev \ 79dbc920bdSVladimir Kondratyev while (*iter != NULL) { \ 80dbc920bdSVladimir Kondratyev parent = *iter; \ 81dbc920bdSVladimir Kondratyev iter_node = rb_entry(parent, type, field); \ 82dbc920bdSVladimir Kondratyev if (START(node) < START(iter_node)) \ 83dbc920bdSVladimir Kondratyev iter = &parent->rb_left; \ 84dbc920bdSVladimir Kondratyev else { \ 85dbc920bdSVladimir Kondratyev iter = &parent->rb_right; \ 86dbc920bdSVladimir Kondratyev min_entry = false; \ 87dbc920bdSVladimir Kondratyev } \ 88dbc920bdSVladimir Kondratyev } \ 89dbc920bdSVladimir Kondratyev \ 90dbc920bdSVladimir Kondratyev rb_link_node(&node->field, parent, iter); \ 91dbc920bdSVladimir Kondratyev rb_insert_color_cached(&node->field, root, min_entry); \ 92dbc920bdSVladimir Kondratyev } 93dbc920bdSVladimir Kondratyev 94dbc920bdSVladimir Kondratyev #define __IT_DEFINE_REMOVE(type, field, attr, name) \ 95dbc920bdSVladimir Kondratyev attr void \ 96dbc920bdSVladimir Kondratyev name##_remove(type *node, struct rb_root_cached *root) \ 97dbc920bdSVladimir Kondratyev { \ 98dbc920bdSVladimir Kondratyev rb_erase_cached(&node->field, root); \ 99dbc920bdSVladimir Kondratyev } 100