1*70abac43SMatthew Dillon /*
2*70abac43SMatthew Dillon * Copyright (c) 2019 Matthew Dillon <dillon@backplane.com>
3*70abac43SMatthew Dillon * All rights reserved.
4*70abac43SMatthew Dillon *
5*70abac43SMatthew Dillon * Redistribution and use in source and binary forms, with or without
6*70abac43SMatthew Dillon * modification, are permitted provided that the following conditions
7*70abac43SMatthew Dillon * are met:
8*70abac43SMatthew Dillon * 1. Redistributions of source code must retain the above copyright
9*70abac43SMatthew Dillon * notice unmodified, this list of conditions, and the following
10*70abac43SMatthew Dillon * disclaimer.
11*70abac43SMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright
12*70abac43SMatthew Dillon * notice, this list of conditions and the following disclaimer in the
13*70abac43SMatthew Dillon * documentation and/or other materials provided with the distribution.
14*70abac43SMatthew Dillon *
15*70abac43SMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16*70abac43SMatthew Dillon * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17*70abac43SMatthew Dillon * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18*70abac43SMatthew Dillon * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19*70abac43SMatthew Dillon * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20*70abac43SMatthew Dillon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21*70abac43SMatthew Dillon * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22*70abac43SMatthew Dillon * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23*70abac43SMatthew Dillon * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24*70abac43SMatthew Dillon * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*70abac43SMatthew Dillon */
26*70abac43SMatthew Dillon
27*70abac43SMatthew Dillon #include <linux/init.h>
28*70abac43SMatthew Dillon #include <linux/interval_tree.h>
29*70abac43SMatthew Dillon #include <linux/module.h>
30*70abac43SMatthew Dillon
31*70abac43SMatthew Dillon typedef struct interval_tree_node itnode_t;
32*70abac43SMatthew Dillon
33*70abac43SMatthew Dillon void
interval_tree_insert(struct interval_tree_node * node,struct rb_root * root)34*70abac43SMatthew Dillon interval_tree_insert(struct interval_tree_node *node, struct rb_root *root)
35*70abac43SMatthew Dillon {
36*70abac43SMatthew Dillon itnode_t *scan;
37*70abac43SMatthew Dillon
38*70abac43SMatthew Dillon scan = (itnode_t *)root->rb_node;
39*70abac43SMatthew Dillon if (scan) {
40*70abac43SMatthew Dillon node->next = scan->next;
41*70abac43SMatthew Dillon node->atroot = 0;
42*70abac43SMatthew Dillon scan->next = node;
43*70abac43SMatthew Dillon } else {
44*70abac43SMatthew Dillon root->rb_node = (void *)node;
45*70abac43SMatthew Dillon node->atroot = 1;
46*70abac43SMatthew Dillon node->next = node;
47*70abac43SMatthew Dillon }
48*70abac43SMatthew Dillon }
49*70abac43SMatthew Dillon
50*70abac43SMatthew Dillon void
interval_tree_remove(struct interval_tree_node * node,struct rb_root * root)51*70abac43SMatthew Dillon interval_tree_remove(struct interval_tree_node *node, struct rb_root *root)
52*70abac43SMatthew Dillon {
53*70abac43SMatthew Dillon itnode_t *scan;
54*70abac43SMatthew Dillon
55*70abac43SMatthew Dillon scan = (itnode_t *)root->rb_node;
56*70abac43SMatthew Dillon KKASSERT(scan != NULL);
57*70abac43SMatthew Dillon while (scan->next != node) {
58*70abac43SMatthew Dillon scan = scan->next;
59*70abac43SMatthew Dillon }
60*70abac43SMatthew Dillon scan->next = node->next;
61*70abac43SMatthew Dillon if (scan == node) {
62*70abac43SMatthew Dillon /*
63*70abac43SMatthew Dillon * Last element is being removed
64*70abac43SMatthew Dillon */
65*70abac43SMatthew Dillon root->rb_node = NULL;
66*70abac43SMatthew Dillon node->atroot = 0;
67*70abac43SMatthew Dillon } else if ((itnode_t *)root->rb_node == node) {
68*70abac43SMatthew Dillon /*
69*70abac43SMatthew Dillon * Root pointer is the node being removed, move the root
70*70abac43SMatthew Dillon * pointer.
71*70abac43SMatthew Dillon */
72*70abac43SMatthew Dillon node->atroot = 0;
73*70abac43SMatthew Dillon scan->atroot = 1;
74*70abac43SMatthew Dillon root->rb_node = (void *)scan;
75*70abac43SMatthew Dillon }
76*70abac43SMatthew Dillon }
77*70abac43SMatthew Dillon
78*70abac43SMatthew Dillon struct interval_tree_node *
interval_tree_iter_first(struct rb_root * root,unsigned long start,unsigned long last)79*70abac43SMatthew Dillon interval_tree_iter_first(struct rb_root *root,
80*70abac43SMatthew Dillon unsigned long start, unsigned long last)
81*70abac43SMatthew Dillon {
82*70abac43SMatthew Dillon itnode_t *scan;
83*70abac43SMatthew Dillon
84*70abac43SMatthew Dillon scan = (itnode_t *)root->rb_node;
85*70abac43SMatthew Dillon if (scan) {
86*70abac43SMatthew Dillon do {
87*70abac43SMatthew Dillon if (start <= scan->last &&
88*70abac43SMatthew Dillon last >= scan->start) {
89*70abac43SMatthew Dillon return scan;
90*70abac43SMatthew Dillon }
91*70abac43SMatthew Dillon scan = scan->next;
92*70abac43SMatthew Dillon } while (scan->atroot == 0);
93*70abac43SMatthew Dillon scan = NULL;
94*70abac43SMatthew Dillon }
95*70abac43SMatthew Dillon return scan;
96*70abac43SMatthew Dillon }
97*70abac43SMatthew Dillon
98*70abac43SMatthew Dillon struct interval_tree_node *
interval_tree_iter_next(struct interval_tree_node * node,unsigned long start,unsigned long last)99*70abac43SMatthew Dillon interval_tree_iter_next(struct interval_tree_node *node,
100*70abac43SMatthew Dillon unsigned long start, unsigned long last)
101*70abac43SMatthew Dillon {
102*70abac43SMatthew Dillon itnode_t *scan;
103*70abac43SMatthew Dillon
104*70abac43SMatthew Dillon scan = node->next;
105*70abac43SMatthew Dillon while (scan->atroot == 0) {
106*70abac43SMatthew Dillon if (start <= scan->last &&
107*70abac43SMatthew Dillon last >= scan->start) {
108*70abac43SMatthew Dillon return scan;
109*70abac43SMatthew Dillon }
110*70abac43SMatthew Dillon scan = scan->next;
111*70abac43SMatthew Dillon }
112*70abac43SMatthew Dillon return NULL;
113*70abac43SMatthew Dillon }
114