Coverage Report

Created: 2026-03-11 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/u-boot/lib/rbtree.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0+
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
  linux/lib/rbtree.c
9
*/
10
11
#include <linux/rbtree_augmented.h>
12
#ifndef __UBOOT__
13
#include <linux/export.h>
14
#else
15
#include <ubi_uboot.h>
16
#endif
17
/*
18
 * red-black trees properties:  http://en.wikipedia.org/wiki/Rbtree
19
 *
20
 *  1) A node is either red or black
21
 *  2) The root is black
22
 *  3) All leaves (NULL) are black
23
 *  4) Both children of every red node are black
24
 *  5) Every simple path from root to leaves contains the same number
25
 *     of black nodes.
26
 *
27
 *  4 and 5 give the O(log n) guarantee, since 4 implies you cannot have two
28
 *  consecutive red nodes in a path and every red node is therefore followed by
29
 *  a black. So if B is the number of black nodes on every simple path (as per
30
 *  5), then the longest possible path due to 4 is 2B.
31
 *
32
 *  We shall indicate color with case, where black nodes are uppercase and red
33
 *  nodes will be lowercase. Unknown color nodes shall be drawn as red within
34
 *  parentheses and have some accompanying text comment.
35
 */
36
37
static inline void rb_set_black(struct rb_node *rb)
38
0
{
39
0
  rb->__rb_parent_color |= RB_BLACK;
40
0
}
41
42
static inline struct rb_node *rb_red_parent(struct rb_node *red)
43
0
{
44
0
  return (struct rb_node *)red->__rb_parent_color;
45
0
}
46
47
/*
48
 * Helper function for rotations:
49
 * - old's parent and color get assigned to new
50
 * - old gets assigned new as a parent and 'color' as a color.
51
 */
52
static inline void
53
__rb_rotate_set_parents(struct rb_node *old, struct rb_node *new,
54
      struct rb_root *root, int color)
55
0
{
56
0
  struct rb_node *parent = rb_parent(old);
57
0
  new->__rb_parent_color = old->__rb_parent_color;
58
0
  rb_set_parent_color(old, new, color);
59
0
  __rb_change_child(old, new, parent, root);
60
0
}
61
62
static __always_inline void
63
__rb_insert(struct rb_node *node, struct rb_root *root,
64
      void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
65
0
{
66
0
  struct rb_node *parent = rb_red_parent(node), *gparent, *tmp;
67
68
0
  while (true) {
69
    /*
70
     * Loop invariant: node is red
71
     *
72
     * If there is a black parent, we are done.
73
     * Otherwise, take some corrective action as we don't
74
     * want a red root or two consecutive red nodes.
75
     */
76
0
    if (!parent) {
77
0
      rb_set_parent_color(node, NULL, RB_BLACK);
78
0
      break;
79
0
    } else if (rb_is_black(parent))
80
0
      break;
81
82
0
    gparent = rb_red_parent(parent);
83
84
0
    tmp = gparent->rb_right;
85
0
    if (parent != tmp) { /* parent == gparent->rb_left */
86
0
      if (tmp && rb_is_red(tmp)) {
87
        /*
88
         * Case 1 - color flips
89
         *
90
         *       G            g
91
         *      / \          / \
92
         *     p   u  -->   P   U
93
         *    /            /
94
         *   n            N
95
         *
96
         * However, since g's parent might be red, and
97
         * 4) does not allow this, we need to recurse
98
         * at g.
99
         */
100
0
        rb_set_parent_color(tmp, gparent, RB_BLACK);
101
0
        rb_set_parent_color(parent, gparent, RB_BLACK);
102
0
        node = gparent;
103
0
        parent = rb_parent(node);
104
0
        rb_set_parent_color(node, parent, RB_RED);
105
0
        continue;
106
0
      }
107
108
0
      tmp = parent->rb_right;
109
0
      if (node == tmp) {
110
        /*
111
         * Case 2 - left rotate at parent
112
         *
113
         *      G             G
114
         *     / \           / \
115
         *    p   U  -->    n   U
116
         *     \           /
117
         *      n         p
118
         *
119
         * This still leaves us in violation of 4), the
120
         * continuation into Case 3 will fix that.
121
         */
122
0
        parent->rb_right = tmp = node->rb_left;
123
0
        node->rb_left = parent;
124
0
        if (tmp)
125
0
          rb_set_parent_color(tmp, parent,
126
0
                  RB_BLACK);
127
0
        rb_set_parent_color(parent, node, RB_RED);
128
0
        augment_rotate(parent, node);
129
0
        parent = node;
130
0
        tmp = node->rb_right;
131
0
      }
132
133
      /*
134
       * Case 3 - right rotate at gparent
135
       *
136
       *        G           P
137
       *       / \         / \
138
       *      p   U  -->  n   g
139
       *     /                 \
140
       *    n                   U
141
       */
142
0
      gparent->rb_left = tmp;  /* == parent->rb_right */
143
0
      parent->rb_right = gparent;
144
0
      if (tmp)
145
0
        rb_set_parent_color(tmp, gparent, RB_BLACK);
146
0
      __rb_rotate_set_parents(gparent, parent, root, RB_RED);
147
0
      augment_rotate(gparent, parent);
148
0
      break;
149
0
    } else {
150
0
      tmp = gparent->rb_left;
151
0
      if (tmp && rb_is_red(tmp)) {
152
        /* Case 1 - color flips */
153
0
        rb_set_parent_color(tmp, gparent, RB_BLACK);
154
0
        rb_set_parent_color(parent, gparent, RB_BLACK);
155
0
        node = gparent;
156
0
        parent = rb_parent(node);
157
0
        rb_set_parent_color(node, parent, RB_RED);
158
0
        continue;
159
0
      }
160
161
0
      tmp = parent->rb_left;
162
0
      if (node == tmp) {
163
        /* Case 2 - right rotate at parent */
164
0
        parent->rb_left = tmp = node->rb_right;
165
0
        node->rb_right = parent;
166
0
        if (tmp)
167
0
          rb_set_parent_color(tmp, parent,
168
0
                  RB_BLACK);
169
0
        rb_set_parent_color(parent, node, RB_RED);
170
0
        augment_rotate(parent, node);
171
0
        parent = node;
172
0
        tmp = node->rb_left;
173
0
      }
174
175
      /* Case 3 - left rotate at gparent */
176
0
      gparent->rb_right = tmp;  /* == parent->rb_left */
177
0
      parent->rb_left = gparent;
178
0
      if (tmp)
179
0
        rb_set_parent_color(tmp, gparent, RB_BLACK);
180
0
      __rb_rotate_set_parents(gparent, parent, root, RB_RED);
181
0
      augment_rotate(gparent, parent);
182
0
      break;
183
0
    }
184
0
  }
185
0
}
186
187
/*
188
 * Inline version for rb_erase() use - we want to be able to inline
189
 * and eliminate the dummy_rotate callback there
190
 */
191
static __always_inline void
192
____rb_erase_color(struct rb_node *parent, struct rb_root *root,
193
  void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
194
0
{
195
0
  struct rb_node *node = NULL, *sibling, *tmp1, *tmp2;
196
197
0
  while (true) {
198
    /*
199
     * Loop invariants:
200
     * - node is black (or NULL on first iteration)
201
     * - node is not the root (parent is not NULL)
202
     * - All leaf paths going through parent and node have a
203
     *   black node count that is 1 lower than other leaf paths.
204
     */
205
0
    sibling = parent->rb_right;
206
0
    if (node != sibling) { /* node == parent->rb_left */
207
0
      if (rb_is_red(sibling)) {
208
        /*
209
         * Case 1 - left rotate at parent
210
         *
211
         *     P               S
212
         *    / \             / \
213
         *   N   s    -->    p   Sr
214
         *      / \         / \
215
         *     Sl  Sr      N   Sl
216
         */
217
0
        parent->rb_right = tmp1 = sibling->rb_left;
218
0
        sibling->rb_left = parent;
219
0
        rb_set_parent_color(tmp1, parent, RB_BLACK);
220
0
        __rb_rotate_set_parents(parent, sibling, root,
221
0
              RB_RED);
222
0
        augment_rotate(parent, sibling);
223
0
        sibling = tmp1;
224
0
      }
225
0
      tmp1 = sibling->rb_right;
226
0
      if (!tmp1 || rb_is_black(tmp1)) {
227
0
        tmp2 = sibling->rb_left;
228
0
        if (!tmp2 || rb_is_black(tmp2)) {
229
          /*
230
           * Case 2 - sibling color flip
231
           * (p could be either color here)
232
           *
233
           *    (p)           (p)
234
           *    / \           / \
235
           *   N   S    -->  N   s
236
           *      / \           / \
237
           *     Sl  Sr        Sl  Sr
238
           *
239
           * This leaves us violating 5) which
240
           * can be fixed by flipping p to black
241
           * if it was red, or by recursing at p.
242
           * p is red when coming from Case 1.
243
           */
244
0
          rb_set_parent_color(sibling, parent,
245
0
                  RB_RED);
246
0
          if (rb_is_red(parent))
247
0
            rb_set_black(parent);
248
0
          else {
249
0
            node = parent;
250
0
            parent = rb_parent(node);
251
0
            if (parent)
252
0
              continue;
253
0
          }
254
0
          break;
255
0
        }
256
        /*
257
         * Case 3 - right rotate at sibling
258
         * (p could be either color here)
259
         *
260
         *   (p)           (p)
261
         *   / \           / \
262
         *  N   S    -->  N   Sl
263
         *     / \             \
264
         *    sl  Sr            s
265
         *                       \
266
         *                        Sr
267
         */
268
0
        sibling->rb_left = tmp1 = tmp2->rb_right;
269
0
        tmp2->rb_right = sibling;
270
0
        parent->rb_right = tmp2;
271
0
        if (tmp1)
272
0
          rb_set_parent_color(tmp1, sibling,
273
0
                  RB_BLACK);
274
0
        augment_rotate(sibling, tmp2);
275
0
        tmp1 = sibling;
276
0
        sibling = tmp2;
277
0
      }
278
      /*
279
       * Case 4 - left rotate at parent + color flips
280
       * (p and sl could be either color here.
281
       *  After rotation, p becomes black, s acquires
282
       *  p's color, and sl keeps its color)
283
       *
284
       *      (p)             (s)
285
       *      / \             / \
286
       *     N   S     -->   P   Sr
287
       *        / \         / \
288
       *      (sl) sr      N  (sl)
289
       */
290
0
      parent->rb_right = tmp2 = sibling->rb_left;
291
0
      sibling->rb_left = parent;
292
0
      rb_set_parent_color(tmp1, sibling, RB_BLACK);
293
0
      if (tmp2)
294
0
        rb_set_parent(tmp2, parent);
295
0
      __rb_rotate_set_parents(parent, sibling, root,
296
0
            RB_BLACK);
297
0
      augment_rotate(parent, sibling);
298
0
      break;
299
0
    } else {
300
0
      sibling = parent->rb_left;
301
0
      if (rb_is_red(sibling)) {
302
        /* Case 1 - right rotate at parent */
303
0
        parent->rb_left = tmp1 = sibling->rb_right;
304
0
        sibling->rb_right = parent;
305
0
        rb_set_parent_color(tmp1, parent, RB_BLACK);
306
0
        __rb_rotate_set_parents(parent, sibling, root,
307
0
              RB_RED);
308
0
        augment_rotate(parent, sibling);
309
0
        sibling = tmp1;
310
0
      }
311
0
      tmp1 = sibling->rb_left;
312
0
      if (!tmp1 || rb_is_black(tmp1)) {
313
0
        tmp2 = sibling->rb_right;
314
0
        if (!tmp2 || rb_is_black(tmp2)) {
315
          /* Case 2 - sibling color flip */
316
0
          rb_set_parent_color(sibling, parent,
317
0
                  RB_RED);
318
0
          if (rb_is_red(parent))
319
0
            rb_set_black(parent);
320
0
          else {
321
0
            node = parent;
322
0
            parent = rb_parent(node);
323
0
            if (parent)
324
0
              continue;
325
0
          }
326
0
          break;
327
0
        }
328
        /* Case 3 - right rotate at sibling */
329
0
        sibling->rb_right = tmp1 = tmp2->rb_left;
330
0
        tmp2->rb_left = sibling;
331
0
        parent->rb_left = tmp2;
332
0
        if (tmp1)
333
0
          rb_set_parent_color(tmp1, sibling,
334
0
                  RB_BLACK);
335
0
        augment_rotate(sibling, tmp2);
336
0
        tmp1 = sibling;
337
0
        sibling = tmp2;
338
0
      }
339
      /* Case 4 - left rotate at parent + color flips */
340
0
      parent->rb_left = tmp2 = sibling->rb_right;
341
0
      sibling->rb_right = parent;
342
0
      rb_set_parent_color(tmp1, sibling, RB_BLACK);
343
0
      if (tmp2)
344
0
        rb_set_parent(tmp2, parent);
345
0
      __rb_rotate_set_parents(parent, sibling, root,
346
0
            RB_BLACK);
347
0
      augment_rotate(parent, sibling);
348
0
      break;
349
0
    }
350
0
  }
351
0
}
352
353
/* Non-inline version for rb_erase_augmented() use */
354
void __rb_erase_color(struct rb_node *parent, struct rb_root *root,
355
  void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
356
0
{
357
0
  ____rb_erase_color(parent, root, augment_rotate);
358
0
}
359
EXPORT_SYMBOL(__rb_erase_color);
360
361
/*
362
 * Non-augmented rbtree manipulation functions.
363
 *
364
 * We use dummy augmented callbacks here, and have the compiler optimize them
365
 * out of the rb_insert_color() and rb_erase() function definitions.
366
 */
367
368
0
static inline void dummy_propagate(struct rb_node *node, struct rb_node *stop) {}
369
0
static inline void dummy_copy(struct rb_node *old, struct rb_node *new) {}
370
0
static inline void dummy_rotate(struct rb_node *old, struct rb_node *new) {}
371
372
static const struct rb_augment_callbacks dummy_callbacks = {
373
  dummy_propagate, dummy_copy, dummy_rotate
374
};
375
376
void rb_insert_color(struct rb_node *node, struct rb_root *root)
377
0
{
378
0
  __rb_insert(node, root, dummy_rotate);
379
0
}
380
EXPORT_SYMBOL(rb_insert_color);
381
382
void rb_erase(struct rb_node *node, struct rb_root *root)
383
0
{
384
0
  struct rb_node *rebalance;
385
0
  rebalance = __rb_erase_augmented(node, root, &dummy_callbacks);
386
0
  if (rebalance)
387
0
    ____rb_erase_color(rebalance, root, dummy_rotate);
388
0
}
389
EXPORT_SYMBOL(rb_erase);
390
391
/*
392
 * Augmented rbtree manipulation functions.
393
 *
394
 * This instantiates the same __always_inline functions as in the non-augmented
395
 * case, but this time with user-defined callbacks.
396
 */
397
398
void __rb_insert_augmented(struct rb_node *node, struct rb_root *root,
399
  void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
400
0
{
401
0
  __rb_insert(node, root, augment_rotate);
402
0
}
403
EXPORT_SYMBOL(__rb_insert_augmented);
404
405
/*
406
 * This function returns the first node (in sort order) of the tree.
407
 */
408
struct rb_node *rb_first(const struct rb_root *root)
409
0
{
410
0
  struct rb_node  *n;
411
412
0
  n = root->rb_node;
413
0
  if (!n)
414
0
    return NULL;
415
0
  while (n->rb_left)
416
0
    n = n->rb_left;
417
0
  return n;
418
0
}
419
EXPORT_SYMBOL(rb_first);
420
421
struct rb_node *rb_last(const struct rb_root *root)
422
0
{
423
0
  struct rb_node  *n;
424
425
0
  n = root->rb_node;
426
0
  if (!n)
427
0
    return NULL;
428
0
  while (n->rb_right)
429
0
    n = n->rb_right;
430
0
  return n;
431
0
}
432
EXPORT_SYMBOL(rb_last);
433
434
struct rb_node *rb_next(const struct rb_node *node)
435
0
{
436
0
  struct rb_node *parent;
437
438
0
  if (RB_EMPTY_NODE(node))
439
0
    return NULL;
440
441
  /*
442
   * If we have a right-hand child, go down and then left as far
443
   * as we can.
444
   */
445
0
  if (node->rb_right) {
446
0
    node = node->rb_right; 
447
0
    while (node->rb_left)
448
0
      node=node->rb_left;
449
0
    return (struct rb_node *)node;
450
0
  }
451
452
  /*
453
   * No right-hand children. Everything down and left is smaller than us,
454
   * so any 'next' node must be in the general direction of our parent.
455
   * Go up the tree; any time the ancestor is a right-hand child of its
456
   * parent, keep going up. First time it's a left-hand child of its
457
   * parent, said parent is our 'next' node.
458
   */
459
0
  while ((parent = rb_parent(node)) && node == parent->rb_right)
460
0
    node = parent;
461
462
0
  return parent;
463
0
}
464
EXPORT_SYMBOL(rb_next);
465
466
struct rb_node *rb_prev(const struct rb_node *node)
467
0
{
468
0
  struct rb_node *parent;
469
470
0
  if (RB_EMPTY_NODE(node))
471
0
    return NULL;
472
473
  /*
474
   * If we have a left-hand child, go down and then right as far
475
   * as we can.
476
   */
477
0
  if (node->rb_left) {
478
0
    node = node->rb_left; 
479
0
    while (node->rb_right)
480
0
      node=node->rb_right;
481
0
    return (struct rb_node *)node;
482
0
  }
483
484
  /*
485
   * No left-hand children. Go up till we find an ancestor which
486
   * is a right-hand child of its parent.
487
   */
488
0
  while ((parent = rb_parent(node)) && node == parent->rb_left)
489
0
    node = parent;
490
491
0
  return parent;
492
0
}
493
EXPORT_SYMBOL(rb_prev);
494
495
void rb_replace_node(struct rb_node *victim, struct rb_node *new,
496
         struct rb_root *root)
497
0
{
498
0
  struct rb_node *parent = rb_parent(victim);
499
500
  /* Set the surrounding nodes to point to the replacement */
501
0
  __rb_change_child(victim, new, parent, root);
502
0
  if (victim->rb_left)
503
0
    rb_set_parent(victim->rb_left, new);
504
0
  if (victim->rb_right)
505
0
    rb_set_parent(victim->rb_right, new);
506
507
  /* Copy the pointers/colour from the victim to the replacement */
508
0
  *new = *victim;
509
0
}
510
EXPORT_SYMBOL(rb_replace_node);
511
512
static struct rb_node *rb_left_deepest_node(const struct rb_node *node)
513
0
{
514
0
  for (;;) {
515
0
    if (node->rb_left)
516
0
      node = node->rb_left;
517
0
    else if (node->rb_right)
518
0
      node = node->rb_right;
519
0
    else
520
0
      return (struct rb_node *)node;
521
0
  }
522
0
}
523
524
struct rb_node *rb_next_postorder(const struct rb_node *node)
525
0
{
526
0
  const struct rb_node *parent;
527
0
  if (!node)
528
0
    return NULL;
529
0
  parent = rb_parent(node);
530
531
  /* If we're sitting on node, we've already seen our children */
532
0
  if (parent && node == parent->rb_left && parent->rb_right) {
533
    /* If we are the parent's left node, go to the parent's right
534
     * node then all the way down to the left */
535
0
    return rb_left_deepest_node(parent->rb_right);
536
0
  } else
537
    /* Otherwise we are the parent's right node, and the parent
538
     * should be next */
539
0
    return (struct rb_node *)parent;
540
0
}
541
EXPORT_SYMBOL(rb_next_postorder);
542
543
struct rb_node *rb_first_postorder(const struct rb_root *root)
544
0
{
545
0
  if (!root->rb_node)
546
0
    return NULL;
547
548
0
  return rb_left_deepest_node(root->rb_node);
549
0
}
550
EXPORT_SYMBOL(rb_first_postorder);