]> rtime.felk.cvut.cz Git - zynq/linux.git/blob - include/linux/rbtree_augmented.h
Apply preempt_rt patch-4.9-rt1.patch.xz
[zynq/linux.git] / include / linux / rbtree_augmented.h
1 /*
2   Red Black Trees
3   (C) 1999  Andrea Arcangeli <andrea@suse.de>
4   (C) 2002  David Woodhouse <dwmw2@infradead.org>
5   (C) 2012  Michel Lespinasse <walken@google.com>
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
21   linux/include/linux/rbtree_augmented.h
22 */
23
24 #ifndef _LINUX_RBTREE_AUGMENTED_H
25 #define _LINUX_RBTREE_AUGMENTED_H
26
27 #include <linux/compiler.h>
28 #include <linux/rbtree.h>
29 #include <linux/rcupdate.h>
30
31 /*
32  * Please note - only struct rb_augment_callbacks and the prototypes for
33  * rb_insert_augmented() and rb_erase_augmented() are intended to be public.
34  * The rest are implementation details you are not expected to depend on.
35  *
36  * See Documentation/rbtree.txt for documentation and samples.
37  */
38
39 struct rb_augment_callbacks {
40         void (*propagate)(struct rb_node *node, struct rb_node *stop);
41         void (*copy)(struct rb_node *old, struct rb_node *new);
42         void (*rotate)(struct rb_node *old, struct rb_node *new);
43 };
44
45 extern void __rb_insert_augmented(struct rb_node *node, struct rb_root *root,
46         void (*augment_rotate)(struct rb_node *old, struct rb_node *new));
47 /*
48  * Fixup the rbtree and update the augmented information when rebalancing.
49  *
50  * On insertion, the user must update the augmented information on the path
51  * leading to the inserted node, then call rb_link_node() as usual and
52  * rb_augment_inserted() instead of the usual rb_insert_color() call.
53  * If rb_augment_inserted() rebalances the rbtree, it will callback into
54  * a user provided function to update the augmented information on the
55  * affected subtrees.
56  */
57 static inline void
58 rb_insert_augmented(struct rb_node *node, struct rb_root *root,
59                     const struct rb_augment_callbacks *augment)
60 {
61         __rb_insert_augmented(node, root, augment->rotate);
62 }
63
64 #define RB_DECLARE_CALLBACKS(rbstatic, rbname, rbstruct, rbfield,       \
65                              rbtype, rbaugmented, rbcompute)            \
66 static inline void                                                      \
67 rbname ## _propagate(struct rb_node *rb, struct rb_node *stop)          \
68 {                                                                       \
69         while (rb != stop) {                                            \
70                 rbstruct *node = rb_entry(rb, rbstruct, rbfield);       \
71                 rbtype augmented = rbcompute(node);                     \
72                 if (node->rbaugmented == augmented)                     \
73                         break;                                          \
74                 node->rbaugmented = augmented;                          \
75                 rb = rb_parent(&node->rbfield);                         \
76         }                                                               \
77 }                                                                       \
78 static inline void                                                      \
79 rbname ## _copy(struct rb_node *rb_old, struct rb_node *rb_new)         \
80 {                                                                       \
81         rbstruct *old = rb_entry(rb_old, rbstruct, rbfield);            \
82         rbstruct *new = rb_entry(rb_new, rbstruct, rbfield);            \
83         new->rbaugmented = old->rbaugmented;                            \
84 }                                                                       \
85 static void                                                             \
86 rbname ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new)       \
87 {                                                                       \
88         rbstruct *old = rb_entry(rb_old, rbstruct, rbfield);            \
89         rbstruct *new = rb_entry(rb_new, rbstruct, rbfield);            \
90         new->rbaugmented = old->rbaugmented;                            \
91         old->rbaugmented = rbcompute(old);                              \
92 }                                                                       \
93 rbstatic const struct rb_augment_callbacks rbname = {                   \
94         rbname ## _propagate, rbname ## _copy, rbname ## _rotate        \
95 };
96
97
98 #define RB_RED          0
99 #define RB_BLACK        1
100
101 #define __rb_parent(pc)    ((struct rb_node *)(pc & ~3))
102
103 #define __rb_color(pc)     ((pc) & 1)
104 #define __rb_is_black(pc)  __rb_color(pc)
105 #define __rb_is_red(pc)    (!__rb_color(pc))
106 #define rb_color(rb)       __rb_color((rb)->__rb_parent_color)
107 #define rb_is_red(rb)      __rb_is_red((rb)->__rb_parent_color)
108 #define rb_is_black(rb)    __rb_is_black((rb)->__rb_parent_color)
109
110 static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
111 {
112         rb->__rb_parent_color = rb_color(rb) | (unsigned long)p;
113 }
114
115 static inline void rb_set_parent_color(struct rb_node *rb,
116                                        struct rb_node *p, int color)
117 {
118         rb->__rb_parent_color = (unsigned long)p | color;
119 }
120
121 static inline void
122 __rb_change_child(struct rb_node *old, struct rb_node *new,
123                   struct rb_node *parent, struct rb_root *root)
124 {
125         if (parent) {
126                 if (parent->rb_left == old)
127                         WRITE_ONCE(parent->rb_left, new);
128                 else
129                         WRITE_ONCE(parent->rb_right, new);
130         } else
131                 WRITE_ONCE(root->rb_node, new);
132 }
133
134 static inline void
135 __rb_change_child_rcu(struct rb_node *old, struct rb_node *new,
136                       struct rb_node *parent, struct rb_root *root)
137 {
138         if (parent) {
139                 if (parent->rb_left == old)
140                         rcu_assign_pointer(parent->rb_left, new);
141                 else
142                         rcu_assign_pointer(parent->rb_right, new);
143         } else
144                 rcu_assign_pointer(root->rb_node, new);
145 }
146
147 extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root,
148         void (*augment_rotate)(struct rb_node *old, struct rb_node *new));
149
150 static __always_inline struct rb_node *
151 __rb_erase_augmented(struct rb_node *node, struct rb_root *root,
152                      const struct rb_augment_callbacks *augment)
153 {
154         struct rb_node *child = node->rb_right;
155         struct rb_node *tmp = node->rb_left;
156         struct rb_node *parent, *rebalance;
157         unsigned long pc;
158
159         if (!tmp) {
160                 /*
161                  * Case 1: node to erase has no more than 1 child (easy!)
162                  *
163                  * Note that if there is one child it must be red due to 5)
164                  * and node must be black due to 4). We adjust colors locally
165                  * so as to bypass __rb_erase_color() later on.
166                  */
167                 pc = node->__rb_parent_color;
168                 parent = __rb_parent(pc);
169                 __rb_change_child(node, child, parent, root);
170                 if (child) {
171                         child->__rb_parent_color = pc;
172                         rebalance = NULL;
173                 } else
174                         rebalance = __rb_is_black(pc) ? parent : NULL;
175                 tmp = parent;
176         } else if (!child) {
177                 /* Still case 1, but this time the child is node->rb_left */
178                 tmp->__rb_parent_color = pc = node->__rb_parent_color;
179                 parent = __rb_parent(pc);
180                 __rb_change_child(node, tmp, parent, root);
181                 rebalance = NULL;
182                 tmp = parent;
183         } else {
184                 struct rb_node *successor = child, *child2;
185
186                 tmp = child->rb_left;
187                 if (!tmp) {
188                         /*
189                          * Case 2: node's successor is its right child
190                          *
191                          *    (n)          (s)
192                          *    / \          / \
193                          *  (x) (s)  ->  (x) (c)
194                          *        \
195                          *        (c)
196                          */
197                         parent = successor;
198                         child2 = successor->rb_right;
199
200                         augment->copy(node, successor);
201                 } else {
202                         /*
203                          * Case 3: node's successor is leftmost under
204                          * node's right child subtree
205                          *
206                          *    (n)          (s)
207                          *    / \          / \
208                          *  (x) (y)  ->  (x) (y)
209                          *      /            /
210                          *    (p)          (p)
211                          *    /            /
212                          *  (s)          (c)
213                          *    \
214                          *    (c)
215                          */
216                         do {
217                                 parent = successor;
218                                 successor = tmp;
219                                 tmp = tmp->rb_left;
220                         } while (tmp);
221                         child2 = successor->rb_right;
222                         WRITE_ONCE(parent->rb_left, child2);
223                         WRITE_ONCE(successor->rb_right, child);
224                         rb_set_parent(child, successor);
225
226                         augment->copy(node, successor);
227                         augment->propagate(parent, successor);
228                 }
229
230                 tmp = node->rb_left;
231                 WRITE_ONCE(successor->rb_left, tmp);
232                 rb_set_parent(tmp, successor);
233
234                 pc = node->__rb_parent_color;
235                 tmp = __rb_parent(pc);
236                 __rb_change_child(node, successor, tmp, root);
237
238                 if (child2) {
239                         successor->__rb_parent_color = pc;
240                         rb_set_parent_color(child2, parent, RB_BLACK);
241                         rebalance = NULL;
242                 } else {
243                         unsigned long pc2 = successor->__rb_parent_color;
244                         successor->__rb_parent_color = pc;
245                         rebalance = __rb_is_black(pc2) ? parent : NULL;
246                 }
247                 tmp = successor;
248         }
249
250         augment->propagate(tmp, NULL);
251         return rebalance;
252 }
253
254 static __always_inline void
255 rb_erase_augmented(struct rb_node *node, struct rb_root *root,
256                    const struct rb_augment_callbacks *augment)
257 {
258         struct rb_node *rebalance = __rb_erase_augmented(node, root, augment);
259         if (rebalance)
260                 __rb_erase_color(rebalance, root, augment->rotate);
261 }
262
263 #endif  /* _LINUX_RBTREE_AUGMENTED_H */