1*7ba890bfSKyungmin Park /* 2*7ba890bfSKyungmin Park Red Black Trees 3*7ba890bfSKyungmin Park (C) 1999 Andrea Arcangeli <andrea@suse.de> 4*7ba890bfSKyungmin Park 5*7ba890bfSKyungmin Park This program is free software; you can redistribute it and/or modify 6*7ba890bfSKyungmin Park it under the terms of the GNU General Public License as published by 7*7ba890bfSKyungmin Park the Free Software Foundation; either version 2 of the License, or 8*7ba890bfSKyungmin Park (at your option) any later version. 9*7ba890bfSKyungmin Park 10*7ba890bfSKyungmin Park This program is distributed in the hope that it will be useful, 11*7ba890bfSKyungmin Park but WITHOUT ANY WARRANTY; without even the implied warranty of 12*7ba890bfSKyungmin Park MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13*7ba890bfSKyungmin Park GNU General Public License for more details. 14*7ba890bfSKyungmin Park 15*7ba890bfSKyungmin Park You should have received a copy of the GNU General Public License 16*7ba890bfSKyungmin Park along with this program; if not, write to the Free Software 17*7ba890bfSKyungmin Park Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18*7ba890bfSKyungmin Park 19*7ba890bfSKyungmin Park linux/include/linux/rbtree.h 20*7ba890bfSKyungmin Park 21*7ba890bfSKyungmin Park To use rbtrees you'll have to implement your own insert and search cores. 22*7ba890bfSKyungmin Park This will avoid us to use callbacks and to drop drammatically performances. 23*7ba890bfSKyungmin Park I know it's not the cleaner way, but in C (not in C++) to get 24*7ba890bfSKyungmin Park performances and genericity... 25*7ba890bfSKyungmin Park 26*7ba890bfSKyungmin Park Some example of insert and search follows here. The search is a plain 27*7ba890bfSKyungmin Park normal search over an ordered tree. The insert instead must be implemented 28*7ba890bfSKyungmin Park int two steps: as first thing the code must insert the element in 29*7ba890bfSKyungmin Park order as a red leaf in the tree, then the support library function 30*7ba890bfSKyungmin Park rb_insert_color() must be called. Such function will do the 31*7ba890bfSKyungmin Park not trivial work to rebalance the rbtree if necessary. 32*7ba890bfSKyungmin Park 33*7ba890bfSKyungmin Park ----------------------------------------------------------------------- 34*7ba890bfSKyungmin Park static inline struct page * rb_search_page_cache(struct inode * inode, 35*7ba890bfSKyungmin Park unsigned long offset) 36*7ba890bfSKyungmin Park { 37*7ba890bfSKyungmin Park struct rb_node * n = inode->i_rb_page_cache.rb_node; 38*7ba890bfSKyungmin Park struct page * page; 39*7ba890bfSKyungmin Park 40*7ba890bfSKyungmin Park while (n) 41*7ba890bfSKyungmin Park { 42*7ba890bfSKyungmin Park page = rb_entry(n, struct page, rb_page_cache); 43*7ba890bfSKyungmin Park 44*7ba890bfSKyungmin Park if (offset < page->offset) 45*7ba890bfSKyungmin Park n = n->rb_left; 46*7ba890bfSKyungmin Park else if (offset > page->offset) 47*7ba890bfSKyungmin Park n = n->rb_right; 48*7ba890bfSKyungmin Park else 49*7ba890bfSKyungmin Park return page; 50*7ba890bfSKyungmin Park } 51*7ba890bfSKyungmin Park return NULL; 52*7ba890bfSKyungmin Park } 53*7ba890bfSKyungmin Park 54*7ba890bfSKyungmin Park static inline struct page * __rb_insert_page_cache(struct inode * inode, 55*7ba890bfSKyungmin Park unsigned long offset, 56*7ba890bfSKyungmin Park struct rb_node * node) 57*7ba890bfSKyungmin Park { 58*7ba890bfSKyungmin Park struct rb_node ** p = &inode->i_rb_page_cache.rb_node; 59*7ba890bfSKyungmin Park struct rb_node * parent = NULL; 60*7ba890bfSKyungmin Park struct page * page; 61*7ba890bfSKyungmin Park 62*7ba890bfSKyungmin Park while (*p) 63*7ba890bfSKyungmin Park { 64*7ba890bfSKyungmin Park parent = *p; 65*7ba890bfSKyungmin Park page = rb_entry(parent, struct page, rb_page_cache); 66*7ba890bfSKyungmin Park 67*7ba890bfSKyungmin Park if (offset < page->offset) 68*7ba890bfSKyungmin Park p = &(*p)->rb_left; 69*7ba890bfSKyungmin Park else if (offset > page->offset) 70*7ba890bfSKyungmin Park p = &(*p)->rb_right; 71*7ba890bfSKyungmin Park else 72*7ba890bfSKyungmin Park return page; 73*7ba890bfSKyungmin Park } 74*7ba890bfSKyungmin Park 75*7ba890bfSKyungmin Park rb_link_node(node, parent, p); 76*7ba890bfSKyungmin Park 77*7ba890bfSKyungmin Park return NULL; 78*7ba890bfSKyungmin Park } 79*7ba890bfSKyungmin Park 80*7ba890bfSKyungmin Park static inline struct page * rb_insert_page_cache(struct inode * inode, 81*7ba890bfSKyungmin Park unsigned long offset, 82*7ba890bfSKyungmin Park struct rb_node * node) 83*7ba890bfSKyungmin Park { 84*7ba890bfSKyungmin Park struct page * ret; 85*7ba890bfSKyungmin Park if ((ret = __rb_insert_page_cache(inode, offset, node))) 86*7ba890bfSKyungmin Park goto out; 87*7ba890bfSKyungmin Park rb_insert_color(node, &inode->i_rb_page_cache); 88*7ba890bfSKyungmin Park out: 89*7ba890bfSKyungmin Park return ret; 90*7ba890bfSKyungmin Park } 91*7ba890bfSKyungmin Park ----------------------------------------------------------------------- 92*7ba890bfSKyungmin Park */ 93*7ba890bfSKyungmin Park 94*7ba890bfSKyungmin Park #ifndef _LINUX_RBTREE_H 95*7ba890bfSKyungmin Park #define _LINUX_RBTREE_H 96*7ba890bfSKyungmin Park 97*7ba890bfSKyungmin Park #include <linux/stddef.h> 98*7ba890bfSKyungmin Park 99*7ba890bfSKyungmin Park struct rb_node 100*7ba890bfSKyungmin Park { 101*7ba890bfSKyungmin Park unsigned long rb_parent_color; 102*7ba890bfSKyungmin Park #define RB_RED 0 103*7ba890bfSKyungmin Park #define RB_BLACK 1 104*7ba890bfSKyungmin Park struct rb_node *rb_right; 105*7ba890bfSKyungmin Park struct rb_node *rb_left; 106*7ba890bfSKyungmin Park } __attribute__((aligned(sizeof(long)))); 107*7ba890bfSKyungmin Park /* The alignment might seem pointless, but allegedly CRIS needs it */ 108*7ba890bfSKyungmin Park 109*7ba890bfSKyungmin Park struct rb_root 110*7ba890bfSKyungmin Park { 111*7ba890bfSKyungmin Park struct rb_node *rb_node; 112*7ba890bfSKyungmin Park }; 113*7ba890bfSKyungmin Park 114*7ba890bfSKyungmin Park 115*7ba890bfSKyungmin Park #define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3)) 116*7ba890bfSKyungmin Park #define rb_color(r) ((r)->rb_parent_color & 1) 117*7ba890bfSKyungmin Park #define rb_is_red(r) (!rb_color(r)) 118*7ba890bfSKyungmin Park #define rb_is_black(r) rb_color(r) 119*7ba890bfSKyungmin Park #define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0) 120*7ba890bfSKyungmin Park #define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0) 121*7ba890bfSKyungmin Park 122*7ba890bfSKyungmin Park static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) 123*7ba890bfSKyungmin Park { 124*7ba890bfSKyungmin Park rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p; 125*7ba890bfSKyungmin Park } 126*7ba890bfSKyungmin Park static inline void rb_set_color(struct rb_node *rb, int color) 127*7ba890bfSKyungmin Park { 128*7ba890bfSKyungmin Park rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; 129*7ba890bfSKyungmin Park } 130*7ba890bfSKyungmin Park 131*7ba890bfSKyungmin Park #define RB_ROOT (struct rb_root) { NULL, } 132*7ba890bfSKyungmin Park #define rb_entry(ptr, type, member) container_of(ptr, type, member) 133*7ba890bfSKyungmin Park 134*7ba890bfSKyungmin Park #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) 135*7ba890bfSKyungmin Park #define RB_EMPTY_NODE(node) (rb_parent(node) == node) 136*7ba890bfSKyungmin Park #define RB_CLEAR_NODE(node) (rb_set_parent(node, node)) 137*7ba890bfSKyungmin Park 138*7ba890bfSKyungmin Park extern void rb_insert_color(struct rb_node *, struct rb_root *); 139*7ba890bfSKyungmin Park extern void rb_erase(struct rb_node *, struct rb_root *); 140*7ba890bfSKyungmin Park 141*7ba890bfSKyungmin Park /* Find logical next and previous nodes in a tree */ 142*7ba890bfSKyungmin Park extern struct rb_node *rb_next(struct rb_node *); 143*7ba890bfSKyungmin Park extern struct rb_node *rb_prev(struct rb_node *); 144*7ba890bfSKyungmin Park extern struct rb_node *rb_first(struct rb_root *); 145*7ba890bfSKyungmin Park extern struct rb_node *rb_last(struct rb_root *); 146*7ba890bfSKyungmin Park 147*7ba890bfSKyungmin Park /* Fast replacement of a single node without remove/rebalance/add/rebalance */ 148*7ba890bfSKyungmin Park extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, 149*7ba890bfSKyungmin Park struct rb_root *root); 150*7ba890bfSKyungmin Park 151*7ba890bfSKyungmin Park static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, 152*7ba890bfSKyungmin Park struct rb_node ** rb_link) 153*7ba890bfSKyungmin Park { 154*7ba890bfSKyungmin Park node->rb_parent_color = (unsigned long )parent; 155*7ba890bfSKyungmin Park node->rb_left = node->rb_right = NULL; 156*7ba890bfSKyungmin Park 157*7ba890bfSKyungmin Park *rb_link = node; 158*7ba890bfSKyungmin Park } 159*7ba890bfSKyungmin Park 160*7ba890bfSKyungmin Park #endif /* _LINUX_RBTREE_H */ 161