1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker Red Black Trees
3*6a54128fSAndroid Build Coastguard Worker (C) 1999 Andrea Arcangeli <[email protected]>
4*6a54128fSAndroid Build Coastguard Worker
5*6a54128fSAndroid Build Coastguard Worker This program is free software; you can redistribute it and/or modify
6*6a54128fSAndroid Build Coastguard Worker it under the terms of the GNU General Public License as published by
7*6a54128fSAndroid Build Coastguard Worker the Free Software Foundation; either version 2 of the License, or
8*6a54128fSAndroid Build Coastguard Worker (at your option) any later version.
9*6a54128fSAndroid Build Coastguard Worker
10*6a54128fSAndroid Build Coastguard Worker This program is distributed in the hope that it will be useful,
11*6a54128fSAndroid Build Coastguard Worker but WITHOUT ANY WARRANTY; without even the implied warranty of
12*6a54128fSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*6a54128fSAndroid Build Coastguard Worker GNU General Public License for more details.
14*6a54128fSAndroid Build Coastguard Worker
15*6a54128fSAndroid Build Coastguard Worker You should have received a copy of the GNU General Public License
16*6a54128fSAndroid Build Coastguard Worker along with this program; if not, write to the Free Software
17*6a54128fSAndroid Build Coastguard Worker Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*6a54128fSAndroid Build Coastguard Worker
19*6a54128fSAndroid Build Coastguard Worker linux/include/linux/rbtree.h
20*6a54128fSAndroid Build Coastguard Worker
21*6a54128fSAndroid Build Coastguard Worker To use rbtrees you'll have to implement your own insert and search cores.
22*6a54128fSAndroid Build Coastguard Worker This will avoid us to use callbacks and to drop dramatically performances.
23*6a54128fSAndroid Build Coastguard Worker I know it's not the cleaner way, but in C (not in C++) to get
24*6a54128fSAndroid Build Coastguard Worker performances and genericity...
25*6a54128fSAndroid Build Coastguard Worker
26*6a54128fSAndroid Build Coastguard Worker Some example of insert and search follows here. The search is a plain
27*6a54128fSAndroid Build Coastguard Worker normal search over an ordered tree. The insert instead must be implemented
28*6a54128fSAndroid Build Coastguard Worker in two steps: First, the code must insert the element in order as a red leaf
29*6a54128fSAndroid Build Coastguard Worker in the tree, and then the support library function rb_insert_color() must
30*6a54128fSAndroid Build Coastguard Worker be called. Such function will do the not trivial work to rebalance the
31*6a54128fSAndroid Build Coastguard Worker rbtree, if necessary.
32*6a54128fSAndroid Build Coastguard Worker
33*6a54128fSAndroid Build Coastguard Worker -----------------------------------------------------------------------
34*6a54128fSAndroid Build Coastguard Worker static inline struct page * rb_search_page_cache(struct inode * inode,
35*6a54128fSAndroid Build Coastguard Worker unsigned long offset)
36*6a54128fSAndroid Build Coastguard Worker {
37*6a54128fSAndroid Build Coastguard Worker struct rb_node * n = inode->i_rb_page_cache.rb_node;
38*6a54128fSAndroid Build Coastguard Worker struct page * page;
39*6a54128fSAndroid Build Coastguard Worker
40*6a54128fSAndroid Build Coastguard Worker while (n)
41*6a54128fSAndroid Build Coastguard Worker {
42*6a54128fSAndroid Build Coastguard Worker page = rb_entry(n, struct page, rb_page_cache);
43*6a54128fSAndroid Build Coastguard Worker
44*6a54128fSAndroid Build Coastguard Worker if (offset < page->offset)
45*6a54128fSAndroid Build Coastguard Worker n = n->rb_left;
46*6a54128fSAndroid Build Coastguard Worker else if (offset > page->offset)
47*6a54128fSAndroid Build Coastguard Worker n = n->rb_right;
48*6a54128fSAndroid Build Coastguard Worker else
49*6a54128fSAndroid Build Coastguard Worker return page;
50*6a54128fSAndroid Build Coastguard Worker }
51*6a54128fSAndroid Build Coastguard Worker return NULL;
52*6a54128fSAndroid Build Coastguard Worker }
53*6a54128fSAndroid Build Coastguard Worker
54*6a54128fSAndroid Build Coastguard Worker static inline struct page * __rb_insert_page_cache(struct inode * inode,
55*6a54128fSAndroid Build Coastguard Worker unsigned long offset,
56*6a54128fSAndroid Build Coastguard Worker struct rb_node * node)
57*6a54128fSAndroid Build Coastguard Worker {
58*6a54128fSAndroid Build Coastguard Worker struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
59*6a54128fSAndroid Build Coastguard Worker struct rb_node * parent = NULL;
60*6a54128fSAndroid Build Coastguard Worker struct page * page;
61*6a54128fSAndroid Build Coastguard Worker
62*6a54128fSAndroid Build Coastguard Worker while (*p)
63*6a54128fSAndroid Build Coastguard Worker {
64*6a54128fSAndroid Build Coastguard Worker parent = *p;
65*6a54128fSAndroid Build Coastguard Worker page = rb_entry(parent, struct page, rb_page_cache);
66*6a54128fSAndroid Build Coastguard Worker
67*6a54128fSAndroid Build Coastguard Worker if (offset < page->offset)
68*6a54128fSAndroid Build Coastguard Worker p = &(*p)->rb_left;
69*6a54128fSAndroid Build Coastguard Worker else if (offset > page->offset)
70*6a54128fSAndroid Build Coastguard Worker p = &(*p)->rb_right;
71*6a54128fSAndroid Build Coastguard Worker else
72*6a54128fSAndroid Build Coastguard Worker return page;
73*6a54128fSAndroid Build Coastguard Worker }
74*6a54128fSAndroid Build Coastguard Worker
75*6a54128fSAndroid Build Coastguard Worker rb_link_node(node, parent, p);
76*6a54128fSAndroid Build Coastguard Worker
77*6a54128fSAndroid Build Coastguard Worker return NULL;
78*6a54128fSAndroid Build Coastguard Worker }
79*6a54128fSAndroid Build Coastguard Worker
80*6a54128fSAndroid Build Coastguard Worker static inline struct page * rb_insert_page_cache(struct inode * inode,
81*6a54128fSAndroid Build Coastguard Worker unsigned long offset,
82*6a54128fSAndroid Build Coastguard Worker struct rb_node * node)
83*6a54128fSAndroid Build Coastguard Worker {
84*6a54128fSAndroid Build Coastguard Worker struct page * ret;
85*6a54128fSAndroid Build Coastguard Worker if ((ret = __rb_insert_page_cache(inode, offset, node)))
86*6a54128fSAndroid Build Coastguard Worker goto out;
87*6a54128fSAndroid Build Coastguard Worker rb_insert_color(node, &inode->i_rb_page_cache);
88*6a54128fSAndroid Build Coastguard Worker out:
89*6a54128fSAndroid Build Coastguard Worker return ret;
90*6a54128fSAndroid Build Coastguard Worker }
91*6a54128fSAndroid Build Coastguard Worker -----------------------------------------------------------------------
92*6a54128fSAndroid Build Coastguard Worker */
93*6a54128fSAndroid Build Coastguard Worker
94*6a54128fSAndroid Build Coastguard Worker #ifndef _LINUX_RBTREE_H
95*6a54128fSAndroid Build Coastguard Worker #define _LINUX_RBTREE_H
96*6a54128fSAndroid Build Coastguard Worker
97*6a54128fSAndroid Build Coastguard Worker #include <stdlib.h>
98*6a54128fSAndroid Build Coastguard Worker #include <stdint.h>
99*6a54128fSAndroid Build Coastguard Worker #include "compiler.h"
100*6a54128fSAndroid Build Coastguard Worker
101*6a54128fSAndroid Build Coastguard Worker #if __GNUC_PREREQ (4, 6)
102*6a54128fSAndroid Build Coastguard Worker #pragma GCC diagnostic push
103*6a54128fSAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wunused-function"
104*6a54128fSAndroid Build Coastguard Worker #endif
105*6a54128fSAndroid Build Coastguard Worker
106*6a54128fSAndroid Build Coastguard Worker struct rb_node
107*6a54128fSAndroid Build Coastguard Worker {
108*6a54128fSAndroid Build Coastguard Worker uintptr_t rb_parent_color;
109*6a54128fSAndroid Build Coastguard Worker #define RB_RED 0
110*6a54128fSAndroid Build Coastguard Worker #define RB_BLACK 1
111*6a54128fSAndroid Build Coastguard Worker struct rb_node *rb_right;
112*6a54128fSAndroid Build Coastguard Worker struct rb_node *rb_left;
113*6a54128fSAndroid Build Coastguard Worker } __attribute__((aligned(sizeof(long))));
114*6a54128fSAndroid Build Coastguard Worker /* The alignment might seem pointless, but allegedly CRIS needs it */
115*6a54128fSAndroid Build Coastguard Worker
116*6a54128fSAndroid Build Coastguard Worker struct rb_root
117*6a54128fSAndroid Build Coastguard Worker {
118*6a54128fSAndroid Build Coastguard Worker struct rb_node *rb_node;
119*6a54128fSAndroid Build Coastguard Worker };
120*6a54128fSAndroid Build Coastguard Worker
121*6a54128fSAndroid Build Coastguard Worker
122*6a54128fSAndroid Build Coastguard Worker #define ext2fs_rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
123*6a54128fSAndroid Build Coastguard Worker #define ext2fs_rb_color(r) ((r)->rb_parent_color & 1)
124*6a54128fSAndroid Build Coastguard Worker #define ext2fs_rb_is_red(r) (!ext2fs_rb_color(r))
125*6a54128fSAndroid Build Coastguard Worker #define ext2fs_rb_is_black(r) ext2fs_rb_color(r)
126*6a54128fSAndroid Build Coastguard Worker #define ext2fs_rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
127*6a54128fSAndroid Build Coastguard Worker #define ext2fs_rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
128*6a54128fSAndroid Build Coastguard Worker
ext2fs_rb_set_parent(struct rb_node * rb,struct rb_node * p)129*6a54128fSAndroid Build Coastguard Worker static inline void ext2fs_rb_set_parent(struct rb_node *rb, struct rb_node *p)
130*6a54128fSAndroid Build Coastguard Worker {
131*6a54128fSAndroid Build Coastguard Worker rb->rb_parent_color = (rb->rb_parent_color & 3) | (uintptr_t)p;
132*6a54128fSAndroid Build Coastguard Worker }
ext2fs_rb_set_color(struct rb_node * rb,int color)133*6a54128fSAndroid Build Coastguard Worker static inline void ext2fs_rb_set_color(struct rb_node *rb, int color)
134*6a54128fSAndroid Build Coastguard Worker {
135*6a54128fSAndroid Build Coastguard Worker rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
136*6a54128fSAndroid Build Coastguard Worker }
137*6a54128fSAndroid Build Coastguard Worker
138*6a54128fSAndroid Build Coastguard Worker #define RB_ROOT (struct rb_root) { NULL, }
139*6a54128fSAndroid Build Coastguard Worker #define ext2fs_rb_entry(ptr, type, member) container_of(ptr, type, member)
140*6a54128fSAndroid Build Coastguard Worker
ext2fs_rb_empty_root(struct rb_root * root)141*6a54128fSAndroid Build Coastguard Worker static inline int ext2fs_rb_empty_root(struct rb_root *root)
142*6a54128fSAndroid Build Coastguard Worker {
143*6a54128fSAndroid Build Coastguard Worker return root->rb_node == NULL;
144*6a54128fSAndroid Build Coastguard Worker }
145*6a54128fSAndroid Build Coastguard Worker
ext2fs_rb_empty_node(struct rb_node * node)146*6a54128fSAndroid Build Coastguard Worker static inline int ext2fs_rb_empty_node(struct rb_node *node)
147*6a54128fSAndroid Build Coastguard Worker {
148*6a54128fSAndroid Build Coastguard Worker return ext2fs_rb_parent(node) == node;
149*6a54128fSAndroid Build Coastguard Worker }
150*6a54128fSAndroid Build Coastguard Worker
ext2fs_rb_clear_node(struct rb_node * node)151*6a54128fSAndroid Build Coastguard Worker static inline void ext2fs_rb_clear_node(struct rb_node *node)
152*6a54128fSAndroid Build Coastguard Worker {
153*6a54128fSAndroid Build Coastguard Worker ext2fs_rb_set_parent(node, node);
154*6a54128fSAndroid Build Coastguard Worker }
155*6a54128fSAndroid Build Coastguard Worker
156*6a54128fSAndroid Build Coastguard Worker extern void ext2fs_rb_insert_color(struct rb_node *, struct rb_root *);
157*6a54128fSAndroid Build Coastguard Worker extern void ext2fs_rb_erase(struct rb_node *, struct rb_root *);
158*6a54128fSAndroid Build Coastguard Worker
159*6a54128fSAndroid Build Coastguard Worker /* Find logical next and previous nodes in a tree */
160*6a54128fSAndroid Build Coastguard Worker extern struct rb_node *ext2fs_rb_next(struct rb_node *);
161*6a54128fSAndroid Build Coastguard Worker extern struct rb_node *ext2fs_rb_prev(struct rb_node *);
162*6a54128fSAndroid Build Coastguard Worker extern struct rb_node *ext2fs_rb_first(const struct rb_root *);
163*6a54128fSAndroid Build Coastguard Worker extern struct rb_node *ext2fs_rb_last(const struct rb_root *);
164*6a54128fSAndroid Build Coastguard Worker
165*6a54128fSAndroid Build Coastguard Worker /* Fast replacement of a single node without remove/rebalance/add/rebalance */
166*6a54128fSAndroid Build Coastguard Worker extern void ext2fs_rb_replace_node(struct rb_node *victim, struct rb_node *new,
167*6a54128fSAndroid Build Coastguard Worker struct rb_root *root);
168*6a54128fSAndroid Build Coastguard Worker
ext2fs_rb_link_node(struct rb_node * node,struct rb_node * parent,struct rb_node ** rb_link)169*6a54128fSAndroid Build Coastguard Worker static inline void ext2fs_rb_link_node(struct rb_node * node,
170*6a54128fSAndroid Build Coastguard Worker struct rb_node * parent,
171*6a54128fSAndroid Build Coastguard Worker struct rb_node ** rb_link)
172*6a54128fSAndroid Build Coastguard Worker {
173*6a54128fSAndroid Build Coastguard Worker node->rb_parent_color = (uintptr_t)parent;
174*6a54128fSAndroid Build Coastguard Worker node->rb_left = node->rb_right = NULL;
175*6a54128fSAndroid Build Coastguard Worker
176*6a54128fSAndroid Build Coastguard Worker *rb_link = node;
177*6a54128fSAndroid Build Coastguard Worker }
178*6a54128fSAndroid Build Coastguard Worker
179*6a54128fSAndroid Build Coastguard Worker #if __GNUC_PREREQ (4, 6)
180*6a54128fSAndroid Build Coastguard Worker #pragma GCC diagnostic pop
181*6a54128fSAndroid Build Coastguard Worker #endif
182*6a54128fSAndroid Build Coastguard Worker
183*6a54128fSAndroid Build Coastguard Worker #endif /* _LINUX_RBTREE_H */
184