1 | /* SPDX-License-Identifier: GPL-2.0-or-later */
|
---|
2 | /*
|
---|
3 | Red Black Trees
|
---|
4 | (C) 1999 Andrea Arcangeli <andrea@suse.de>
|
---|
5 | (C) 2002 David Woodhouse <dwmw2@infradead.org>
|
---|
6 | (C) 2012 Michel Lespinasse <walken@google.com>
|
---|
7 |
|
---|
8 |
|
---|
9 | linux/include/linux/rbtree_augmented.h
|
---|
10 | */
|
---|
11 |
|
---|
12 | /* from 5.10.10 */
|
---|
13 |
|
---|
14 | #ifndef _LINUX_RBTREE_AUGMENTED_H
|
---|
15 | #define _LINUX_RBTREE_AUGMENTED_H
|
---|
16 |
|
---|
17 | #include <linux/compiler.h>
|
---|
18 | #include <linux/rbtree.h>
|
---|
19 | //#include <linux/rcupdate.h>
|
---|
20 |
|
---|
21 | /*
|
---|
22 | * Please note - only struct rb_augment_callbacks and the prototypes for
|
---|
23 | * rb_insert_augmented() and rb_erase_augmented() are intended to be public.
|
---|
24 | * The rest are implementation details you are not expected to depend on.
|
---|
25 | *
|
---|
26 | * See Documentation/core-api/rbtree.rst for documentation and samples.
|
---|
27 | */
|
---|
28 |
|
---|
29 | struct rb_augment_callbacks {
|
---|
30 | void (*propagate)(struct rb_node *node, struct rb_node *stop);
|
---|
31 | void (*copy)(struct rb_node *old, struct rb_node *new);
|
---|
32 | void (*rotate)(struct rb_node *old, struct rb_node *new);
|
---|
33 | };
|
---|
34 |
|
---|
35 | extern void __rb_insert_augmented(struct rb_node *node, struct rb_root *root,
|
---|
36 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new));
|
---|
37 |
|
---|
38 | /*
|
---|
39 | * Fixup the rbtree and update the augmented information when rebalancing.
|
---|
40 | *
|
---|
41 | * On insertion, the user must update the augmented information on the path
|
---|
42 | * leading to the inserted node, then call rb_link_node() as usual and
|
---|
43 | * rb_insert_augmented() instead of the usual rb_insert_color() call.
|
---|
44 | * If rb_insert_augmented() rebalances the rbtree, it will callback into
|
---|
45 | * a user provided function to update the augmented information on the
|
---|
46 | * affected subtrees.
|
---|
47 | */
|
---|
48 | static inline void
|
---|
49 | rb_insert_augmented(struct rb_node *node, struct rb_root *root,
|
---|
50 | const struct rb_augment_callbacks *augment)
|
---|
51 | {
|
---|
52 | __rb_insert_augmented(node, root, augment->rotate);
|
---|
53 | }
|
---|
54 |
|
---|
55 | static inline void
|
---|
56 | rb_insert_augmented_cached(struct rb_node *node,
|
---|
57 | struct rb_root_cached *root, bool newleft,
|
---|
58 | const struct rb_augment_callbacks *augment)
|
---|
59 | {
|
---|
60 | if (newleft)
|
---|
61 | root->rb_leftmost = node;
|
---|
62 | rb_insert_augmented(node, &root->rb_root, augment);
|
---|
63 | }
|
---|
64 |
|
---|
65 | /*
|
---|
66 | * Template for declaring augmented rbtree callbacks (generic case)
|
---|
67 | *
|
---|
68 | * RBSTATIC: 'static' or empty
|
---|
69 | * RBNAME: name of the rb_augment_callbacks structure
|
---|
70 | * RBSTRUCT: struct type of the tree nodes
|
---|
71 | * RBFIELD: name of struct rb_node field within RBSTRUCT
|
---|
72 | * RBAUGMENTED: name of field within RBSTRUCT holding data for subtree
|
---|
73 | * RBCOMPUTE: name of function that recomputes the RBAUGMENTED data
|
---|
74 | */
|
---|
75 |
|
---|
76 | #define RB_DECLARE_CALLBACKS(RBSTATIC, RBNAME, \
|
---|
77 | RBSTRUCT, RBFIELD, RBAUGMENTED, RBCOMPUTE) \
|
---|
78 | static inline void \
|
---|
79 | RBNAME ## _propagate(struct rb_node *rb, struct rb_node *stop) \
|
---|
80 | { \
|
---|
81 | while (rb != stop) { \
|
---|
82 | RBSTRUCT *node = rb_entry(rb, RBSTRUCT, RBFIELD); \
|
---|
83 | if (RBCOMPUTE(node, true)) \
|
---|
84 | break; \
|
---|
85 | rb = rb_parent(&node->RBFIELD); \
|
---|
86 | } \
|
---|
87 | } \
|
---|
88 | static inline void \
|
---|
89 | RBNAME ## _copy(struct rb_node *rb_old, struct rb_node *rb_new) \
|
---|
90 | { \
|
---|
91 | RBSTRUCT *old = rb_entry(rb_old, RBSTRUCT, RBFIELD); \
|
---|
92 | RBSTRUCT *new = rb_entry(rb_new, RBSTRUCT, RBFIELD); \
|
---|
93 | new->RBAUGMENTED = old->RBAUGMENTED; \
|
---|
94 | } \
|
---|
95 | static void \
|
---|
96 | RBNAME ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new) \
|
---|
97 | { \
|
---|
98 | RBSTRUCT *old = rb_entry(rb_old, RBSTRUCT, RBFIELD); \
|
---|
99 | RBSTRUCT *new = rb_entry(rb_new, RBSTRUCT, RBFIELD); \
|
---|
100 | new->RBAUGMENTED = old->RBAUGMENTED; \
|
---|
101 | RBCOMPUTE(old, false); \
|
---|
102 | } \
|
---|
103 | RBSTATIC const struct rb_augment_callbacks RBNAME = { \
|
---|
104 | .propagate = RBNAME ## _propagate, \
|
---|
105 | .copy = RBNAME ## _copy, \
|
---|
106 | .rotate = RBNAME ## _rotate \
|
---|
107 | };
|
---|
108 |
|
---|
109 | /*
|
---|
110 | * Template for declaring augmented rbtree callbacks,
|
---|
111 | * computing RBAUGMENTED scalar as max(RBCOMPUTE(node)) for all subtree nodes.
|
---|
112 | *
|
---|
113 | * RBSTATIC: 'static' or empty
|
---|
114 | * RBNAME: name of the rb_augment_callbacks structure
|
---|
115 | * RBSTRUCT: struct type of the tree nodes
|
---|
116 | * RBFIELD: name of struct rb_node field within RBSTRUCT
|
---|
117 | * RBTYPE: type of the RBAUGMENTED field
|
---|
118 | * RBAUGMENTED: name of RBTYPE field within RBSTRUCT holding data for subtree
|
---|
119 | * RBCOMPUTE: name of function that returns the per-node RBTYPE scalar
|
---|
120 | */
|
---|
121 |
|
---|
122 | #define RB_DECLARE_CALLBACKS_MAX(RBSTATIC, RBNAME, RBSTRUCT, RBFIELD, \
|
---|
123 | RBTYPE, RBAUGMENTED, RBCOMPUTE) \
|
---|
124 | static inline bool RBNAME ## _compute_max(RBSTRUCT *node, bool exit) \
|
---|
125 | { \
|
---|
126 | RBSTRUCT *child; \
|
---|
127 | RBTYPE max = RBCOMPUTE(node); \
|
---|
128 | if (node->RBFIELD.rb_left) { \
|
---|
129 | child = rb_entry(node->RBFIELD.rb_left, RBSTRUCT, RBFIELD); \
|
---|
130 | if (child->RBAUGMENTED > max) \
|
---|
131 | max = child->RBAUGMENTED; \
|
---|
132 | } \
|
---|
133 | if (node->RBFIELD.rb_right) { \
|
---|
134 | child = rb_entry(node->RBFIELD.rb_right, RBSTRUCT, RBFIELD); \
|
---|
135 | if (child->RBAUGMENTED > max) \
|
---|
136 | max = child->RBAUGMENTED; \
|
---|
137 | } \
|
---|
138 | if (exit && node->RBAUGMENTED == max) \
|
---|
139 | return true; \
|
---|
140 | node->RBAUGMENTED = max; \
|
---|
141 | return false; \
|
---|
142 | } \
|
---|
143 | RB_DECLARE_CALLBACKS(RBSTATIC, RBNAME, \
|
---|
144 | RBSTRUCT, RBFIELD, RBAUGMENTED, RBNAME ## _compute_max)
|
---|
145 |
|
---|
146 |
|
---|
147 | #define RB_RED 0
|
---|
148 | #define RB_BLACK 1
|
---|
149 |
|
---|
150 | #define __rb_parent(pc) ((struct rb_node *)(pc & ~3))
|
---|
151 |
|
---|
152 | #define __rb_color(pc) ((pc) & 1)
|
---|
153 | #define __rb_is_black(pc) __rb_color(pc)
|
---|
154 | #define __rb_is_red(pc) (!__rb_color(pc))
|
---|
155 | #define rb_color(rb) __rb_color((rb)->__rb_parent_color)
|
---|
156 | #define rb_is_red(rb) __rb_is_red((rb)->__rb_parent_color)
|
---|
157 | #define rb_is_black(rb) __rb_is_black((rb)->__rb_parent_color)
|
---|
158 |
|
---|
159 | static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
|
---|
160 | {
|
---|
161 | rb->__rb_parent_color = rb_color(rb) | (unsigned long)p;
|
---|
162 | }
|
---|
163 |
|
---|
164 | static inline void rb_set_parent_color(struct rb_node *rb,
|
---|
165 | struct rb_node *p, int color)
|
---|
166 | {
|
---|
167 | rb->__rb_parent_color = (unsigned long)p | color;
|
---|
168 | }
|
---|
169 |
|
---|
170 | static inline void
|
---|
171 | __rb_change_child(struct rb_node *old, struct rb_node *new,
|
---|
172 | struct rb_node *parent, struct rb_root *root)
|
---|
173 | {
|
---|
174 | if (parent) {
|
---|
175 | if (parent->rb_left == old)
|
---|
176 | WRITE_ONCE(parent->rb_left, new);
|
---|
177 | else
|
---|
178 | WRITE_ONCE(parent->rb_right, new);
|
---|
179 | } else
|
---|
180 | WRITE_ONCE(root->rb_node, new);
|
---|
181 | }
|
---|
182 |
|
---|
183 | #ifndef TARGET_OS2
|
---|
184 | static inline void
|
---|
185 | __rb_change_child_rcu(struct rb_node *old, struct rb_node *new,
|
---|
186 | struct rb_node *parent, struct rb_root *root)
|
---|
187 | {
|
---|
188 | if (parent) {
|
---|
189 | if (parent->rb_left == old)
|
---|
190 | rcu_assign_pointer(parent->rb_left, new);
|
---|
191 | else
|
---|
192 | rcu_assign_pointer(parent->rb_right, new);
|
---|
193 | } else
|
---|
194 | rcu_assign_pointer(root->rb_node, new);
|
---|
195 | }
|
---|
196 | #endif
|
---|
197 |
|
---|
198 | extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root,
|
---|
199 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new));
|
---|
200 |
|
---|
201 | static inline struct rb_node *
|
---|
202 | __rb_erase_augmented(struct rb_node *node, struct rb_root *root,
|
---|
203 | const struct rb_augment_callbacks *augment)
|
---|
204 | {
|
---|
205 | struct rb_node *child = node->rb_right;
|
---|
206 | struct rb_node *tmp = node->rb_left;
|
---|
207 | struct rb_node *parent, *rebalance;
|
---|
208 | unsigned long pc;
|
---|
209 |
|
---|
210 | if (!tmp) {
|
---|
211 | /*
|
---|
212 | * Case 1: node to erase has no more than 1 child (easy!)
|
---|
213 | *
|
---|
214 | * Note that if there is one child it must be red due to 5)
|
---|
215 | * and node must be black due to 4). We adjust colors locally
|
---|
216 | * so as to bypass __rb_erase_color() later on.
|
---|
217 | */
|
---|
218 | pc = node->__rb_parent_color;
|
---|
219 | parent = __rb_parent(pc);
|
---|
220 | __rb_change_child(node, child, parent, root);
|
---|
221 | if (child) {
|
---|
222 | child->__rb_parent_color = pc;
|
---|
223 | rebalance = NULL;
|
---|
224 | } else
|
---|
225 | rebalance = __rb_is_black(pc) ? parent : NULL;
|
---|
226 | tmp = parent;
|
---|
227 | } else if (!child) {
|
---|
228 | /* Still case 1, but this time the child is node->rb_left */
|
---|
229 | tmp->__rb_parent_color = pc = node->__rb_parent_color;
|
---|
230 | parent = __rb_parent(pc);
|
---|
231 | __rb_change_child(node, tmp, parent, root);
|
---|
232 | rebalance = NULL;
|
---|
233 | tmp = parent;
|
---|
234 | } else {
|
---|
235 | struct rb_node *successor = child, *child2;
|
---|
236 |
|
---|
237 | tmp = child->rb_left;
|
---|
238 | if (!tmp) {
|
---|
239 | /*
|
---|
240 | * Case 2: node's successor is its right child
|
---|
241 | *
|
---|
242 | * (n) (s)
|
---|
243 | * / \ / \
|
---|
244 | * (x) (s) -> (x) (c)
|
---|
245 | * \
|
---|
246 | * (c)
|
---|
247 | */
|
---|
248 | parent = successor;
|
---|
249 | child2 = successor->rb_right;
|
---|
250 |
|
---|
251 | augment->copy(node, successor);
|
---|
252 | } else {
|
---|
253 | /*
|
---|
254 | * Case 3: node's successor is leftmost under
|
---|
255 | * node's right child subtree
|
---|
256 | *
|
---|
257 | * (n) (s)
|
---|
258 | * / \ / \
|
---|
259 | * (x) (y) -> (x) (y)
|
---|
260 | * / /
|
---|
261 | * (p) (p)
|
---|
262 | * / /
|
---|
263 | * (s) (c)
|
---|
264 | * \
|
---|
265 | * (c)
|
---|
266 | */
|
---|
267 | do {
|
---|
268 | parent = successor;
|
---|
269 | successor = tmp;
|
---|
270 | tmp = tmp->rb_left;
|
---|
271 | } while (tmp);
|
---|
272 | child2 = successor->rb_right;
|
---|
273 | WRITE_ONCE(parent->rb_left, child2);
|
---|
274 | WRITE_ONCE(successor->rb_right, child);
|
---|
275 | rb_set_parent(child, successor);
|
---|
276 |
|
---|
277 | augment->copy(node, successor);
|
---|
278 | augment->propagate(parent, successor);
|
---|
279 | }
|
---|
280 |
|
---|
281 | tmp = node->rb_left;
|
---|
282 | WRITE_ONCE(successor->rb_left, tmp);
|
---|
283 | rb_set_parent(tmp, successor);
|
---|
284 |
|
---|
285 | pc = node->__rb_parent_color;
|
---|
286 | tmp = __rb_parent(pc);
|
---|
287 | __rb_change_child(node, successor, tmp, root);
|
---|
288 |
|
---|
289 | if (child2) {
|
---|
290 | rb_set_parent_color(child2, parent, RB_BLACK);
|
---|
291 | rebalance = NULL;
|
---|
292 | } else {
|
---|
293 | rebalance = rb_is_black(successor) ? parent : NULL;
|
---|
294 | }
|
---|
295 | successor->__rb_parent_color = pc;
|
---|
296 | tmp = successor;
|
---|
297 | }
|
---|
298 |
|
---|
299 | augment->propagate(tmp, NULL);
|
---|
300 | return rebalance;
|
---|
301 | }
|
---|
302 |
|
---|
303 | static inline void
|
---|
304 | rb_erase_augmented(struct rb_node *node, struct rb_root *root,
|
---|
305 | const struct rb_augment_callbacks *augment)
|
---|
306 | {
|
---|
307 | struct rb_node *rebalance = __rb_erase_augmented(node, root, augment);
|
---|
308 | if (rebalance)
|
---|
309 | __rb_erase_color(rebalance, root, augment->rotate);
|
---|
310 | }
|
---|
311 |
|
---|
312 | static inline void
|
---|
313 | rb_erase_augmented_cached(struct rb_node *node, struct rb_root_cached *root,
|
---|
314 | const struct rb_augment_callbacks *augment)
|
---|
315 | {
|
---|
316 | if (root->rb_leftmost == node)
|
---|
317 | root->rb_leftmost = rb_next(node);
|
---|
318 | rb_erase_augmented(node, &root->rb_root, augment);
|
---|
319 | }
|
---|
320 |
|
---|
321 | #endif /* _LINUX_RBTREE_AUGMENTED_H */
|
---|