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