Commit 7ba890bf2f2b92831420243c058951aa831119fd

Authored by Kyungmin Park
Committed by Wolfgang Denk
1 parent fbd85ad65d

Add Red Black Tree support

Now it's used at UBI module. Of course other modules can use it.
If you want to use it, please define CONFIG_RBTREE

Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>

Showing 3 changed files with 551 additions and 0 deletions Side-by-side Diff

include/linux/rbtree.h
  1 +/*
  2 + Red Black Trees
  3 + (C) 1999 Andrea Arcangeli <andrea@suse.de>
  4 +
  5 + This program is free software; you can redistribute it and/or modify
  6 + it under the terms of the GNU General Public License as published by
  7 + the Free Software Foundation; either version 2 of the License, or
  8 + (at your option) any later version.
  9 +
  10 + This program is distributed in the hope that it will be useful,
  11 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13 + GNU General Public License for more details.
  14 +
  15 + You should have received a copy of the GNU General Public License
  16 + along with this program; if not, write to the Free Software
  17 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18 +
  19 + linux/include/linux/rbtree.h
  20 +
  21 + To use rbtrees you'll have to implement your own insert and search cores.
  22 + This will avoid us to use callbacks and to drop drammatically performances.
  23 + I know it's not the cleaner way, but in C (not in C++) to get
  24 + performances and genericity...
  25 +
  26 + Some example of insert and search follows here. The search is a plain
  27 + normal search over an ordered tree. The insert instead must be implemented
  28 + int two steps: as first thing the code must insert the element in
  29 + order as a red leaf in the tree, then the support library function
  30 + rb_insert_color() must be called. Such function will do the
  31 + not trivial work to rebalance the rbtree if necessary.
  32 +
  33 +-----------------------------------------------------------------------
  34 +static inline struct page * rb_search_page_cache(struct inode * inode,
  35 + unsigned long offset)
  36 +{
  37 + struct rb_node * n = inode->i_rb_page_cache.rb_node;
  38 + struct page * page;
  39 +
  40 + while (n)
  41 + {
  42 + page = rb_entry(n, struct page, rb_page_cache);
  43 +
  44 + if (offset < page->offset)
  45 + n = n->rb_left;
  46 + else if (offset > page->offset)
  47 + n = n->rb_right;
  48 + else
  49 + return page;
  50 + }
  51 + return NULL;
  52 +}
  53 +
  54 +static inline struct page * __rb_insert_page_cache(struct inode * inode,
  55 + unsigned long offset,
  56 + struct rb_node * node)
  57 +{
  58 + struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
  59 + struct rb_node * parent = NULL;
  60 + struct page * page;
  61 +
  62 + while (*p)
  63 + {
  64 + parent = *p;
  65 + page = rb_entry(parent, struct page, rb_page_cache);
  66 +
  67 + if (offset < page->offset)
  68 + p = &(*p)->rb_left;
  69 + else if (offset > page->offset)
  70 + p = &(*p)->rb_right;
  71 + else
  72 + return page;
  73 + }
  74 +
  75 + rb_link_node(node, parent, p);
  76 +
  77 + return NULL;
  78 +}
  79 +
  80 +static inline struct page * rb_insert_page_cache(struct inode * inode,
  81 + unsigned long offset,
  82 + struct rb_node * node)
  83 +{
  84 + struct page * ret;
  85 + if ((ret = __rb_insert_page_cache(inode, offset, node)))
  86 + goto out;
  87 + rb_insert_color(node, &inode->i_rb_page_cache);
  88 + out:
  89 + return ret;
  90 +}
  91 +-----------------------------------------------------------------------
  92 +*/
  93 +
  94 +#ifndef _LINUX_RBTREE_H
  95 +#define _LINUX_RBTREE_H
  96 +
  97 +#include <linux/stddef.h>
  98 +
  99 +struct rb_node
  100 +{
  101 + unsigned long rb_parent_color;
  102 +#define RB_RED 0
  103 +#define RB_BLACK 1
  104 + struct rb_node *rb_right;
  105 + struct rb_node *rb_left;
  106 +} __attribute__((aligned(sizeof(long))));
  107 + /* The alignment might seem pointless, but allegedly CRIS needs it */
  108 +
  109 +struct rb_root
  110 +{
  111 + struct rb_node *rb_node;
  112 +};
  113 +
  114 +
  115 +#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
  116 +#define rb_color(r) ((r)->rb_parent_color & 1)
  117 +#define rb_is_red(r) (!rb_color(r))
  118 +#define rb_is_black(r) rb_color(r)
  119 +#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
  120 +#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
  121 +
  122 +static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
  123 +{
  124 + rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
  125 +}
  126 +static inline void rb_set_color(struct rb_node *rb, int color)
  127 +{
  128 + rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
  129 +}
  130 +
  131 +#define RB_ROOT (struct rb_root) { NULL, }
  132 +#define rb_entry(ptr, type, member) container_of(ptr, type, member)
  133 +
  134 +#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
  135 +#define RB_EMPTY_NODE(node) (rb_parent(node) == node)
  136 +#define RB_CLEAR_NODE(node) (rb_set_parent(node, node))
  137 +
  138 +extern void rb_insert_color(struct rb_node *, struct rb_root *);
  139 +extern void rb_erase(struct rb_node *, struct rb_root *);
  140 +
  141 +/* Find logical next and previous nodes in a tree */
  142 +extern struct rb_node *rb_next(struct rb_node *);
  143 +extern struct rb_node *rb_prev(struct rb_node *);
  144 +extern struct rb_node *rb_first(struct rb_root *);
  145 +extern struct rb_node *rb_last(struct rb_root *);
  146 +
  147 +/* Fast replacement of a single node without remove/rebalance/add/rebalance */
  148 +extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
  149 + struct rb_root *root);
  150 +
  151 +static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
  152 + struct rb_node ** rb_link)
  153 +{
  154 + node->rb_parent_color = (unsigned long )parent;
  155 + node->rb_left = node->rb_right = NULL;
  156 +
  157 + *rb_link = node;
  158 +}
  159 +
  160 +#endif /* _LINUX_RBTREE_H */
lib_generic/Makefile
... ... @@ -45,6 +45,7 @@
45 45 COBJS-y += strmhz.o
46 46 COBJS-y += vsprintf.o
47 47 COBJS-y += zlib.o
  48 +COBJS-$(CONFIG_RBTREE) += rbtree.o
48 49  
49 50 COBJS := $(COBJS-y)
50 51 SRCS := $(COBJS:.o=.c)
lib_generic/rbtree.c
  1 +/*
  2 + Red Black Trees
  3 + (C) 1999 Andrea Arcangeli <andrea@suse.de>
  4 + (C) 2002 David Woodhouse <dwmw2@infradead.org>
  5 +
  6 + This program is free software; you can redistribute it and/or modify
  7 + it under the terms of the GNU General Public License as published by
  8 + the Free Software Foundation; either version 2 of the License, or
  9 + (at your option) any later version.
  10 +
  11 + This program is distributed in the hope that it will be useful,
  12 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + GNU General Public License for more details.
  15 +
  16 + You should have received a copy of the GNU General Public License
  17 + along with this program; if not, write to the Free Software
  18 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 +
  20 + linux/lib/rbtree.c
  21 +*/
  22 +
  23 +#include <ubi_uboot.h>
  24 +#include <linux/rbtree.h>
  25 +
  26 +static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
  27 +{
  28 + struct rb_node *right = node->rb_right;
  29 + struct rb_node *parent = rb_parent(node);
  30 +
  31 + if ((node->rb_right = right->rb_left))
  32 + rb_set_parent(right->rb_left, node);
  33 + right->rb_left = node;
  34 +
  35 + rb_set_parent(right, parent);
  36 +
  37 + if (parent)
  38 + {
  39 + if (node == parent->rb_left)
  40 + parent->rb_left = right;
  41 + else
  42 + parent->rb_right = right;
  43 + }
  44 + else
  45 + root->rb_node = right;
  46 + rb_set_parent(node, right);
  47 +}
  48 +
  49 +static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
  50 +{
  51 + struct rb_node *left = node->rb_left;
  52 + struct rb_node *parent = rb_parent(node);
  53 +
  54 + if ((node->rb_left = left->rb_right))
  55 + rb_set_parent(left->rb_right, node);
  56 + left->rb_right = node;
  57 +
  58 + rb_set_parent(left, parent);
  59 +
  60 + if (parent)
  61 + {
  62 + if (node == parent->rb_right)
  63 + parent->rb_right = left;
  64 + else
  65 + parent->rb_left = left;
  66 + }
  67 + else
  68 + root->rb_node = left;
  69 + rb_set_parent(node, left);
  70 +}
  71 +
  72 +void rb_insert_color(struct rb_node *node, struct rb_root *root)
  73 +{
  74 + struct rb_node *parent, *gparent;
  75 +
  76 + while ((parent = rb_parent(node)) && rb_is_red(parent))
  77 + {
  78 + gparent = rb_parent(parent);
  79 +
  80 + if (parent == gparent->rb_left)
  81 + {
  82 + {
  83 + register struct rb_node *uncle = gparent->rb_right;
  84 + if (uncle && rb_is_red(uncle))
  85 + {
  86 + rb_set_black(uncle);
  87 + rb_set_black(parent);
  88 + rb_set_red(gparent);
  89 + node = gparent;
  90 + continue;
  91 + }
  92 + }
  93 +
  94 + if (parent->rb_right == node)
  95 + {
  96 + register struct rb_node *tmp;
  97 + __rb_rotate_left(parent, root);
  98 + tmp = parent;
  99 + parent = node;
  100 + node = tmp;
  101 + }
  102 +
  103 + rb_set_black(parent);
  104 + rb_set_red(gparent);
  105 + __rb_rotate_right(gparent, root);
  106 + } else {
  107 + {
  108 + register struct rb_node *uncle = gparent->rb_left;
  109 + if (uncle && rb_is_red(uncle))
  110 + {
  111 + rb_set_black(uncle);
  112 + rb_set_black(parent);
  113 + rb_set_red(gparent);
  114 + node = gparent;
  115 + continue;
  116 + }
  117 + }
  118 +
  119 + if (parent->rb_left == node)
  120 + {
  121 + register struct rb_node *tmp;
  122 + __rb_rotate_right(parent, root);
  123 + tmp = parent;
  124 + parent = node;
  125 + node = tmp;
  126 + }
  127 +
  128 + rb_set_black(parent);
  129 + rb_set_red(gparent);
  130 + __rb_rotate_left(gparent, root);
  131 + }
  132 + }
  133 +
  134 + rb_set_black(root->rb_node);
  135 +}
  136 +
  137 +static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
  138 + struct rb_root *root)
  139 +{
  140 + struct rb_node *other;
  141 +
  142 + while ((!node || rb_is_black(node)) && node != root->rb_node)
  143 + {
  144 + if (parent->rb_left == node)
  145 + {
  146 + other = parent->rb_right;
  147 + if (rb_is_red(other))
  148 + {
  149 + rb_set_black(other);
  150 + rb_set_red(parent);
  151 + __rb_rotate_left(parent, root);
  152 + other = parent->rb_right;
  153 + }
  154 + if ((!other->rb_left || rb_is_black(other->rb_left)) &&
  155 + (!other->rb_right || rb_is_black(other->rb_right)))
  156 + {
  157 + rb_set_red(other);
  158 + node = parent;
  159 + parent = rb_parent(node);
  160 + }
  161 + else
  162 + {
  163 + if (!other->rb_right || rb_is_black(other->rb_right))
  164 + {
  165 + struct rb_node *o_left;
  166 + if ((o_left = other->rb_left))
  167 + rb_set_black(o_left);
  168 + rb_set_red(other);
  169 + __rb_rotate_right(other, root);
  170 + other = parent->rb_right;
  171 + }
  172 + rb_set_color(other, rb_color(parent));
  173 + rb_set_black(parent);
  174 + if (other->rb_right)
  175 + rb_set_black(other->rb_right);
  176 + __rb_rotate_left(parent, root);
  177 + node = root->rb_node;
  178 + break;
  179 + }
  180 + }
  181 + else
  182 + {
  183 + other = parent->rb_left;
  184 + if (rb_is_red(other))
  185 + {
  186 + rb_set_black(other);
  187 + rb_set_red(parent);
  188 + __rb_rotate_right(parent, root);
  189 + other = parent->rb_left;
  190 + }
  191 + if ((!other->rb_left || rb_is_black(other->rb_left)) &&
  192 + (!other->rb_right || rb_is_black(other->rb_right)))
  193 + {
  194 + rb_set_red(other);
  195 + node = parent;
  196 + parent = rb_parent(node);
  197 + }
  198 + else
  199 + {
  200 + if (!other->rb_left || rb_is_black(other->rb_left))
  201 + {
  202 + register struct rb_node *o_right;
  203 + if ((o_right = other->rb_right))
  204 + rb_set_black(o_right);
  205 + rb_set_red(other);
  206 + __rb_rotate_left(other, root);
  207 + other = parent->rb_left;
  208 + }
  209 + rb_set_color(other, rb_color(parent));
  210 + rb_set_black(parent);
  211 + if (other->rb_left)
  212 + rb_set_black(other->rb_left);
  213 + __rb_rotate_right(parent, root);
  214 + node = root->rb_node;
  215 + break;
  216 + }
  217 + }
  218 + }
  219 + if (node)
  220 + rb_set_black(node);
  221 +}
  222 +
  223 +void rb_erase(struct rb_node *node, struct rb_root *root)
  224 +{
  225 + struct rb_node *child, *parent;
  226 + int color;
  227 +
  228 + if (!node->rb_left)
  229 + child = node->rb_right;
  230 + else if (!node->rb_right)
  231 + child = node->rb_left;
  232 + else
  233 + {
  234 + struct rb_node *old = node, *left;
  235 +
  236 + node = node->rb_right;
  237 + while ((left = node->rb_left) != NULL)
  238 + node = left;
  239 + child = node->rb_right;
  240 + parent = rb_parent(node);
  241 + color = rb_color(node);
  242 +
  243 + if (child)
  244 + rb_set_parent(child, parent);
  245 + if (parent == old) {
  246 + parent->rb_right = child;
  247 + parent = node;
  248 + } else
  249 + parent->rb_left = child;
  250 +
  251 + node->rb_parent_color = old->rb_parent_color;
  252 + node->rb_right = old->rb_right;
  253 + node->rb_left = old->rb_left;
  254 +
  255 + if (rb_parent(old))
  256 + {
  257 + if (rb_parent(old)->rb_left == old)
  258 + rb_parent(old)->rb_left = node;
  259 + else
  260 + rb_parent(old)->rb_right = node;
  261 + } else
  262 + root->rb_node = node;
  263 +
  264 + rb_set_parent(old->rb_left, node);
  265 + if (old->rb_right)
  266 + rb_set_parent(old->rb_right, node);
  267 + goto color;
  268 + }
  269 +
  270 + parent = rb_parent(node);
  271 + color = rb_color(node);
  272 +
  273 + if (child)
  274 + rb_set_parent(child, parent);
  275 + if (parent)
  276 + {
  277 + if (parent->rb_left == node)
  278 + parent->rb_left = child;
  279 + else
  280 + parent->rb_right = child;
  281 + }
  282 + else
  283 + root->rb_node = child;
  284 +
  285 + color:
  286 + if (color == RB_BLACK)
  287 + __rb_erase_color(child, parent, root);
  288 +}
  289 +
  290 +/*
  291 + * This function returns the first node (in sort order) of the tree.
  292 + */
  293 +struct rb_node *rb_first(struct rb_root *root)
  294 +{
  295 + struct rb_node *n;
  296 +
  297 + n = root->rb_node;
  298 + if (!n)
  299 + return NULL;
  300 + while (n->rb_left)
  301 + n = n->rb_left;
  302 + return n;
  303 +}
  304 +
  305 +struct rb_node *rb_last(struct rb_root *root)
  306 +{
  307 + struct rb_node *n;
  308 +
  309 + n = root->rb_node;
  310 + if (!n)
  311 + return NULL;
  312 + while (n->rb_right)
  313 + n = n->rb_right;
  314 + return n;
  315 +}
  316 +
  317 +struct rb_node *rb_next(struct rb_node *node)
  318 +{
  319 + struct rb_node *parent;
  320 +
  321 + if (rb_parent(node) == node)
  322 + return NULL;
  323 +
  324 + /* If we have a right-hand child, go down and then left as far
  325 + as we can. */
  326 + if (node->rb_right) {
  327 + node = node->rb_right;
  328 + while (node->rb_left)
  329 + node=node->rb_left;
  330 + return node;
  331 + }
  332 +
  333 + /* No right-hand children. Everything down and left is
  334 + smaller than us, so any 'next' node must be in the general
  335 + direction of our parent. Go up the tree; any time the
  336 + ancestor is a right-hand child of its parent, keep going
  337 + up. First time it's a left-hand child of its parent, said
  338 + parent is our 'next' node. */
  339 + while ((parent = rb_parent(node)) && node == parent->rb_right)
  340 + node = parent;
  341 +
  342 + return parent;
  343 +}
  344 +
  345 +struct rb_node *rb_prev(struct rb_node *node)
  346 +{
  347 + struct rb_node *parent;
  348 +
  349 + if (rb_parent(node) == node)
  350 + return NULL;
  351 +
  352 + /* If we have a left-hand child, go down and then right as far
  353 + as we can. */
  354 + if (node->rb_left) {
  355 + node = node->rb_left;
  356 + while (node->rb_right)
  357 + node=node->rb_right;
  358 + return node;
  359 + }
  360 +
  361 + /* No left-hand children. Go up till we find an ancestor which
  362 + is a right-hand child of its parent */
  363 + while ((parent = rb_parent(node)) && node == parent->rb_left)
  364 + node = parent;
  365 +
  366 + return parent;
  367 +}
  368 +
  369 +void rb_replace_node(struct rb_node *victim, struct rb_node *new,
  370 + struct rb_root *root)
  371 +{
  372 + struct rb_node *parent = rb_parent(victim);
  373 +
  374 + /* Set the surrounding nodes to point to the replacement */
  375 + if (parent) {
  376 + if (victim == parent->rb_left)
  377 + parent->rb_left = new;
  378 + else
  379 + parent->rb_right = new;
  380 + } else {
  381 + root->rb_node = new;
  382 + }
  383 + if (victim->rb_left)
  384 + rb_set_parent(victim->rb_left, new);
  385 + if (victim->rb_right)
  386 + rb_set_parent(victim->rb_right, new);
  387 +
  388 + /* Copy the pointers/colour from the victim to the replacement */
  389 + *new = *victim;
  390 +}