| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | Red Black Trees |
|---|
| 3 | 4 | (C) 1999 Andrea Arcangeli <andrea@suse.de> |
|---|
| 4 | 5 | (C) 2002 David Woodhouse <dwmw2@infradead.org> |
|---|
| 5 | 6 | (C) 2012 Michel Lespinasse <walken@google.com> |
|---|
| 6 | 7 | |
|---|
| 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 | 8 | |
|---|
| 21 | 9 | linux/lib/rbtree.c |
|---|
| 22 | 10 | */ |
|---|
| 23 | 11 | |
|---|
| 24 | 12 | #include <linux/rbtree_augmented.h> |
|---|
| 13 | +#include <linux/export.h> |
|---|
| 25 | 14 | |
|---|
| 26 | 15 | /* |
|---|
| 27 | | - * red-black trees properties: http://en.wikipedia.org/wiki/Rbtree |
|---|
| 16 | + * red-black trees properties: https://en.wikipedia.org/wiki/Rbtree |
|---|
| 28 | 17 | * |
|---|
| 29 | 18 | * 1) A node is either red or black |
|---|
| 30 | 19 | * 2) The root is black |
|---|
| .. | .. |
|---|
| 41 | 30 | * We shall indicate color with case, where black nodes are uppercase and red |
|---|
| 42 | 31 | * nodes will be lowercase. Unknown color nodes shall be drawn as red within |
|---|
| 43 | 32 | * parentheses and have some accompanying text comment. |
|---|
| 33 | + */ |
|---|
| 34 | + |
|---|
| 35 | +/* |
|---|
| 36 | + * Notes on lockless lookups: |
|---|
| 37 | + * |
|---|
| 38 | + * All stores to the tree structure (rb_left and rb_right) must be done using |
|---|
| 39 | + * WRITE_ONCE(). And we must not inadvertently cause (temporary) loops in the |
|---|
| 40 | + * tree structure as seen in program order. |
|---|
| 41 | + * |
|---|
| 42 | + * These two requirements will allow lockless iteration of the tree -- not |
|---|
| 43 | + * correct iteration mind you, tree rotations are not atomic so a lookup might |
|---|
| 44 | + * miss entire subtrees. |
|---|
| 45 | + * |
|---|
| 46 | + * But they do guarantee that any such traversal will only see valid elements |
|---|
| 47 | + * and that it will indeed complete -- does not get stuck in a loop. |
|---|
| 48 | + * |
|---|
| 49 | + * It also guarantees that if the lookup returns an element it is the 'correct' |
|---|
| 50 | + * one. But not returning an element does _NOT_ mean it's not present. |
|---|
| 51 | + * |
|---|
| 52 | + * NOTE: |
|---|
| 53 | + * |
|---|
| 54 | + * Stores to __rb_parent_color are not important for simple lookups so those |
|---|
| 55 | + * are left undone as of now. Nor did I check for loops involving parent |
|---|
| 56 | + * pointers. |
|---|
| 44 | 57 | */ |
|---|
| 45 | 58 | |
|---|
| 46 | 59 | static inline void rb_set_black(struct rb_node *rb) |
|---|
| .. | .. |
|---|
| 76 | 89 | |
|---|
| 77 | 90 | while (true) { |
|---|
| 78 | 91 | /* |
|---|
| 79 | | - * Loop invariant: node is red |
|---|
| 80 | | - * |
|---|
| 81 | | - * If there is a black parent, we are done. |
|---|
| 82 | | - * Otherwise, take some corrective action as we don't |
|---|
| 83 | | - * want a red root or two consecutive red nodes. |
|---|
| 92 | + * Loop invariant: node is red. |
|---|
| 84 | 93 | */ |
|---|
| 85 | | - if (!parent) { |
|---|
| 94 | + if (unlikely(!parent)) { |
|---|
| 95 | + /* |
|---|
| 96 | + * The inserted node is root. Either this is the |
|---|
| 97 | + * first node, or we recursed at Case 1 below and |
|---|
| 98 | + * are no longer violating 4). |
|---|
| 99 | + */ |
|---|
| 86 | 100 | rb_set_parent_color(node, NULL, RB_BLACK); |
|---|
| 87 | 101 | break; |
|---|
| 88 | | - } else if (rb_is_black(parent)) |
|---|
| 102 | + } |
|---|
| 103 | + |
|---|
| 104 | + /* |
|---|
| 105 | + * If there is a black parent, we are done. |
|---|
| 106 | + * Otherwise, take some corrective action as, |
|---|
| 107 | + * per 4), we don't want a red root or two |
|---|
| 108 | + * consecutive red nodes. |
|---|
| 109 | + */ |
|---|
| 110 | + if(rb_is_black(parent)) |
|---|
| 89 | 111 | break; |
|---|
| 90 | 112 | |
|---|
| 91 | 113 | gparent = rb_red_parent(parent); |
|---|
| .. | .. |
|---|
| 94 | 116 | if (parent != tmp) { /* parent == gparent->rb_left */ |
|---|
| 95 | 117 | if (tmp && rb_is_red(tmp)) { |
|---|
| 96 | 118 | /* |
|---|
| 97 | | - * Case 1 - color flips |
|---|
| 119 | + * Case 1 - node's uncle is red (color flips). |
|---|
| 98 | 120 | * |
|---|
| 99 | 121 | * G g |
|---|
| 100 | 122 | * / \ / \ |
|---|
| .. | .. |
|---|
| 117 | 139 | tmp = parent->rb_right; |
|---|
| 118 | 140 | if (node == tmp) { |
|---|
| 119 | 141 | /* |
|---|
| 120 | | - * Case 2 - left rotate at parent |
|---|
| 142 | + * Case 2 - node's uncle is black and node is |
|---|
| 143 | + * the parent's right child (left rotate at parent). |
|---|
| 121 | 144 | * |
|---|
| 122 | 145 | * G G |
|---|
| 123 | 146 | * / \ / \ |
|---|
| .. | .. |
|---|
| 128 | 151 | * This still leaves us in violation of 4), the |
|---|
| 129 | 152 | * continuation into Case 3 will fix that. |
|---|
| 130 | 153 | */ |
|---|
| 131 | | - parent->rb_right = tmp = node->rb_left; |
|---|
| 132 | | - node->rb_left = parent; |
|---|
| 154 | + tmp = node->rb_left; |
|---|
| 155 | + WRITE_ONCE(parent->rb_right, tmp); |
|---|
| 156 | + WRITE_ONCE(node->rb_left, parent); |
|---|
| 133 | 157 | if (tmp) |
|---|
| 134 | 158 | rb_set_parent_color(tmp, parent, |
|---|
| 135 | 159 | RB_BLACK); |
|---|
| .. | .. |
|---|
| 140 | 164 | } |
|---|
| 141 | 165 | |
|---|
| 142 | 166 | /* |
|---|
| 143 | | - * Case 3 - right rotate at gparent |
|---|
| 167 | + * Case 3 - node's uncle is black and node is |
|---|
| 168 | + * the parent's left child (right rotate at gparent). |
|---|
| 144 | 169 | * |
|---|
| 145 | 170 | * G P |
|---|
| 146 | 171 | * / \ / \ |
|---|
| .. | .. |
|---|
| 148 | 173 | * / \ |
|---|
| 149 | 174 | * n U |
|---|
| 150 | 175 | */ |
|---|
| 151 | | - gparent->rb_left = tmp; /* == parent->rb_right */ |
|---|
| 152 | | - parent->rb_right = gparent; |
|---|
| 176 | + WRITE_ONCE(gparent->rb_left, tmp); /* == parent->rb_right */ |
|---|
| 177 | + WRITE_ONCE(parent->rb_right, gparent); |
|---|
| 153 | 178 | if (tmp) |
|---|
| 154 | 179 | rb_set_parent_color(tmp, gparent, RB_BLACK); |
|---|
| 155 | 180 | __rb_rotate_set_parents(gparent, parent, root, RB_RED); |
|---|
| .. | .. |
|---|
| 170 | 195 | tmp = parent->rb_left; |
|---|
| 171 | 196 | if (node == tmp) { |
|---|
| 172 | 197 | /* Case 2 - right rotate at parent */ |
|---|
| 173 | | - parent->rb_left = tmp = node->rb_right; |
|---|
| 174 | | - node->rb_right = parent; |
|---|
| 198 | + tmp = node->rb_right; |
|---|
| 199 | + WRITE_ONCE(parent->rb_left, tmp); |
|---|
| 200 | + WRITE_ONCE(node->rb_right, parent); |
|---|
| 175 | 201 | if (tmp) |
|---|
| 176 | 202 | rb_set_parent_color(tmp, parent, |
|---|
| 177 | 203 | RB_BLACK); |
|---|
| .. | .. |
|---|
| 182 | 208 | } |
|---|
| 183 | 209 | |
|---|
| 184 | 210 | /* Case 3 - left rotate at gparent */ |
|---|
| 185 | | - gparent->rb_right = tmp; /* == parent->rb_left */ |
|---|
| 186 | | - parent->rb_left = gparent; |
|---|
| 211 | + WRITE_ONCE(gparent->rb_right, tmp); /* == parent->rb_left */ |
|---|
| 212 | + WRITE_ONCE(parent->rb_left, gparent); |
|---|
| 187 | 213 | if (tmp) |
|---|
| 188 | 214 | rb_set_parent_color(tmp, gparent, RB_BLACK); |
|---|
| 189 | 215 | __rb_rotate_set_parents(gparent, parent, root, RB_RED); |
|---|
| .. | .. |
|---|
| 223 | 249 | * / \ / \ |
|---|
| 224 | 250 | * Sl Sr N Sl |
|---|
| 225 | 251 | */ |
|---|
| 226 | | - parent->rb_right = tmp1 = sibling->rb_left; |
|---|
| 227 | | - sibling->rb_left = parent; |
|---|
| 252 | + tmp1 = sibling->rb_left; |
|---|
| 253 | + WRITE_ONCE(parent->rb_right, tmp1); |
|---|
| 254 | + WRITE_ONCE(sibling->rb_left, parent); |
|---|
| 228 | 255 | rb_set_parent_color(tmp1, parent, RB_BLACK); |
|---|
| 229 | 256 | __rb_rotate_set_parents(parent, sibling, root, |
|---|
| 230 | 257 | RB_RED); |
|---|
| .. | .. |
|---|
| 268 | 295 | * |
|---|
| 269 | 296 | * (p) (p) |
|---|
| 270 | 297 | * / \ / \ |
|---|
| 271 | | - * N S --> N Sl |
|---|
| 298 | + * N S --> N sl |
|---|
| 272 | 299 | * / \ \ |
|---|
| 273 | | - * sl Sr s |
|---|
| 300 | + * sl Sr S |
|---|
| 274 | 301 | * \ |
|---|
| 275 | 302 | * Sr |
|---|
| 303 | + * |
|---|
| 304 | + * Note: p might be red, and then both |
|---|
| 305 | + * p and sl are red after rotation(which |
|---|
| 306 | + * breaks property 4). This is fixed in |
|---|
| 307 | + * Case 4 (in __rb_rotate_set_parents() |
|---|
| 308 | + * which set sl the color of p |
|---|
| 309 | + * and set p RB_BLACK) |
|---|
| 310 | + * |
|---|
| 311 | + * (p) (sl) |
|---|
| 312 | + * / \ / \ |
|---|
| 313 | + * N sl --> P S |
|---|
| 314 | + * \ / \ |
|---|
| 315 | + * S N Sr |
|---|
| 316 | + * \ |
|---|
| 317 | + * Sr |
|---|
| 276 | 318 | */ |
|---|
| 277 | | - sibling->rb_left = tmp1 = tmp2->rb_right; |
|---|
| 278 | | - tmp2->rb_right = sibling; |
|---|
| 279 | | - parent->rb_right = tmp2; |
|---|
| 319 | + tmp1 = tmp2->rb_right; |
|---|
| 320 | + WRITE_ONCE(sibling->rb_left, tmp1); |
|---|
| 321 | + WRITE_ONCE(tmp2->rb_right, sibling); |
|---|
| 322 | + WRITE_ONCE(parent->rb_right, tmp2); |
|---|
| 280 | 323 | if (tmp1) |
|---|
| 281 | 324 | rb_set_parent_color(tmp1, sibling, |
|---|
| 282 | 325 | RB_BLACK); |
|---|
| .. | .. |
|---|
| 296 | 339 | * / \ / \ |
|---|
| 297 | 340 | * (sl) sr N (sl) |
|---|
| 298 | 341 | */ |
|---|
| 299 | | - parent->rb_right = tmp2 = sibling->rb_left; |
|---|
| 300 | | - sibling->rb_left = parent; |
|---|
| 342 | + tmp2 = sibling->rb_left; |
|---|
| 343 | + WRITE_ONCE(parent->rb_right, tmp2); |
|---|
| 344 | + WRITE_ONCE(sibling->rb_left, parent); |
|---|
| 301 | 345 | rb_set_parent_color(tmp1, sibling, RB_BLACK); |
|---|
| 302 | 346 | if (tmp2) |
|---|
| 303 | 347 | rb_set_parent(tmp2, parent); |
|---|
| .. | .. |
|---|
| 309 | 353 | sibling = parent->rb_left; |
|---|
| 310 | 354 | if (rb_is_red(sibling)) { |
|---|
| 311 | 355 | /* Case 1 - right rotate at parent */ |
|---|
| 312 | | - parent->rb_left = tmp1 = sibling->rb_right; |
|---|
| 313 | | - sibling->rb_right = parent; |
|---|
| 356 | + tmp1 = sibling->rb_right; |
|---|
| 357 | + WRITE_ONCE(parent->rb_left, tmp1); |
|---|
| 358 | + WRITE_ONCE(sibling->rb_right, parent); |
|---|
| 314 | 359 | rb_set_parent_color(tmp1, parent, RB_BLACK); |
|---|
| 315 | 360 | __rb_rotate_set_parents(parent, sibling, root, |
|---|
| 316 | 361 | RB_RED); |
|---|
| .. | .. |
|---|
| 334 | 379 | } |
|---|
| 335 | 380 | break; |
|---|
| 336 | 381 | } |
|---|
| 337 | | - /* Case 3 - right rotate at sibling */ |
|---|
| 338 | | - sibling->rb_right = tmp1 = tmp2->rb_left; |
|---|
| 339 | | - tmp2->rb_left = sibling; |
|---|
| 340 | | - parent->rb_left = tmp2; |
|---|
| 382 | + /* Case 3 - left rotate at sibling */ |
|---|
| 383 | + tmp1 = tmp2->rb_left; |
|---|
| 384 | + WRITE_ONCE(sibling->rb_right, tmp1); |
|---|
| 385 | + WRITE_ONCE(tmp2->rb_left, sibling); |
|---|
| 386 | + WRITE_ONCE(parent->rb_left, tmp2); |
|---|
| 341 | 387 | if (tmp1) |
|---|
| 342 | 388 | rb_set_parent_color(tmp1, sibling, |
|---|
| 343 | 389 | RB_BLACK); |
|---|
| .. | .. |
|---|
| 345 | 391 | tmp1 = sibling; |
|---|
| 346 | 392 | sibling = tmp2; |
|---|
| 347 | 393 | } |
|---|
| 348 | | - /* Case 4 - left rotate at parent + color flips */ |
|---|
| 349 | | - parent->rb_left = tmp2 = sibling->rb_right; |
|---|
| 350 | | - sibling->rb_right = parent; |
|---|
| 394 | + /* Case 4 - right rotate at parent + color flips */ |
|---|
| 395 | + tmp2 = sibling->rb_right; |
|---|
| 396 | + WRITE_ONCE(parent->rb_left, tmp2); |
|---|
| 397 | + WRITE_ONCE(sibling->rb_right, parent); |
|---|
| 351 | 398 | rb_set_parent_color(tmp1, sibling, RB_BLACK); |
|---|
| 352 | 399 | if (tmp2) |
|---|
| 353 | 400 | rb_set_parent(tmp2, parent); |
|---|
| .. | .. |
|---|
| 378 | 425 | static inline void dummy_rotate(struct rb_node *old, struct rb_node *new) {} |
|---|
| 379 | 426 | |
|---|
| 380 | 427 | static const struct rb_augment_callbacks dummy_callbacks = { |
|---|
| 381 | | - dummy_propagate, dummy_copy, dummy_rotate |
|---|
| 428 | + .propagate = dummy_propagate, |
|---|
| 429 | + .copy = dummy_copy, |
|---|
| 430 | + .rotate = dummy_rotate |
|---|
| 382 | 431 | }; |
|---|
| 383 | 432 | |
|---|
| 384 | 433 | void rb_insert_color(struct rb_node *node, struct rb_root *root) |
|---|
| .. | .. |
|---|
| 448 | 497 | if (node->rb_right) { |
|---|
| 449 | 498 | node = node->rb_right; |
|---|
| 450 | 499 | while (node->rb_left) |
|---|
| 451 | | - node=node->rb_left; |
|---|
| 500 | + node = node->rb_left; |
|---|
| 452 | 501 | return (struct rb_node *)node; |
|---|
| 453 | 502 | } |
|---|
| 454 | 503 | |
|---|
| .. | .. |
|---|
| 479 | 528 | if (node->rb_left) { |
|---|
| 480 | 529 | node = node->rb_left; |
|---|
| 481 | 530 | while (node->rb_right) |
|---|
| 482 | | - node=node->rb_right; |
|---|
| 531 | + node = node->rb_right; |
|---|
| 483 | 532 | return (struct rb_node *)node; |
|---|
| 484 | 533 | } |
|---|
| 485 | 534 | |
|---|
| .. | .. |
|---|
| 498 | 547 | { |
|---|
| 499 | 548 | struct rb_node *parent = rb_parent(victim); |
|---|
| 500 | 549 | |
|---|
| 550 | + /* Copy the pointers/colour from the victim to the replacement */ |
|---|
| 551 | + *new = *victim; |
|---|
| 552 | + |
|---|
| 501 | 553 | /* Set the surrounding nodes to point to the replacement */ |
|---|
| 502 | | - __rb_change_child(victim, new, parent, root); |
|---|
| 503 | 554 | if (victim->rb_left) |
|---|
| 504 | 555 | rb_set_parent(victim->rb_left, new); |
|---|
| 505 | 556 | if (victim->rb_right) |
|---|
| 506 | 557 | rb_set_parent(victim->rb_right, new); |
|---|
| 507 | | - |
|---|
| 508 | | - /* Copy the pointers/colour from the victim to the replacement */ |
|---|
| 509 | | - *new = *victim; |
|---|
| 558 | + __rb_change_child(victim, new, parent, root); |
|---|
| 510 | 559 | } |
|---|
| 511 | 560 | |
|---|
| 512 | 561 | static struct rb_node *rb_left_deepest_node(const struct rb_node *node) |
|---|