mm: replace vma prio_tree with an interval tree
[deliverable/linux.git] / lib / interval_tree.c
index 6fd540b1e4990153981225813044a7c53deb81d7..77a793e0644b901b4db5de9bb992141eda7df7d3 100644 (file)
 #include <linux/init.h>
 #include <linux/interval_tree.h>
 
-/* Callbacks for augmented rbtree insert and remove */
-
-static inline unsigned long
-compute_subtree_last(struct interval_tree_node *node)
-{
-       unsigned long max = node->last, subtree_last;
-       if (node->rb.rb_left) {
-               subtree_last = rb_entry(node->rb.rb_left,
-                       struct interval_tree_node, rb)->__subtree_last;
-               if (max < subtree_last)
-                       max = subtree_last;
-       }
-       if (node->rb.rb_right) {
-               subtree_last = rb_entry(node->rb.rb_right,
-                       struct interval_tree_node, rb)->__subtree_last;
-               if (max < subtree_last)
-                       max = subtree_last;
-       }
-       return max;
-}
-
-RB_DECLARE_CALLBACKS(static, augment_callbacks, struct interval_tree_node, rb,
-                    unsigned long, __subtree_last, compute_subtree_last)
-
-/* Insert / remove interval nodes from the tree */
-
-void interval_tree_insert(struct interval_tree_node *node,
-                         struct rb_root *root)
-{
-       struct rb_node **link = &root->rb_node, *rb_parent = NULL;
-       unsigned long start = node->start, last = node->last;
-       struct interval_tree_node *parent;
-
-       while (*link) {
-               rb_parent = *link;
-               parent = rb_entry(rb_parent, struct interval_tree_node, rb);
-               if (parent->__subtree_last < last)
-                       parent->__subtree_last = last;
-               if (start < parent->start)
-                       link = &parent->rb.rb_left;
-               else
-                       link = &parent->rb.rb_right;
-       }
-
-       node->__subtree_last = last;
-       rb_link_node(&node->rb, rb_parent, link);
-       rb_insert_augmented(&node->rb, root, &augment_callbacks);
-}
-
-void interval_tree_remove(struct interval_tree_node *node,
-                         struct rb_root *root)
-{
-       rb_erase_augmented(&node->rb, root, &augment_callbacks);
-}
-
-/*
- * Iterate over intervals intersecting [start;last]
- *
- * Note that a node's interval intersects [start;last] iff:
- *   Cond1: node->start <= last
- * and
- *   Cond2: start <= node->last
- */
-
-static struct interval_tree_node *
-subtree_search(struct interval_tree_node *node,
-              unsigned long start, unsigned long last)
-{
-       while (true) {
-               /*
-                * Loop invariant: start <= node->__subtree_last
-                * (Cond2 is satisfied by one of the subtree nodes)
-                */
-               if (node->rb.rb_left) {
-                       struct interval_tree_node *left =
-                               rb_entry(node->rb.rb_left,
-                                        struct interval_tree_node, rb);
-                       if (start <= left->__subtree_last) {
-                               /*
-                                * Some nodes in left subtree satisfy Cond2.
-                                * Iterate to find the leftmost such node N.
-                                * If it also satisfies Cond1, that's the match
-                                * we are looking for. Otherwise, there is no
-                                * matching interval as nodes to the right of N
-                                * can't satisfy Cond1 either.
-                                */
-                               node = left;
-                               continue;
-                       }
-               }
-               if (node->start <= last) {              /* Cond1 */
-                       if (start <= node->last)        /* Cond2 */
-                               return node;    /* node is leftmost match */
-                       if (node->rb.rb_right) {
-                               node = rb_entry(node->rb.rb_right,
-                                       struct interval_tree_node, rb);
-                               if (start <= node->__subtree_last)
-                                       continue;
-                       }
-               }
-               return NULL;    /* No match */
-       }
-}
-
-struct interval_tree_node *
-interval_tree_iter_first(struct rb_root *root,
-                        unsigned long start, unsigned long last)
-{
-       struct interval_tree_node *node;
-
-       if (!root->rb_node)
-               return NULL;
-       node = rb_entry(root->rb_node, struct interval_tree_node, rb);
-       if (node->__subtree_last < start)
-               return NULL;
-       return subtree_search(node, start, last);
-}
-
-struct interval_tree_node *
-interval_tree_iter_next(struct interval_tree_node *node,
-                       unsigned long start, unsigned long last)
-{
-       struct rb_node *rb = node->rb.rb_right, *prev;
-
-       while (true) {
-               /*
-                * Loop invariants:
-                *   Cond1: node->start <= last
-                *   rb == node->rb.rb_right
-                *
-                * First, search right subtree if suitable
-                */
-               if (rb) {
-                       struct interval_tree_node *right =
-                               rb_entry(rb, struct interval_tree_node, rb);
-                       if (start <= right->__subtree_last)
-                               return subtree_search(right, start, last);
-               }
-
-               /* Move up the tree until we come from a node's left child */
-               do {
-                       rb = rb_parent(&node->rb);
-                       if (!rb)
-                               return NULL;
-                       prev = &node->rb;
-                       node = rb_entry(rb, struct interval_tree_node, rb);
-                       rb = node->rb.rb_right;
-               } while (prev == rb);
-
-               /* Check if the node intersects [start;last] */
-               if (last < node->start)         /* !Cond1 */
-                       return NULL;
-               else if (start <= node->last)   /* Cond2 */
-                       return node;
-       }
-}
+#define ITSTRUCT   struct interval_tree_node
+#define ITRB       rb
+#define ITTYPE     unsigned long
+#define ITSUBTREE  __subtree_last
+#define ITSTART(n) ((n)->start)
+#define ITLAST(n)  ((n)->last)
+#define ITSTATIC
+#define ITPREFIX   interval_tree
+
+#include <linux/interval_tree_tmpl.h>
This page took 0.028376 seconds and 5 git commands to generate.