1 /*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /* These assertions are very useful when debugging the tree code
8 * itself, but produce significant performance degradation as they are
9 * checked many times per operation. Leave them off unless you're
10 * working on the rbtree code itself
11 */
12 #define CHECK(n) /**/
13 /* #define CHECK(n) __ASSERT_NO_MSG(n) */
14
15 #include <zephyr/kernel.h>
16 #include <zephyr/sys/rb.h>
17 #include <stdbool.h>
18
19 enum rb_color { RED = 0U, BLACK = 1U };
20
get_child(struct rbnode * n,uint8_t side)21 static struct rbnode *get_child(struct rbnode *n, uint8_t side)
22 {
23 CHECK(n);
24 if (side != 0U) {
25 return n->children[1];
26 }
27
28 uintptr_t l = (uintptr_t) n->children[0];
29
30 l &= ~1UL;
31 return (struct rbnode *) l;
32 }
33
set_child(struct rbnode * n,uint8_t side,void * val)34 static void set_child(struct rbnode *n, uint8_t side, void *val)
35 {
36 CHECK(n);
37 if (side != 0U) {
38 n->children[1] = val;
39 } else {
40 uintptr_t old = (uintptr_t) n->children[0];
41 uintptr_t new = (uintptr_t) val;
42
43 n->children[0] = (void *) (new | (old & 1UL));
44 }
45 }
46
get_color(struct rbnode * n)47 static enum rb_color get_color(struct rbnode *n)
48 {
49 CHECK(n);
50 return ((uintptr_t)n->children[0]) & 1UL;
51 }
52
is_black(struct rbnode * n)53 static bool is_black(struct rbnode *n)
54 {
55 return get_color(n) == BLACK;
56 }
57
is_red(struct rbnode * n)58 static bool is_red(struct rbnode *n)
59 {
60 return get_color(n) == RED;
61 }
62
set_color(struct rbnode * n,enum rb_color color)63 static void set_color(struct rbnode *n, enum rb_color color)
64 {
65 CHECK(n);
66
67 uintptr_t *p = (void *) &n->children[0];
68
69 *p = (*p & ~1UL) | (uint8_t)color;
70 }
71
72 /* Searches the tree down to a node that is either identical with the
73 * "node" argument or has an empty/leaf child pointer where "node"
74 * should be, leaving all nodes found in the resulting stack. Note
75 * that tree must not be empty and that stack should be allocated to
76 * contain at least tree->max_depth entries! Returns the number of
77 * entries pushed onto the stack.
78 */
find_and_stack(struct rbtree * tree,struct rbnode * node,struct rbnode ** stack)79 static int find_and_stack(struct rbtree *tree, struct rbnode *node,
80 struct rbnode **stack)
81 {
82 int sz = 0;
83
84 stack[sz++] = tree->root;
85
86 while (stack[sz - 1] != node) {
87 uint8_t side = tree->lessthan_fn(node, stack[sz - 1]) ? 0U : 1U;
88 struct rbnode *ch = get_child(stack[sz - 1], side);
89
90 if (ch != NULL) {
91 stack[sz++] = ch;
92 } else {
93 break;
94 }
95 }
96
97 return sz;
98 }
99
z_rb_get_minmax(struct rbtree * tree,uint8_t side)100 struct rbnode *z_rb_get_minmax(struct rbtree *tree, uint8_t side)
101 {
102 struct rbnode *n;
103
104 for (n = tree->root; (n != NULL) && (get_child(n, side) != NULL);
105 n = get_child(n, side)) {
106 ;
107 }
108 return n;
109 }
110
get_side(struct rbnode * parent,struct rbnode * child)111 static uint8_t get_side(struct rbnode *parent, struct rbnode *child)
112 {
113 CHECK(get_child(parent, 0U) == child || get_child(parent, 1U) == child);
114
115 return (get_child(parent, 1U) == child) ? 1U : 0U;
116 }
117
118 /* Swaps the position of the two nodes at the top of the provided
119 * stack, modifying the stack accordingly. Does not change the color
120 * of either node. That is, it effects the following transition (or
121 * its mirror if N is on the other side of P, of course):
122 *
123 * P N
124 * N c --> a P
125 * a b b c
126 *
127 */
rotate(struct rbnode ** stack,int stacksz)128 static void rotate(struct rbnode **stack, int stacksz)
129 {
130 CHECK(stacksz >= 2);
131
132 struct rbnode *parent = stack[stacksz - 2];
133 struct rbnode *child = stack[stacksz - 1];
134 uint8_t side = get_side(parent, child);
135 struct rbnode *a = get_child(child, side);
136 struct rbnode *b = get_child(child, (side == 0U) ? 1U : 0U);
137
138 if (stacksz >= 3) {
139 struct rbnode *grandparent = stack[stacksz - 3];
140
141 set_child(grandparent, get_side(grandparent, parent), child);
142 }
143
144 set_child(child, side, a);
145 set_child(child, (side == 0U) ? 1U : 0U, parent);
146 set_child(parent, side, b);
147 stack[stacksz - 2] = child;
148 stack[stacksz - 1] = parent;
149 }
150
151 /* The node at the top of the provided stack is red, and its parent is
152 * too. Iteratively fix the tree so it becomes a valid red black tree
153 * again
154 */
fix_extra_red(struct rbnode ** stack,int stacksz)155 static void fix_extra_red(struct rbnode **stack, int stacksz)
156 {
157 while (stacksz > 1) {
158 struct rbnode *node = stack[stacksz - 1];
159 struct rbnode *parent = stack[stacksz - 2];
160
161 /* Correct child colors are a precondition of the loop */
162 CHECK((get_child(node, 0U) == NULL) ||
163 is_black(get_child(node, 0U)));
164 CHECK((get_child(node, 1U) == NULL) ||
165 is_black(get_child(node, 1U)));
166
167 if (is_black(parent)) {
168 return;
169 }
170
171 /* We are guaranteed to have a grandparent if our
172 * parent is red, as red nodes cannot be the root
173 */
174 CHECK(stacksz >= 2);
175
176 struct rbnode *grandparent = stack[stacksz - 3];
177 uint8_t side = get_side(grandparent, parent);
178 struct rbnode *aunt = get_child(grandparent,
179 (side == 0U) ? 1U : 0U);
180
181 if ((aunt != NULL) && is_red(aunt)) {
182 set_color(grandparent, RED);
183 set_color(parent, BLACK);
184 set_color(aunt, BLACK);
185
186 /* We colored the grandparent red, which might
187 * have a red parent, so continue iterating
188 * from there.
189 */
190 stacksz -= 2;
191 continue;
192 }
193
194 /* We can rotate locally to fix the whole tree. First
195 * make sure that node is on the same side of parent
196 * as parent is of grandparent.
197 */
198 uint8_t parent_side = get_side(parent, node);
199
200 if (parent_side != side) {
201 rotate(stack, stacksz);
202 }
203
204 /* Rotate the grandparent with parent, swapping colors */
205 rotate(stack, stacksz - 1);
206 set_color(stack[stacksz - 3], BLACK);
207 set_color(stack[stacksz - 2], RED);
208 return;
209 }
210
211 /* If we exit the loop, it's because our node is now the root,
212 * which must be black.
213 */
214 set_color(stack[0], BLACK);
215 }
216
rb_insert(struct rbtree * tree,struct rbnode * node)217 void rb_insert(struct rbtree *tree, struct rbnode *node)
218 {
219 set_child(node, 0U, NULL);
220 set_child(node, 1U, NULL);
221
222 if (tree->root == NULL) {
223 tree->root = node;
224 tree->max_depth = 1;
225 set_color(node, BLACK);
226 return;
227 }
228
229 #ifdef CONFIG_MISRA_SANE
230 struct rbnode **stack = &tree->iter_stack[0];
231 #else
232 struct rbnode *stack[tree->max_depth + 1];
233 #endif
234
235 int stacksz = find_and_stack(tree, node, stack);
236
237 struct rbnode *parent = stack[stacksz - 1];
238
239 uint8_t side = tree->lessthan_fn(node, parent) ? 0U : 1U;
240
241 set_child(parent, side, node);
242 set_color(node, RED);
243
244 stack[stacksz++] = node;
245 fix_extra_red(stack, stacksz);
246
247 if (stacksz > tree->max_depth) {
248 tree->max_depth = stacksz;
249 }
250
251 /* We may have rotated up into the root! */
252 tree->root = stack[0];
253 CHECK(is_black(tree->root));
254 }
255
256 /* Called for a node N (at the top of the stack) which after a
257 * deletion operation is "missing a black" in its subtree. By
258 * construction N must be black (because if it was red it would be
259 * trivially fixed by recoloring and we wouldn't be here). Fixes up
260 * the tree to preserve red/black rules. The "null_node" pointer is
261 * for situations where we are removing a childless black node. The
262 * tree munging needs a real node for simplicity, so we use it and
263 * then clean it up (replace it with a simple NULL child in the
264 * parent) when finished.
265 */
fix_missing_black(struct rbnode ** stack,int stacksz,struct rbnode * null_node)266 static void fix_missing_black(struct rbnode **stack, int stacksz,
267 struct rbnode *null_node)
268 {
269 /* Loop upward until we reach the root */
270 while (stacksz > 1) {
271 struct rbnode *c0, *c1, *inner, *outer;
272 struct rbnode *n = stack[stacksz - 1];
273 struct rbnode *parent = stack[stacksz - 2];
274 uint8_t n_side = get_side(parent, n);
275 struct rbnode *sib = get_child(parent,
276 (n_side == 0U) ? 1U : 0U);
277
278 CHECK(is_black(n));
279
280 /* Guarantee the sibling is black, rotating N down a
281 * level if needed (after rotate() our parent is the
282 * child of our previous-sibling, so N is lower in the
283 * tree)
284 */
285 if (!is_black(sib)) {
286 stack[stacksz - 1] = sib;
287 rotate(stack, stacksz);
288 set_color(parent, RED);
289 set_color(sib, BLACK);
290 stack[stacksz++] = n;
291
292 parent = stack[stacksz - 2];
293 sib = get_child(parent, (n_side == 0U) ? 1U : 0U);
294 }
295
296 CHECK(sib);
297
298 /* Cases where the sibling has only black children
299 * have simple resolutions
300 */
301 c0 = get_child(sib, 0U);
302 c1 = get_child(sib, 1U);
303 if (((c0 == NULL) || is_black(c0)) && ((c1 == NULL) ||
304 is_black(c1))) {
305 if (n == null_node) {
306 set_child(parent, n_side, NULL);
307 }
308
309 set_color(sib, RED);
310 if (is_black(parent)) {
311 /* Balance the sibling's subtree by
312 * coloring it red, then our parent
313 * has a missing black so iterate
314 * upward
315 */
316 stacksz--;
317 continue;
318 } else {
319 /* Recoloring makes the whole tree OK */
320 set_color(parent, BLACK);
321 return;
322 }
323 }
324
325 CHECK((c0 && is_red(c0)) || (c1 && is_red(c1)));
326
327 /* We know sibling has at least one red child. Fix it
328 * so that the far/outer position (i.e. on the
329 * opposite side from N) is definitely red.
330 */
331 outer = get_child(sib, (n_side == 0U) ? 1U : 0U);
332 if (!((outer != NULL) && is_red(outer))) {
333 inner = get_child(sib, n_side);
334
335 stack[stacksz - 1] = sib;
336 stack[stacksz++] = inner;
337 rotate(stack, stacksz);
338 set_color(sib, RED);
339 set_color(inner, BLACK);
340
341 /* Restore stack state to have N on the top
342 * and make sib reflect the new sibling
343 */
344 sib = stack[stacksz - 2];
345 outer = get_child(sib, (n_side == 0U) ? 1U : 0U);
346 stack[stacksz - 2] = n;
347 stacksz--;
348 }
349
350 /* Finally, the sibling must have a red child in the
351 * far/outer slot. We can rotate sib with our parent
352 * and recolor to produce a valid tree.
353 */
354 CHECK(is_red(outer));
355 set_color(sib, get_color(parent));
356 set_color(parent, BLACK);
357 set_color(outer, BLACK);
358 stack[stacksz - 1] = sib;
359 rotate(stack, stacksz);
360 if (n == null_node) {
361 set_child(parent, n_side, NULL);
362 }
363 return;
364 }
365 }
366
rb_remove(struct rbtree * tree,struct rbnode * node)367 void rb_remove(struct rbtree *tree, struct rbnode *node)
368 {
369 struct rbnode *tmp;
370 #ifdef CONFIG_MISRA_SANE
371 struct rbnode **stack = &tree->iter_stack[0];
372 #else
373 struct rbnode *stack[tree->max_depth + 1];
374 #endif
375
376 int stacksz = find_and_stack(tree, node, stack);
377
378 if (node != stack[stacksz - 1]) {
379 return;
380 }
381
382 /* We can only remove a node with zero or one child, if we
383 * have two then pick the "biggest" child of side 0 (smallest
384 * of 1 would work too) and swap our spot in the tree with
385 * that one
386 */
387 if ((get_child(node, 0U) != NULL) && (get_child(node, 1U) != NULL)) {
388 int stacksz0 = stacksz;
389 struct rbnode *hiparent, *loparent;
390 struct rbnode *node2 = get_child(node, 0U);
391
392 hiparent = (stacksz > 1) ? stack[stacksz - 2] : NULL;
393 stack[stacksz++] = node2;
394 while (get_child(node2, 1U) != NULL) {
395 node2 = get_child(node2, 1U);
396 stack[stacksz++] = node2;
397 }
398
399 loparent = stack[stacksz - 2];
400
401 /* Now swap the position of node/node2 in the tree.
402 * Design note: this is a spot where being an
403 * intrusive data structure hurts us fairly badly.
404 * The trees you see in textbooks do this by swapping
405 * the "data" pointers between the two nodes, but we
406 * have a few special cases to check. In principle
407 * this works by swapping the child pointers between
408 * the nodes and retargeting the nodes pointing to
409 * them from their parents, but: (1) the upper node
410 * may be the root of the tree and not have a parent,
411 * and (2) the lower node may be a direct child of the
412 * upper node. Remember to swap the color bits of the
413 * two nodes also. And of course we don't have parent
414 * pointers, so the stack tracking this structure
415 * needs to be swapped too!
416 */
417 if (hiparent != NULL) {
418 set_child(hiparent, get_side(hiparent, node), node2);
419 } else {
420 tree->root = node2;
421 }
422
423 if (loparent == node) {
424 set_child(node, 0U, get_child(node2, 0U));
425 set_child(node2, 0U, node);
426 } else {
427 set_child(loparent, get_side(loparent, node2), node);
428 tmp = get_child(node, 0U);
429 set_child(node, 0U, get_child(node2, 0U));
430 set_child(node2, 0U, tmp);
431 }
432
433 set_child(node2, 1U, get_child(node, 1U));
434 set_child(node, 1U, NULL);
435
436 tmp = stack[stacksz0 - 1];
437 stack[stacksz0 - 1] = stack[stacksz - 1];
438 stack[stacksz - 1] = tmp;
439
440 enum rb_color ctmp = get_color(node);
441
442 set_color(node, get_color(node2));
443 set_color(node2, ctmp);
444 }
445
446 CHECK((get_child(node, 0U) == NULL) ||
447 (get_child(node, 1U) == NULL));
448
449 struct rbnode *child = get_child(node, 0U);
450
451 if (child == NULL) {
452 child = get_child(node, 1U);
453 }
454
455 /* Removing the root */
456 if (stacksz < 2) {
457 tree->root = child;
458 if (child != NULL) {
459 set_color(child, BLACK);
460 } else {
461 tree->max_depth = 0;
462 }
463 return;
464 }
465
466 struct rbnode *parent = stack[stacksz - 2];
467
468 /* Special case: if the node to be removed is childless, then
469 * we leave it in place while we do the missing black
470 * rotations, which will replace it with a proper NULL when
471 * they isolate it.
472 */
473 if (child == NULL) {
474 if (is_black(node)) {
475 fix_missing_black(stack, stacksz, node);
476 } else {
477 /* Red childless nodes can just be dropped */
478 set_child(parent, get_side(parent, node), NULL);
479 }
480 } else {
481 set_child(parent, get_side(parent, node), child);
482
483 /* Check colors, if one was red (at least one must have been
484 * black in a valid tree), then we're done.
485 */
486 __ASSERT(is_black(node) || is_black(child), "both nodes red?!");
487 if (is_red(node) || is_red(child)) {
488 set_color(child, BLACK);
489 }
490 }
491
492 /* We may have rotated up into the root! */
493 tree->root = stack[0];
494 }
495
496 #ifndef CONFIG_MISRA_SANE
z_rb_walk(struct rbnode * node,rb_visit_t visit_fn,void * cookie)497 void z_rb_walk(struct rbnode *node, rb_visit_t visit_fn, void *cookie)
498 {
499 if (node != NULL) {
500 z_rb_walk(get_child(node, 0U), visit_fn, cookie);
501 visit_fn(node, cookie);
502 z_rb_walk(get_child(node, 1U), visit_fn, cookie);
503 }
504 }
505 #endif
506
z_rb_child(struct rbnode * node,uint8_t side)507 struct rbnode *z_rb_child(struct rbnode *node, uint8_t side)
508 {
509 return get_child(node, side);
510 }
511
z_rb_is_black(struct rbnode * node)512 int z_rb_is_black(struct rbnode *node)
513 {
514 return is_black(node);
515 }
516
rb_contains(struct rbtree * tree,struct rbnode * node)517 bool rb_contains(struct rbtree *tree, struct rbnode *node)
518 {
519 struct rbnode *n = tree->root;
520
521 while ((n != NULL) && (n != node)) {
522 n = get_child(n, tree->lessthan_fn(n, node));
523 }
524
525 return n == node;
526 }
527
528 /* Pushes the node and its chain of left-side children onto the stack
529 * in the foreach struct, returning the last node, which is the next
530 * node to iterate. By construction node will always be a right child
531 * or the root, so is_left must be false.
532 */
stack_left_limb(struct rbnode * n,struct _rb_foreach * f)533 static inline struct rbnode *stack_left_limb(struct rbnode *n,
534 struct _rb_foreach *f)
535 {
536 f->top++;
537 f->stack[f->top] = n;
538 f->is_left[f->top] = 0U;
539
540 while ((n = get_child(n, 0U)) != NULL) {
541 f->top++;
542 f->stack[f->top] = n;
543 f->is_left[f->top] = 1;
544 }
545
546 return f->stack[f->top];
547 }
548
549 /* The foreach tracking works via a dynamic stack allocated via
550 * alloca(). The current node is found in stack[top] (and its parent
551 * is thus stack[top-1]). The side of each stacked node from its
552 * parent is stored in is_left[] (i.e. if is_left[top] is true, then
553 * node/stack[top] is the left child of stack[top-1]). The special
554 * case of top == -1 indicates that the stack is uninitialized and we
555 * need to push an initial stack starting at the root.
556 */
z_rb_foreach_next(struct rbtree * tree,struct _rb_foreach * f)557 struct rbnode *z_rb_foreach_next(struct rbtree *tree, struct _rb_foreach *f)
558 {
559 struct rbnode *n;
560
561 if (tree->root == NULL) {
562 return NULL;
563 }
564
565 /* Initialization condition, pick the leftmost child of the
566 * root as our first node, initializing the stack on the way.
567 */
568 if (f->top == -1) {
569 return stack_left_limb(tree->root, f);
570 }
571
572 /* The next child from a given node is the leftmost child of
573 * it's right subtree if it has a right child
574 */
575 n = get_child(f->stack[f->top], 1U);
576 if (n != NULL) {
577 return stack_left_limb(n, f);
578 }
579
580 /* Otherwise if the node is a left child of its parent, the
581 * next node is the parent (note that the root is stacked
582 * above with is_left set to 0, so this condition still works
583 * even if node has no parent).
584 */
585 if (f->is_left[f->top] != 0U) {
586 return f->stack[--f->top];
587 }
588
589 /* If we had no left tree and are a right child then our
590 * parent was already walked, so walk up the stack looking for
591 * a left child (whose parent is unwalked, and thus next).
592 */
593 while ((f->top > 0) && (f->is_left[f->top] == 0U)) {
594 f->top--;
595 }
596
597 f->top--;
598 return (f->top >= 0) ? f->stack[f->top] : NULL;
599 }
600