11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 23f735377SArnaldo Carvalho de Melo /* 33f735377SArnaldo Carvalho de Melo Red Black Trees 43f735377SArnaldo Carvalho de Melo (C) 1999 Andrea Arcangeli <andrea@suse.de> 53f735377SArnaldo Carvalho de Melo (C) 2002 David Woodhouse <dwmw2@infradead.org> 63f735377SArnaldo Carvalho de Melo (C) 2012 Michel Lespinasse <walken@google.com> 73f735377SArnaldo Carvalho de Melo 83f735377SArnaldo Carvalho de Melo 93f735377SArnaldo Carvalho de Melo linux/lib/rbtree.c 103f735377SArnaldo Carvalho de Melo */ 113f735377SArnaldo Carvalho de Melo 123f735377SArnaldo Carvalho de Melo #include <linux/rbtree_augmented.h> 133aef2cadSDavidlohr Bueso #include <linux/export.h> 143f735377SArnaldo Carvalho de Melo 153f735377SArnaldo Carvalho de Melo /* 16*79e3ea5aSAlexander A. Klimov * red-black trees properties: https://en.wikipedia.org/wiki/Rbtree 173f735377SArnaldo Carvalho de Melo * 183f735377SArnaldo Carvalho de Melo * 1) A node is either red or black 193f735377SArnaldo Carvalho de Melo * 2) The root is black 203f735377SArnaldo Carvalho de Melo * 3) All leaves (NULL) are black 213f735377SArnaldo Carvalho de Melo * 4) Both children of every red node are black 223f735377SArnaldo Carvalho de Melo * 5) Every simple path from root to leaves contains the same number 233f735377SArnaldo Carvalho de Melo * of black nodes. 243f735377SArnaldo Carvalho de Melo * 253f735377SArnaldo Carvalho de Melo * 4 and 5 give the O(log n) guarantee, since 4 implies you cannot have two 263f735377SArnaldo Carvalho de Melo * consecutive red nodes in a path and every red node is therefore followed by 273f735377SArnaldo Carvalho de Melo * a black. So if B is the number of black nodes on every simple path (as per 283f735377SArnaldo Carvalho de Melo * 5), then the longest possible path due to 4 is 2B. 293f735377SArnaldo Carvalho de Melo * 303f735377SArnaldo Carvalho de Melo * We shall indicate color with case, where black nodes are uppercase and red 313f735377SArnaldo Carvalho de Melo * nodes will be lowercase. Unknown color nodes shall be drawn as red within 323f735377SArnaldo Carvalho de Melo * parentheses and have some accompanying text comment. 333f735377SArnaldo Carvalho de Melo */ 343f735377SArnaldo Carvalho de Melo 353aef2cadSDavidlohr Bueso /* 363aef2cadSDavidlohr Bueso * Notes on lockless lookups: 373aef2cadSDavidlohr Bueso * 383aef2cadSDavidlohr Bueso * All stores to the tree structure (rb_left and rb_right) must be done using 393aef2cadSDavidlohr Bueso * WRITE_ONCE(). And we must not inadvertently cause (temporary) loops in the 403aef2cadSDavidlohr Bueso * tree structure as seen in program order. 413aef2cadSDavidlohr Bueso * 423aef2cadSDavidlohr Bueso * These two requirements will allow lockless iteration of the tree -- not 433aef2cadSDavidlohr Bueso * correct iteration mind you, tree rotations are not atomic so a lookup might 443aef2cadSDavidlohr Bueso * miss entire subtrees. 453aef2cadSDavidlohr Bueso * 463aef2cadSDavidlohr Bueso * But they do guarantee that any such traversal will only see valid elements 473aef2cadSDavidlohr Bueso * and that it will indeed complete -- does not get stuck in a loop. 483aef2cadSDavidlohr Bueso * 493aef2cadSDavidlohr Bueso * It also guarantees that if the lookup returns an element it is the 'correct' 503aef2cadSDavidlohr Bueso * one. But not returning an element does _NOT_ mean it's not present. 513aef2cadSDavidlohr Bueso * 523aef2cadSDavidlohr Bueso * NOTE: 533aef2cadSDavidlohr Bueso * 543aef2cadSDavidlohr Bueso * Stores to __rb_parent_color are not important for simple lookups so those 553aef2cadSDavidlohr Bueso * are left undone as of now. Nor did I check for loops involving parent 563aef2cadSDavidlohr Bueso * pointers. 573aef2cadSDavidlohr Bueso */ 583aef2cadSDavidlohr Bueso 593f735377SArnaldo Carvalho de Melo static inline void rb_set_black(struct rb_node *rb) 603f735377SArnaldo Carvalho de Melo { 613f735377SArnaldo Carvalho de Melo rb->__rb_parent_color |= RB_BLACK; 623f735377SArnaldo Carvalho de Melo } 633f735377SArnaldo Carvalho de Melo 643f735377SArnaldo Carvalho de Melo static inline struct rb_node *rb_red_parent(struct rb_node *red) 653f735377SArnaldo Carvalho de Melo { 663f735377SArnaldo Carvalho de Melo return (struct rb_node *)red->__rb_parent_color; 673f735377SArnaldo Carvalho de Melo } 683f735377SArnaldo Carvalho de Melo 693f735377SArnaldo Carvalho de Melo /* 703f735377SArnaldo Carvalho de Melo * Helper function for rotations: 713f735377SArnaldo Carvalho de Melo * - old's parent and color get assigned to new 723f735377SArnaldo Carvalho de Melo * - old gets assigned new as a parent and 'color' as a color. 733f735377SArnaldo Carvalho de Melo */ 743f735377SArnaldo Carvalho de Melo static inline void 753f735377SArnaldo Carvalho de Melo __rb_rotate_set_parents(struct rb_node *old, struct rb_node *new, 763f735377SArnaldo Carvalho de Melo struct rb_root *root, int color) 773f735377SArnaldo Carvalho de Melo { 783f735377SArnaldo Carvalho de Melo struct rb_node *parent = rb_parent(old); 793f735377SArnaldo Carvalho de Melo new->__rb_parent_color = old->__rb_parent_color; 803f735377SArnaldo Carvalho de Melo rb_set_parent_color(old, new, color); 813f735377SArnaldo Carvalho de Melo __rb_change_child(old, new, parent, root); 823f735377SArnaldo Carvalho de Melo } 833f735377SArnaldo Carvalho de Melo 843f735377SArnaldo Carvalho de Melo static __always_inline void 853f735377SArnaldo Carvalho de Melo __rb_insert(struct rb_node *node, struct rb_root *root, 863f735377SArnaldo Carvalho de Melo void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) 873f735377SArnaldo Carvalho de Melo { 883f735377SArnaldo Carvalho de Melo struct rb_node *parent = rb_red_parent(node), *gparent, *tmp; 893f735377SArnaldo Carvalho de Melo 903f735377SArnaldo Carvalho de Melo while (true) { 913f735377SArnaldo Carvalho de Melo /* 923aef2cadSDavidlohr Bueso * Loop invariant: node is red. 933f735377SArnaldo Carvalho de Melo */ 943aef2cadSDavidlohr Bueso if (unlikely(!parent)) { 953aef2cadSDavidlohr Bueso /* 963aef2cadSDavidlohr Bueso * The inserted node is root. Either this is the 973aef2cadSDavidlohr Bueso * first node, or we recursed at Case 1 below and 983aef2cadSDavidlohr Bueso * are no longer violating 4). 993aef2cadSDavidlohr Bueso */ 1003f735377SArnaldo Carvalho de Melo rb_set_parent_color(node, NULL, RB_BLACK); 1013f735377SArnaldo Carvalho de Melo break; 1023aef2cadSDavidlohr Bueso } 1033aef2cadSDavidlohr Bueso 1043aef2cadSDavidlohr Bueso /* 1053aef2cadSDavidlohr Bueso * If there is a black parent, we are done. 1063aef2cadSDavidlohr Bueso * Otherwise, take some corrective action as, 1073aef2cadSDavidlohr Bueso * per 4), we don't want a red root or two 1083aef2cadSDavidlohr Bueso * consecutive red nodes. 1093aef2cadSDavidlohr Bueso */ 1103aef2cadSDavidlohr Bueso if(rb_is_black(parent)) 1113f735377SArnaldo Carvalho de Melo break; 1123f735377SArnaldo Carvalho de Melo 1133f735377SArnaldo Carvalho de Melo gparent = rb_red_parent(parent); 1143f735377SArnaldo Carvalho de Melo 1153f735377SArnaldo Carvalho de Melo tmp = gparent->rb_right; 1163f735377SArnaldo Carvalho de Melo if (parent != tmp) { /* parent == gparent->rb_left */ 1173f735377SArnaldo Carvalho de Melo if (tmp && rb_is_red(tmp)) { 1183f735377SArnaldo Carvalho de Melo /* 1193aef2cadSDavidlohr Bueso * Case 1 - node's uncle is red (color flips). 1203f735377SArnaldo Carvalho de Melo * 1213f735377SArnaldo Carvalho de Melo * G g 1223f735377SArnaldo Carvalho de Melo * / \ / \ 1233f735377SArnaldo Carvalho de Melo * p u --> P U 1243f735377SArnaldo Carvalho de Melo * / / 1253f735377SArnaldo Carvalho de Melo * n n 1263f735377SArnaldo Carvalho de Melo * 1273f735377SArnaldo Carvalho de Melo * However, since g's parent might be red, and 1283f735377SArnaldo Carvalho de Melo * 4) does not allow this, we need to recurse 1293f735377SArnaldo Carvalho de Melo * at g. 1303f735377SArnaldo Carvalho de Melo */ 1313f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp, gparent, RB_BLACK); 1323f735377SArnaldo Carvalho de Melo rb_set_parent_color(parent, gparent, RB_BLACK); 1333f735377SArnaldo Carvalho de Melo node = gparent; 1343f735377SArnaldo Carvalho de Melo parent = rb_parent(node); 1353f735377SArnaldo Carvalho de Melo rb_set_parent_color(node, parent, RB_RED); 1363f735377SArnaldo Carvalho de Melo continue; 1373f735377SArnaldo Carvalho de Melo } 1383f735377SArnaldo Carvalho de Melo 1393f735377SArnaldo Carvalho de Melo tmp = parent->rb_right; 1403f735377SArnaldo Carvalho de Melo if (node == tmp) { 1413f735377SArnaldo Carvalho de Melo /* 1423aef2cadSDavidlohr Bueso * Case 2 - node's uncle is black and node is 1433aef2cadSDavidlohr Bueso * the parent's right child (left rotate at parent). 1443f735377SArnaldo Carvalho de Melo * 1453f735377SArnaldo Carvalho de Melo * G G 1463f735377SArnaldo Carvalho de Melo * / \ / \ 1473f735377SArnaldo Carvalho de Melo * p U --> n U 1483f735377SArnaldo Carvalho de Melo * \ / 1493f735377SArnaldo Carvalho de Melo * n p 1503f735377SArnaldo Carvalho de Melo * 1513f735377SArnaldo Carvalho de Melo * This still leaves us in violation of 4), the 1523f735377SArnaldo Carvalho de Melo * continuation into Case 3 will fix that. 1533f735377SArnaldo Carvalho de Melo */ 1543aef2cadSDavidlohr Bueso tmp = node->rb_left; 1553aef2cadSDavidlohr Bueso WRITE_ONCE(parent->rb_right, tmp); 1563aef2cadSDavidlohr Bueso WRITE_ONCE(node->rb_left, parent); 1573f735377SArnaldo Carvalho de Melo if (tmp) 1583f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp, parent, 1593f735377SArnaldo Carvalho de Melo RB_BLACK); 1603f735377SArnaldo Carvalho de Melo rb_set_parent_color(parent, node, RB_RED); 1613f735377SArnaldo Carvalho de Melo augment_rotate(parent, node); 1623f735377SArnaldo Carvalho de Melo parent = node; 1633f735377SArnaldo Carvalho de Melo tmp = node->rb_right; 1643f735377SArnaldo Carvalho de Melo } 1653f735377SArnaldo Carvalho de Melo 1663f735377SArnaldo Carvalho de Melo /* 1673aef2cadSDavidlohr Bueso * Case 3 - node's uncle is black and node is 1683aef2cadSDavidlohr Bueso * the parent's left child (right rotate at gparent). 1693f735377SArnaldo Carvalho de Melo * 1703f735377SArnaldo Carvalho de Melo * G P 1713f735377SArnaldo Carvalho de Melo * / \ / \ 1723f735377SArnaldo Carvalho de Melo * p U --> n g 1733f735377SArnaldo Carvalho de Melo * / \ 1743f735377SArnaldo Carvalho de Melo * n U 1753f735377SArnaldo Carvalho de Melo */ 1763aef2cadSDavidlohr Bueso WRITE_ONCE(gparent->rb_left, tmp); /* == parent->rb_right */ 1773aef2cadSDavidlohr Bueso WRITE_ONCE(parent->rb_right, gparent); 1783f735377SArnaldo Carvalho de Melo if (tmp) 1793f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp, gparent, RB_BLACK); 1803f735377SArnaldo Carvalho de Melo __rb_rotate_set_parents(gparent, parent, root, RB_RED); 1813f735377SArnaldo Carvalho de Melo augment_rotate(gparent, parent); 1823f735377SArnaldo Carvalho de Melo break; 1833f735377SArnaldo Carvalho de Melo } else { 1843f735377SArnaldo Carvalho de Melo tmp = gparent->rb_left; 1853f735377SArnaldo Carvalho de Melo if (tmp && rb_is_red(tmp)) { 1863f735377SArnaldo Carvalho de Melo /* Case 1 - color flips */ 1873f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp, gparent, RB_BLACK); 1883f735377SArnaldo Carvalho de Melo rb_set_parent_color(parent, gparent, RB_BLACK); 1893f735377SArnaldo Carvalho de Melo node = gparent; 1903f735377SArnaldo Carvalho de Melo parent = rb_parent(node); 1913f735377SArnaldo Carvalho de Melo rb_set_parent_color(node, parent, RB_RED); 1923f735377SArnaldo Carvalho de Melo continue; 1933f735377SArnaldo Carvalho de Melo } 1943f735377SArnaldo Carvalho de Melo 1953f735377SArnaldo Carvalho de Melo tmp = parent->rb_left; 1963f735377SArnaldo Carvalho de Melo if (node == tmp) { 1973f735377SArnaldo Carvalho de Melo /* Case 2 - right rotate at parent */ 1983aef2cadSDavidlohr Bueso tmp = node->rb_right; 1993aef2cadSDavidlohr Bueso WRITE_ONCE(parent->rb_left, tmp); 2003aef2cadSDavidlohr Bueso WRITE_ONCE(node->rb_right, parent); 2013f735377SArnaldo Carvalho de Melo if (tmp) 2023f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp, parent, 2033f735377SArnaldo Carvalho de Melo RB_BLACK); 2043f735377SArnaldo Carvalho de Melo rb_set_parent_color(parent, node, RB_RED); 2053f735377SArnaldo Carvalho de Melo augment_rotate(parent, node); 2063f735377SArnaldo Carvalho de Melo parent = node; 2073f735377SArnaldo Carvalho de Melo tmp = node->rb_left; 2083f735377SArnaldo Carvalho de Melo } 2093f735377SArnaldo Carvalho de Melo 2103f735377SArnaldo Carvalho de Melo /* Case 3 - left rotate at gparent */ 2113aef2cadSDavidlohr Bueso WRITE_ONCE(gparent->rb_right, tmp); /* == parent->rb_left */ 2123aef2cadSDavidlohr Bueso WRITE_ONCE(parent->rb_left, gparent); 2133f735377SArnaldo Carvalho de Melo if (tmp) 2143f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp, gparent, RB_BLACK); 2153f735377SArnaldo Carvalho de Melo __rb_rotate_set_parents(gparent, parent, root, RB_RED); 2163f735377SArnaldo Carvalho de Melo augment_rotate(gparent, parent); 2173f735377SArnaldo Carvalho de Melo break; 2183f735377SArnaldo Carvalho de Melo } 2193f735377SArnaldo Carvalho de Melo } 2203f735377SArnaldo Carvalho de Melo } 2213f735377SArnaldo Carvalho de Melo 2223f735377SArnaldo Carvalho de Melo /* 2233f735377SArnaldo Carvalho de Melo * Inline version for rb_erase() use - we want to be able to inline 2243f735377SArnaldo Carvalho de Melo * and eliminate the dummy_rotate callback there 2253f735377SArnaldo Carvalho de Melo */ 2263f735377SArnaldo Carvalho de Melo static __always_inline void 2273f735377SArnaldo Carvalho de Melo ____rb_erase_color(struct rb_node *parent, struct rb_root *root, 2283f735377SArnaldo Carvalho de Melo void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) 2293f735377SArnaldo Carvalho de Melo { 2303f735377SArnaldo Carvalho de Melo struct rb_node *node = NULL, *sibling, *tmp1, *tmp2; 2313f735377SArnaldo Carvalho de Melo 2323f735377SArnaldo Carvalho de Melo while (true) { 2333f735377SArnaldo Carvalho de Melo /* 2343f735377SArnaldo Carvalho de Melo * Loop invariants: 2353f735377SArnaldo Carvalho de Melo * - node is black (or NULL on first iteration) 2363f735377SArnaldo Carvalho de Melo * - node is not the root (parent is not NULL) 2373f735377SArnaldo Carvalho de Melo * - All leaf paths going through parent and node have a 2383f735377SArnaldo Carvalho de Melo * black node count that is 1 lower than other leaf paths. 2393f735377SArnaldo Carvalho de Melo */ 2403f735377SArnaldo Carvalho de Melo sibling = parent->rb_right; 2413f735377SArnaldo Carvalho de Melo if (node != sibling) { /* node == parent->rb_left */ 2423f735377SArnaldo Carvalho de Melo if (rb_is_red(sibling)) { 2433f735377SArnaldo Carvalho de Melo /* 2443f735377SArnaldo Carvalho de Melo * Case 1 - left rotate at parent 2453f735377SArnaldo Carvalho de Melo * 2463f735377SArnaldo Carvalho de Melo * P S 2473f735377SArnaldo Carvalho de Melo * / \ / \ 2483f735377SArnaldo Carvalho de Melo * N s --> p Sr 2493f735377SArnaldo Carvalho de Melo * / \ / \ 2503f735377SArnaldo Carvalho de Melo * Sl Sr N Sl 2513f735377SArnaldo Carvalho de Melo */ 2523aef2cadSDavidlohr Bueso tmp1 = sibling->rb_left; 2533aef2cadSDavidlohr Bueso WRITE_ONCE(parent->rb_right, tmp1); 2543aef2cadSDavidlohr Bueso WRITE_ONCE(sibling->rb_left, parent); 2553f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp1, parent, RB_BLACK); 2563f735377SArnaldo Carvalho de Melo __rb_rotate_set_parents(parent, sibling, root, 2573f735377SArnaldo Carvalho de Melo RB_RED); 2583f735377SArnaldo Carvalho de Melo augment_rotate(parent, sibling); 2593f735377SArnaldo Carvalho de Melo sibling = tmp1; 2603f735377SArnaldo Carvalho de Melo } 2613f735377SArnaldo Carvalho de Melo tmp1 = sibling->rb_right; 2623f735377SArnaldo Carvalho de Melo if (!tmp1 || rb_is_black(tmp1)) { 2633f735377SArnaldo Carvalho de Melo tmp2 = sibling->rb_left; 2643f735377SArnaldo Carvalho de Melo if (!tmp2 || rb_is_black(tmp2)) { 2653f735377SArnaldo Carvalho de Melo /* 2663f735377SArnaldo Carvalho de Melo * Case 2 - sibling color flip 2673f735377SArnaldo Carvalho de Melo * (p could be either color here) 2683f735377SArnaldo Carvalho de Melo * 2693f735377SArnaldo Carvalho de Melo * (p) (p) 2703f735377SArnaldo Carvalho de Melo * / \ / \ 2713f735377SArnaldo Carvalho de Melo * N S --> N s 2723f735377SArnaldo Carvalho de Melo * / \ / \ 2733f735377SArnaldo Carvalho de Melo * Sl Sr Sl Sr 2743f735377SArnaldo Carvalho de Melo * 2753f735377SArnaldo Carvalho de Melo * This leaves us violating 5) which 2763f735377SArnaldo Carvalho de Melo * can be fixed by flipping p to black 2773f735377SArnaldo Carvalho de Melo * if it was red, or by recursing at p. 2783f735377SArnaldo Carvalho de Melo * p is red when coming from Case 1. 2793f735377SArnaldo Carvalho de Melo */ 2803f735377SArnaldo Carvalho de Melo rb_set_parent_color(sibling, parent, 2813f735377SArnaldo Carvalho de Melo RB_RED); 2823f735377SArnaldo Carvalho de Melo if (rb_is_red(parent)) 2833f735377SArnaldo Carvalho de Melo rb_set_black(parent); 2843f735377SArnaldo Carvalho de Melo else { 2853f735377SArnaldo Carvalho de Melo node = parent; 2863f735377SArnaldo Carvalho de Melo parent = rb_parent(node); 2873f735377SArnaldo Carvalho de Melo if (parent) 2883f735377SArnaldo Carvalho de Melo continue; 2893f735377SArnaldo Carvalho de Melo } 2903f735377SArnaldo Carvalho de Melo break; 2913f735377SArnaldo Carvalho de Melo } 2923f735377SArnaldo Carvalho de Melo /* 2933f735377SArnaldo Carvalho de Melo * Case 3 - right rotate at sibling 2943f735377SArnaldo Carvalho de Melo * (p could be either color here) 2953f735377SArnaldo Carvalho de Melo * 2963f735377SArnaldo Carvalho de Melo * (p) (p) 2973f735377SArnaldo Carvalho de Melo * / \ / \ 2983aef2cadSDavidlohr Bueso * N S --> N sl 2993f735377SArnaldo Carvalho de Melo * / \ \ 3003aef2cadSDavidlohr Bueso * sl Sr S 3013aef2cadSDavidlohr Bueso * \ 3023aef2cadSDavidlohr Bueso * Sr 3033aef2cadSDavidlohr Bueso * 3043aef2cadSDavidlohr Bueso * Note: p might be red, and then both 3053aef2cadSDavidlohr Bueso * p and sl are red after rotation(which 3063aef2cadSDavidlohr Bueso * breaks property 4). This is fixed in 3073aef2cadSDavidlohr Bueso * Case 4 (in __rb_rotate_set_parents() 3083aef2cadSDavidlohr Bueso * which set sl the color of p 3093aef2cadSDavidlohr Bueso * and set p RB_BLACK) 3103aef2cadSDavidlohr Bueso * 3113aef2cadSDavidlohr Bueso * (p) (sl) 3123aef2cadSDavidlohr Bueso * / \ / \ 3133aef2cadSDavidlohr Bueso * N sl --> P S 3143aef2cadSDavidlohr Bueso * \ / \ 3153aef2cadSDavidlohr Bueso * S N Sr 3163f735377SArnaldo Carvalho de Melo * \ 3173f735377SArnaldo Carvalho de Melo * Sr 3183f735377SArnaldo Carvalho de Melo */ 3193aef2cadSDavidlohr Bueso tmp1 = tmp2->rb_right; 3203aef2cadSDavidlohr Bueso WRITE_ONCE(sibling->rb_left, tmp1); 3213aef2cadSDavidlohr Bueso WRITE_ONCE(tmp2->rb_right, sibling); 3223aef2cadSDavidlohr Bueso WRITE_ONCE(parent->rb_right, tmp2); 3233f735377SArnaldo Carvalho de Melo if (tmp1) 3243f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp1, sibling, 3253f735377SArnaldo Carvalho de Melo RB_BLACK); 3263f735377SArnaldo Carvalho de Melo augment_rotate(sibling, tmp2); 3273f735377SArnaldo Carvalho de Melo tmp1 = sibling; 3283f735377SArnaldo Carvalho de Melo sibling = tmp2; 3293f735377SArnaldo Carvalho de Melo } 3303f735377SArnaldo Carvalho de Melo /* 3313f735377SArnaldo Carvalho de Melo * Case 4 - left rotate at parent + color flips 3323f735377SArnaldo Carvalho de Melo * (p and sl could be either color here. 3333f735377SArnaldo Carvalho de Melo * After rotation, p becomes black, s acquires 3343f735377SArnaldo Carvalho de Melo * p's color, and sl keeps its color) 3353f735377SArnaldo Carvalho de Melo * 3363f735377SArnaldo Carvalho de Melo * (p) (s) 3373f735377SArnaldo Carvalho de Melo * / \ / \ 3383f735377SArnaldo Carvalho de Melo * N S --> P Sr 3393f735377SArnaldo Carvalho de Melo * / \ / \ 3403f735377SArnaldo Carvalho de Melo * (sl) sr N (sl) 3413f735377SArnaldo Carvalho de Melo */ 3423aef2cadSDavidlohr Bueso tmp2 = sibling->rb_left; 3433aef2cadSDavidlohr Bueso WRITE_ONCE(parent->rb_right, tmp2); 3443aef2cadSDavidlohr Bueso WRITE_ONCE(sibling->rb_left, parent); 3453f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp1, sibling, RB_BLACK); 3463f735377SArnaldo Carvalho de Melo if (tmp2) 3473f735377SArnaldo Carvalho de Melo rb_set_parent(tmp2, parent); 3483f735377SArnaldo Carvalho de Melo __rb_rotate_set_parents(parent, sibling, root, 3493f735377SArnaldo Carvalho de Melo RB_BLACK); 3503f735377SArnaldo Carvalho de Melo augment_rotate(parent, sibling); 3513f735377SArnaldo Carvalho de Melo break; 3523f735377SArnaldo Carvalho de Melo } else { 3533f735377SArnaldo Carvalho de Melo sibling = parent->rb_left; 3543f735377SArnaldo Carvalho de Melo if (rb_is_red(sibling)) { 3553f735377SArnaldo Carvalho de Melo /* Case 1 - right rotate at parent */ 3563aef2cadSDavidlohr Bueso tmp1 = sibling->rb_right; 3573aef2cadSDavidlohr Bueso WRITE_ONCE(parent->rb_left, tmp1); 3583aef2cadSDavidlohr Bueso WRITE_ONCE(sibling->rb_right, parent); 3593f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp1, parent, RB_BLACK); 3603f735377SArnaldo Carvalho de Melo __rb_rotate_set_parents(parent, sibling, root, 3613f735377SArnaldo Carvalho de Melo RB_RED); 3623f735377SArnaldo Carvalho de Melo augment_rotate(parent, sibling); 3633f735377SArnaldo Carvalho de Melo sibling = tmp1; 3643f735377SArnaldo Carvalho de Melo } 3653f735377SArnaldo Carvalho de Melo tmp1 = sibling->rb_left; 3663f735377SArnaldo Carvalho de Melo if (!tmp1 || rb_is_black(tmp1)) { 3673f735377SArnaldo Carvalho de Melo tmp2 = sibling->rb_right; 3683f735377SArnaldo Carvalho de Melo if (!tmp2 || rb_is_black(tmp2)) { 3693f735377SArnaldo Carvalho de Melo /* Case 2 - sibling color flip */ 3703f735377SArnaldo Carvalho de Melo rb_set_parent_color(sibling, parent, 3713f735377SArnaldo Carvalho de Melo RB_RED); 3723f735377SArnaldo Carvalho de Melo if (rb_is_red(parent)) 3733f735377SArnaldo Carvalho de Melo rb_set_black(parent); 3743f735377SArnaldo Carvalho de Melo else { 3753f735377SArnaldo Carvalho de Melo node = parent; 3763f735377SArnaldo Carvalho de Melo parent = rb_parent(node); 3773f735377SArnaldo Carvalho de Melo if (parent) 3783f735377SArnaldo Carvalho de Melo continue; 3793f735377SArnaldo Carvalho de Melo } 3803f735377SArnaldo Carvalho de Melo break; 3813f735377SArnaldo Carvalho de Melo } 3823aef2cadSDavidlohr Bueso /* Case 3 - left rotate at sibling */ 3833aef2cadSDavidlohr Bueso tmp1 = tmp2->rb_left; 3843aef2cadSDavidlohr Bueso WRITE_ONCE(sibling->rb_right, tmp1); 3853aef2cadSDavidlohr Bueso WRITE_ONCE(tmp2->rb_left, sibling); 3863aef2cadSDavidlohr Bueso WRITE_ONCE(parent->rb_left, tmp2); 3873f735377SArnaldo Carvalho de Melo if (tmp1) 3883f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp1, sibling, 3893f735377SArnaldo Carvalho de Melo RB_BLACK); 3903f735377SArnaldo Carvalho de Melo augment_rotate(sibling, tmp2); 3913f735377SArnaldo Carvalho de Melo tmp1 = sibling; 3923f735377SArnaldo Carvalho de Melo sibling = tmp2; 3933f735377SArnaldo Carvalho de Melo } 3943aef2cadSDavidlohr Bueso /* Case 4 - right rotate at parent + color flips */ 3953aef2cadSDavidlohr Bueso tmp2 = sibling->rb_right; 3963aef2cadSDavidlohr Bueso WRITE_ONCE(parent->rb_left, tmp2); 3973aef2cadSDavidlohr Bueso WRITE_ONCE(sibling->rb_right, parent); 3983f735377SArnaldo Carvalho de Melo rb_set_parent_color(tmp1, sibling, RB_BLACK); 3993f735377SArnaldo Carvalho de Melo if (tmp2) 4003f735377SArnaldo Carvalho de Melo rb_set_parent(tmp2, parent); 4013f735377SArnaldo Carvalho de Melo __rb_rotate_set_parents(parent, sibling, root, 4023f735377SArnaldo Carvalho de Melo RB_BLACK); 4033f735377SArnaldo Carvalho de Melo augment_rotate(parent, sibling); 4043f735377SArnaldo Carvalho de Melo break; 4053f735377SArnaldo Carvalho de Melo } 4063f735377SArnaldo Carvalho de Melo } 4073f735377SArnaldo Carvalho de Melo } 4083f735377SArnaldo Carvalho de Melo 4093f735377SArnaldo Carvalho de Melo /* Non-inline version for rb_erase_augmented() use */ 4103f735377SArnaldo Carvalho de Melo void __rb_erase_color(struct rb_node *parent, struct rb_root *root, 4113f735377SArnaldo Carvalho de Melo void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) 4123f735377SArnaldo Carvalho de Melo { 4133f735377SArnaldo Carvalho de Melo ____rb_erase_color(parent, root, augment_rotate); 4143f735377SArnaldo Carvalho de Melo } 4153f735377SArnaldo Carvalho de Melo 4163f735377SArnaldo Carvalho de Melo /* 4173f735377SArnaldo Carvalho de Melo * Non-augmented rbtree manipulation functions. 4183f735377SArnaldo Carvalho de Melo * 4193f735377SArnaldo Carvalho de Melo * We use dummy augmented callbacks here, and have the compiler optimize them 4203f735377SArnaldo Carvalho de Melo * out of the rb_insert_color() and rb_erase() function definitions. 4213f735377SArnaldo Carvalho de Melo */ 4223f735377SArnaldo Carvalho de Melo 4233f735377SArnaldo Carvalho de Melo static inline void dummy_propagate(struct rb_node *node, struct rb_node *stop) {} 4243f735377SArnaldo Carvalho de Melo static inline void dummy_copy(struct rb_node *old, struct rb_node *new) {} 4253f735377SArnaldo Carvalho de Melo static inline void dummy_rotate(struct rb_node *old, struct rb_node *new) {} 4263f735377SArnaldo Carvalho de Melo 4273f735377SArnaldo Carvalho de Melo static const struct rb_augment_callbacks dummy_callbacks = { 4283aef2cadSDavidlohr Bueso .propagate = dummy_propagate, 4293aef2cadSDavidlohr Bueso .copy = dummy_copy, 4303aef2cadSDavidlohr Bueso .rotate = dummy_rotate 4313f735377SArnaldo Carvalho de Melo }; 4323f735377SArnaldo Carvalho de Melo 4333f735377SArnaldo Carvalho de Melo void rb_insert_color(struct rb_node *node, struct rb_root *root) 4343f735377SArnaldo Carvalho de Melo { 435c7d4f7eeSMichel Lespinasse __rb_insert(node, root, dummy_rotate); 4363f735377SArnaldo Carvalho de Melo } 4373f735377SArnaldo Carvalho de Melo 4383f735377SArnaldo Carvalho de Melo void rb_erase(struct rb_node *node, struct rb_root *root) 4393f735377SArnaldo Carvalho de Melo { 4403f735377SArnaldo Carvalho de Melo struct rb_node *rebalance; 441c7d4f7eeSMichel Lespinasse rebalance = __rb_erase_augmented(node, root, &dummy_callbacks); 4423f735377SArnaldo Carvalho de Melo if (rebalance) 4433f735377SArnaldo Carvalho de Melo ____rb_erase_color(rebalance, root, dummy_rotate); 4443f735377SArnaldo Carvalho de Melo } 4453f735377SArnaldo Carvalho de Melo 4463f735377SArnaldo Carvalho de Melo /* 4473f735377SArnaldo Carvalho de Melo * Augmented rbtree manipulation functions. 4483f735377SArnaldo Carvalho de Melo * 4493f735377SArnaldo Carvalho de Melo * This instantiates the same __always_inline functions as in the non-augmented 4503f735377SArnaldo Carvalho de Melo * case, but this time with user-defined callbacks. 4513f735377SArnaldo Carvalho de Melo */ 4523f735377SArnaldo Carvalho de Melo 4533f735377SArnaldo Carvalho de Melo void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, 4543f735377SArnaldo Carvalho de Melo void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) 4553f735377SArnaldo Carvalho de Melo { 456c7d4f7eeSMichel Lespinasse __rb_insert(node, root, augment_rotate); 4573f735377SArnaldo Carvalho de Melo } 4583f735377SArnaldo Carvalho de Melo 4593f735377SArnaldo Carvalho de Melo /* 4603f735377SArnaldo Carvalho de Melo * This function returns the first node (in sort order) of the tree. 4613f735377SArnaldo Carvalho de Melo */ 4623f735377SArnaldo Carvalho de Melo struct rb_node *rb_first(const struct rb_root *root) 4633f735377SArnaldo Carvalho de Melo { 4643f735377SArnaldo Carvalho de Melo struct rb_node *n; 4653f735377SArnaldo Carvalho de Melo 4663f735377SArnaldo Carvalho de Melo n = root->rb_node; 4673f735377SArnaldo Carvalho de Melo if (!n) 4683f735377SArnaldo Carvalho de Melo return NULL; 4693f735377SArnaldo Carvalho de Melo while (n->rb_left) 4703f735377SArnaldo Carvalho de Melo n = n->rb_left; 4713f735377SArnaldo Carvalho de Melo return n; 4723f735377SArnaldo Carvalho de Melo } 4733f735377SArnaldo Carvalho de Melo 4743f735377SArnaldo Carvalho de Melo struct rb_node *rb_last(const struct rb_root *root) 4753f735377SArnaldo Carvalho de Melo { 4763f735377SArnaldo Carvalho de Melo struct rb_node *n; 4773f735377SArnaldo Carvalho de Melo 4783f735377SArnaldo Carvalho de Melo n = root->rb_node; 4793f735377SArnaldo Carvalho de Melo if (!n) 4803f735377SArnaldo Carvalho de Melo return NULL; 4813f735377SArnaldo Carvalho de Melo while (n->rb_right) 4823f735377SArnaldo Carvalho de Melo n = n->rb_right; 4833f735377SArnaldo Carvalho de Melo return n; 4843f735377SArnaldo Carvalho de Melo } 4853f735377SArnaldo Carvalho de Melo 4863f735377SArnaldo Carvalho de Melo struct rb_node *rb_next(const struct rb_node *node) 4873f735377SArnaldo Carvalho de Melo { 4883f735377SArnaldo Carvalho de Melo struct rb_node *parent; 4893f735377SArnaldo Carvalho de Melo 4903f735377SArnaldo Carvalho de Melo if (RB_EMPTY_NODE(node)) 4913f735377SArnaldo Carvalho de Melo return NULL; 4923f735377SArnaldo Carvalho de Melo 4933f735377SArnaldo Carvalho de Melo /* 4943f735377SArnaldo Carvalho de Melo * If we have a right-hand child, go down and then left as far 4953f735377SArnaldo Carvalho de Melo * as we can. 4963f735377SArnaldo Carvalho de Melo */ 4973f735377SArnaldo Carvalho de Melo if (node->rb_right) { 4983f735377SArnaldo Carvalho de Melo node = node->rb_right; 4993f735377SArnaldo Carvalho de Melo while (node->rb_left) 5003f735377SArnaldo Carvalho de Melo node = node->rb_left; 5013f735377SArnaldo Carvalho de Melo return (struct rb_node *)node; 5023f735377SArnaldo Carvalho de Melo } 5033f735377SArnaldo Carvalho de Melo 5043f735377SArnaldo Carvalho de Melo /* 5053f735377SArnaldo Carvalho de Melo * No right-hand children. Everything down and left is smaller than us, 5063f735377SArnaldo Carvalho de Melo * so any 'next' node must be in the general direction of our parent. 5073f735377SArnaldo Carvalho de Melo * Go up the tree; any time the ancestor is a right-hand child of its 5083f735377SArnaldo Carvalho de Melo * parent, keep going up. First time it's a left-hand child of its 5093f735377SArnaldo Carvalho de Melo * parent, said parent is our 'next' node. 5103f735377SArnaldo Carvalho de Melo */ 5113f735377SArnaldo Carvalho de Melo while ((parent = rb_parent(node)) && node == parent->rb_right) 5123f735377SArnaldo Carvalho de Melo node = parent; 5133f735377SArnaldo Carvalho de Melo 5143f735377SArnaldo Carvalho de Melo return parent; 5153f735377SArnaldo Carvalho de Melo } 5163f735377SArnaldo Carvalho de Melo 5173f735377SArnaldo Carvalho de Melo struct rb_node *rb_prev(const struct rb_node *node) 5183f735377SArnaldo Carvalho de Melo { 5193f735377SArnaldo Carvalho de Melo struct rb_node *parent; 5203f735377SArnaldo Carvalho de Melo 5213f735377SArnaldo Carvalho de Melo if (RB_EMPTY_NODE(node)) 5223f735377SArnaldo Carvalho de Melo return NULL; 5233f735377SArnaldo Carvalho de Melo 5243f735377SArnaldo Carvalho de Melo /* 5253f735377SArnaldo Carvalho de Melo * If we have a left-hand child, go down and then right as far 5263f735377SArnaldo Carvalho de Melo * as we can. 5273f735377SArnaldo Carvalho de Melo */ 5283f735377SArnaldo Carvalho de Melo if (node->rb_left) { 5293f735377SArnaldo Carvalho de Melo node = node->rb_left; 5303f735377SArnaldo Carvalho de Melo while (node->rb_right) 5313f735377SArnaldo Carvalho de Melo node = node->rb_right; 5323f735377SArnaldo Carvalho de Melo return (struct rb_node *)node; 5333f735377SArnaldo Carvalho de Melo } 5343f735377SArnaldo Carvalho de Melo 5353f735377SArnaldo Carvalho de Melo /* 5363f735377SArnaldo Carvalho de Melo * No left-hand children. Go up till we find an ancestor which 5373f735377SArnaldo Carvalho de Melo * is a right-hand child of its parent. 5383f735377SArnaldo Carvalho de Melo */ 5393f735377SArnaldo Carvalho de Melo while ((parent = rb_parent(node)) && node == parent->rb_left) 5403f735377SArnaldo Carvalho de Melo node = parent; 5413f735377SArnaldo Carvalho de Melo 5423f735377SArnaldo Carvalho de Melo return parent; 5433f735377SArnaldo Carvalho de Melo } 5443f735377SArnaldo Carvalho de Melo 5453f735377SArnaldo Carvalho de Melo void rb_replace_node(struct rb_node *victim, struct rb_node *new, 5463f735377SArnaldo Carvalho de Melo struct rb_root *root) 5473f735377SArnaldo Carvalho de Melo { 5483f735377SArnaldo Carvalho de Melo struct rb_node *parent = rb_parent(victim); 5493f735377SArnaldo Carvalho de Melo 5503aef2cadSDavidlohr Bueso /* Copy the pointers/colour from the victim to the replacement */ 5513aef2cadSDavidlohr Bueso *new = *victim; 5523aef2cadSDavidlohr Bueso 5533f735377SArnaldo Carvalho de Melo /* Set the surrounding nodes to point to the replacement */ 5543f735377SArnaldo Carvalho de Melo if (victim->rb_left) 5553f735377SArnaldo Carvalho de Melo rb_set_parent(victim->rb_left, new); 5563f735377SArnaldo Carvalho de Melo if (victim->rb_right) 5573f735377SArnaldo Carvalho de Melo rb_set_parent(victim->rb_right, new); 5583aef2cadSDavidlohr Bueso __rb_change_child(victim, new, parent, root); 5593aef2cadSDavidlohr Bueso } 5603f735377SArnaldo Carvalho de Melo 5613f735377SArnaldo Carvalho de Melo static struct rb_node *rb_left_deepest_node(const struct rb_node *node) 5623f735377SArnaldo Carvalho de Melo { 5633f735377SArnaldo Carvalho de Melo for (;;) { 5643f735377SArnaldo Carvalho de Melo if (node->rb_left) 5653f735377SArnaldo Carvalho de Melo node = node->rb_left; 5663f735377SArnaldo Carvalho de Melo else if (node->rb_right) 5673f735377SArnaldo Carvalho de Melo node = node->rb_right; 5683f735377SArnaldo Carvalho de Melo else 5693f735377SArnaldo Carvalho de Melo return (struct rb_node *)node; 5703f735377SArnaldo Carvalho de Melo } 5713f735377SArnaldo Carvalho de Melo } 5723f735377SArnaldo Carvalho de Melo 5733f735377SArnaldo Carvalho de Melo struct rb_node *rb_next_postorder(const struct rb_node *node) 5743f735377SArnaldo Carvalho de Melo { 5753f735377SArnaldo Carvalho de Melo const struct rb_node *parent; 5763f735377SArnaldo Carvalho de Melo if (!node) 5773f735377SArnaldo Carvalho de Melo return NULL; 5783f735377SArnaldo Carvalho de Melo parent = rb_parent(node); 5793f735377SArnaldo Carvalho de Melo 5803f735377SArnaldo Carvalho de Melo /* If we're sitting on node, we've already seen our children */ 5813f735377SArnaldo Carvalho de Melo if (parent && node == parent->rb_left && parent->rb_right) { 5823f735377SArnaldo Carvalho de Melo /* If we are the parent's left node, go to the parent's right 5833f735377SArnaldo Carvalho de Melo * node then all the way down to the left */ 5843f735377SArnaldo Carvalho de Melo return rb_left_deepest_node(parent->rb_right); 5853f735377SArnaldo Carvalho de Melo } else 5863f735377SArnaldo Carvalho de Melo /* Otherwise we are the parent's right node, and the parent 5873f735377SArnaldo Carvalho de Melo * should be next */ 5883f735377SArnaldo Carvalho de Melo return (struct rb_node *)parent; 5893f735377SArnaldo Carvalho de Melo } 5903f735377SArnaldo Carvalho de Melo 5913f735377SArnaldo Carvalho de Melo struct rb_node *rb_first_postorder(const struct rb_root *root) 5923f735377SArnaldo Carvalho de Melo { 5933f735377SArnaldo Carvalho de Melo if (!root->rb_node) 5943f735377SArnaldo Carvalho de Melo return NULL; 5953f735377SArnaldo Carvalho de Melo 5963f735377SArnaldo Carvalho de Melo return rb_left_deepest_node(root->rb_node); 5973f735377SArnaldo Carvalho de Melo } 598