xref: /openbmc/linux/tools/lib/rbtree.c (revision 3aef2cad5d51ee66d2a614dd2f70cb34c74caf77)
13f735377SArnaldo Carvalho de Melo /*
23f735377SArnaldo Carvalho de Melo   Red Black Trees
33f735377SArnaldo Carvalho de Melo   (C) 1999  Andrea Arcangeli <andrea@suse.de>
43f735377SArnaldo Carvalho de Melo   (C) 2002  David Woodhouse <dwmw2@infradead.org>
53f735377SArnaldo Carvalho de Melo   (C) 2012  Michel Lespinasse <walken@google.com>
63f735377SArnaldo Carvalho de Melo 
73f735377SArnaldo Carvalho de Melo   This program is free software; you can redistribute it and/or modify
83f735377SArnaldo Carvalho de Melo   it under the terms of the GNU General Public License as published by
93f735377SArnaldo Carvalho de Melo   the Free Software Foundation; either version 2 of the License, or
103f735377SArnaldo Carvalho de Melo   (at your option) any later version.
113f735377SArnaldo Carvalho de Melo 
123f735377SArnaldo Carvalho de Melo   This program is distributed in the hope that it will be useful,
133f735377SArnaldo Carvalho de Melo   but WITHOUT ANY WARRANTY; without even the implied warranty of
143f735377SArnaldo Carvalho de Melo   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
153f735377SArnaldo Carvalho de Melo   GNU General Public License for more details.
163f735377SArnaldo Carvalho de Melo 
173f735377SArnaldo Carvalho de Melo   You should have received a copy of the GNU General Public License
183f735377SArnaldo Carvalho de Melo   along with this program; if not, write to the Free Software
193f735377SArnaldo Carvalho de Melo   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
203f735377SArnaldo Carvalho de Melo 
213f735377SArnaldo Carvalho de Melo   linux/lib/rbtree.c
223f735377SArnaldo Carvalho de Melo */
233f735377SArnaldo Carvalho de Melo 
243f735377SArnaldo Carvalho de Melo #include <linux/rbtree_augmented.h>
25*3aef2cadSDavidlohr Bueso #include <linux/export.h>
263f735377SArnaldo Carvalho de Melo 
273f735377SArnaldo Carvalho de Melo /*
283f735377SArnaldo Carvalho de Melo  * red-black trees properties:  http://en.wikipedia.org/wiki/Rbtree
293f735377SArnaldo Carvalho de Melo  *
303f735377SArnaldo Carvalho de Melo  *  1) A node is either red or black
313f735377SArnaldo Carvalho de Melo  *  2) The root is black
323f735377SArnaldo Carvalho de Melo  *  3) All leaves (NULL) are black
333f735377SArnaldo Carvalho de Melo  *  4) Both children of every red node are black
343f735377SArnaldo Carvalho de Melo  *  5) Every simple path from root to leaves contains the same number
353f735377SArnaldo Carvalho de Melo  *     of black nodes.
363f735377SArnaldo Carvalho de Melo  *
373f735377SArnaldo Carvalho de Melo  *  4 and 5 give the O(log n) guarantee, since 4 implies you cannot have two
383f735377SArnaldo Carvalho de Melo  *  consecutive red nodes in a path and every red node is therefore followed by
393f735377SArnaldo Carvalho de Melo  *  a black. So if B is the number of black nodes on every simple path (as per
403f735377SArnaldo Carvalho de Melo  *  5), then the longest possible path due to 4 is 2B.
413f735377SArnaldo Carvalho de Melo  *
423f735377SArnaldo Carvalho de Melo  *  We shall indicate color with case, where black nodes are uppercase and red
433f735377SArnaldo Carvalho de Melo  *  nodes will be lowercase. Unknown color nodes shall be drawn as red within
443f735377SArnaldo Carvalho de Melo  *  parentheses and have some accompanying text comment.
453f735377SArnaldo Carvalho de Melo  */
463f735377SArnaldo Carvalho de Melo 
47*3aef2cadSDavidlohr Bueso /*
48*3aef2cadSDavidlohr Bueso  * Notes on lockless lookups:
49*3aef2cadSDavidlohr Bueso  *
50*3aef2cadSDavidlohr Bueso  * All stores to the tree structure (rb_left and rb_right) must be done using
51*3aef2cadSDavidlohr Bueso  * WRITE_ONCE(). And we must not inadvertently cause (temporary) loops in the
52*3aef2cadSDavidlohr Bueso  * tree structure as seen in program order.
53*3aef2cadSDavidlohr Bueso  *
54*3aef2cadSDavidlohr Bueso  * These two requirements will allow lockless iteration of the tree -- not
55*3aef2cadSDavidlohr Bueso  * correct iteration mind you, tree rotations are not atomic so a lookup might
56*3aef2cadSDavidlohr Bueso  * miss entire subtrees.
57*3aef2cadSDavidlohr Bueso  *
58*3aef2cadSDavidlohr Bueso  * But they do guarantee that any such traversal will only see valid elements
59*3aef2cadSDavidlohr Bueso  * and that it will indeed complete -- does not get stuck in a loop.
60*3aef2cadSDavidlohr Bueso  *
61*3aef2cadSDavidlohr Bueso  * It also guarantees that if the lookup returns an element it is the 'correct'
62*3aef2cadSDavidlohr Bueso  * one. But not returning an element does _NOT_ mean it's not present.
63*3aef2cadSDavidlohr Bueso  *
64*3aef2cadSDavidlohr Bueso  * NOTE:
65*3aef2cadSDavidlohr Bueso  *
66*3aef2cadSDavidlohr Bueso  * Stores to __rb_parent_color are not important for simple lookups so those
67*3aef2cadSDavidlohr Bueso  * are left undone as of now. Nor did I check for loops involving parent
68*3aef2cadSDavidlohr Bueso  * pointers.
69*3aef2cadSDavidlohr Bueso  */
70*3aef2cadSDavidlohr Bueso 
713f735377SArnaldo Carvalho de Melo static inline void rb_set_black(struct rb_node *rb)
723f735377SArnaldo Carvalho de Melo {
733f735377SArnaldo Carvalho de Melo 	rb->__rb_parent_color |= RB_BLACK;
743f735377SArnaldo Carvalho de Melo }
753f735377SArnaldo Carvalho de Melo 
763f735377SArnaldo Carvalho de Melo static inline struct rb_node *rb_red_parent(struct rb_node *red)
773f735377SArnaldo Carvalho de Melo {
783f735377SArnaldo Carvalho de Melo 	return (struct rb_node *)red->__rb_parent_color;
793f735377SArnaldo Carvalho de Melo }
803f735377SArnaldo Carvalho de Melo 
813f735377SArnaldo Carvalho de Melo /*
823f735377SArnaldo Carvalho de Melo  * Helper function for rotations:
833f735377SArnaldo Carvalho de Melo  * - old's parent and color get assigned to new
843f735377SArnaldo Carvalho de Melo  * - old gets assigned new as a parent and 'color' as a color.
853f735377SArnaldo Carvalho de Melo  */
863f735377SArnaldo Carvalho de Melo static inline void
873f735377SArnaldo Carvalho de Melo __rb_rotate_set_parents(struct rb_node *old, struct rb_node *new,
883f735377SArnaldo Carvalho de Melo 			struct rb_root *root, int color)
893f735377SArnaldo Carvalho de Melo {
903f735377SArnaldo Carvalho de Melo 	struct rb_node *parent = rb_parent(old);
913f735377SArnaldo Carvalho de Melo 	new->__rb_parent_color = old->__rb_parent_color;
923f735377SArnaldo Carvalho de Melo 	rb_set_parent_color(old, new, color);
933f735377SArnaldo Carvalho de Melo 	__rb_change_child(old, new, parent, root);
943f735377SArnaldo Carvalho de Melo }
953f735377SArnaldo Carvalho de Melo 
963f735377SArnaldo Carvalho de Melo static __always_inline void
973f735377SArnaldo Carvalho de Melo __rb_insert(struct rb_node *node, struct rb_root *root,
98*3aef2cadSDavidlohr Bueso 	    bool newleft, struct rb_node **leftmost,
993f735377SArnaldo Carvalho de Melo 	    void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
1003f735377SArnaldo Carvalho de Melo {
1013f735377SArnaldo Carvalho de Melo 	struct rb_node *parent = rb_red_parent(node), *gparent, *tmp;
1023f735377SArnaldo Carvalho de Melo 
103*3aef2cadSDavidlohr Bueso 	if (newleft)
104*3aef2cadSDavidlohr Bueso 		*leftmost = node;
105*3aef2cadSDavidlohr Bueso 
1063f735377SArnaldo Carvalho de Melo 	while (true) {
1073f735377SArnaldo Carvalho de Melo 		/*
108*3aef2cadSDavidlohr Bueso 		 * Loop invariant: node is red.
1093f735377SArnaldo Carvalho de Melo 		 */
110*3aef2cadSDavidlohr Bueso 		if (unlikely(!parent)) {
111*3aef2cadSDavidlohr Bueso 			/*
112*3aef2cadSDavidlohr Bueso 			 * The inserted node is root. Either this is the
113*3aef2cadSDavidlohr Bueso 			 * first node, or we recursed at Case 1 below and
114*3aef2cadSDavidlohr Bueso 			 * are no longer violating 4).
115*3aef2cadSDavidlohr Bueso 			 */
1163f735377SArnaldo Carvalho de Melo 			rb_set_parent_color(node, NULL, RB_BLACK);
1173f735377SArnaldo Carvalho de Melo 			break;
118*3aef2cadSDavidlohr Bueso 		}
119*3aef2cadSDavidlohr Bueso 
120*3aef2cadSDavidlohr Bueso 		/*
121*3aef2cadSDavidlohr Bueso 		 * If there is a black parent, we are done.
122*3aef2cadSDavidlohr Bueso 		 * Otherwise, take some corrective action as,
123*3aef2cadSDavidlohr Bueso 		 * per 4), we don't want a red root or two
124*3aef2cadSDavidlohr Bueso 		 * consecutive red nodes.
125*3aef2cadSDavidlohr Bueso 		 */
126*3aef2cadSDavidlohr Bueso 		if(rb_is_black(parent))
1273f735377SArnaldo Carvalho de Melo 			break;
1283f735377SArnaldo Carvalho de Melo 
1293f735377SArnaldo Carvalho de Melo 		gparent = rb_red_parent(parent);
1303f735377SArnaldo Carvalho de Melo 
1313f735377SArnaldo Carvalho de Melo 		tmp = gparent->rb_right;
1323f735377SArnaldo Carvalho de Melo 		if (parent != tmp) {	/* parent == gparent->rb_left */
1333f735377SArnaldo Carvalho de Melo 			if (tmp && rb_is_red(tmp)) {
1343f735377SArnaldo Carvalho de Melo 				/*
135*3aef2cadSDavidlohr Bueso 				 * Case 1 - node's uncle is red (color flips).
1363f735377SArnaldo Carvalho de Melo 				 *
1373f735377SArnaldo Carvalho de Melo 				 *       G            g
1383f735377SArnaldo Carvalho de Melo 				 *      / \          / \
1393f735377SArnaldo Carvalho de Melo 				 *     p   u  -->   P   U
1403f735377SArnaldo Carvalho de Melo 				 *    /            /
1413f735377SArnaldo Carvalho de Melo 				 *   n            n
1423f735377SArnaldo Carvalho de Melo 				 *
1433f735377SArnaldo Carvalho de Melo 				 * However, since g's parent might be red, and
1443f735377SArnaldo Carvalho de Melo 				 * 4) does not allow this, we need to recurse
1453f735377SArnaldo Carvalho de Melo 				 * at g.
1463f735377SArnaldo Carvalho de Melo 				 */
1473f735377SArnaldo Carvalho de Melo 				rb_set_parent_color(tmp, gparent, RB_BLACK);
1483f735377SArnaldo Carvalho de Melo 				rb_set_parent_color(parent, gparent, RB_BLACK);
1493f735377SArnaldo Carvalho de Melo 				node = gparent;
1503f735377SArnaldo Carvalho de Melo 				parent = rb_parent(node);
1513f735377SArnaldo Carvalho de Melo 				rb_set_parent_color(node, parent, RB_RED);
1523f735377SArnaldo Carvalho de Melo 				continue;
1533f735377SArnaldo Carvalho de Melo 			}
1543f735377SArnaldo Carvalho de Melo 
1553f735377SArnaldo Carvalho de Melo 			tmp = parent->rb_right;
1563f735377SArnaldo Carvalho de Melo 			if (node == tmp) {
1573f735377SArnaldo Carvalho de Melo 				/*
158*3aef2cadSDavidlohr Bueso 				 * Case 2 - node's uncle is black and node is
159*3aef2cadSDavidlohr Bueso 				 * the parent's right child (left rotate at parent).
1603f735377SArnaldo Carvalho de Melo 				 *
1613f735377SArnaldo Carvalho de Melo 				 *      G             G
1623f735377SArnaldo Carvalho de Melo 				 *     / \           / \
1633f735377SArnaldo Carvalho de Melo 				 *    p   U  -->    n   U
1643f735377SArnaldo Carvalho de Melo 				 *     \           /
1653f735377SArnaldo Carvalho de Melo 				 *      n         p
1663f735377SArnaldo Carvalho de Melo 				 *
1673f735377SArnaldo Carvalho de Melo 				 * This still leaves us in violation of 4), the
1683f735377SArnaldo Carvalho de Melo 				 * continuation into Case 3 will fix that.
1693f735377SArnaldo Carvalho de Melo 				 */
170*3aef2cadSDavidlohr Bueso 				tmp = node->rb_left;
171*3aef2cadSDavidlohr Bueso 				WRITE_ONCE(parent->rb_right, tmp);
172*3aef2cadSDavidlohr Bueso 				WRITE_ONCE(node->rb_left, parent);
1733f735377SArnaldo Carvalho de Melo 				if (tmp)
1743f735377SArnaldo Carvalho de Melo 					rb_set_parent_color(tmp, parent,
1753f735377SArnaldo Carvalho de Melo 							    RB_BLACK);
1763f735377SArnaldo Carvalho de Melo 				rb_set_parent_color(parent, node, RB_RED);
1773f735377SArnaldo Carvalho de Melo 				augment_rotate(parent, node);
1783f735377SArnaldo Carvalho de Melo 				parent = node;
1793f735377SArnaldo Carvalho de Melo 				tmp = node->rb_right;
1803f735377SArnaldo Carvalho de Melo 			}
1813f735377SArnaldo Carvalho de Melo 
1823f735377SArnaldo Carvalho de Melo 			/*
183*3aef2cadSDavidlohr Bueso 			 * Case 3 - node's uncle is black and node is
184*3aef2cadSDavidlohr Bueso 			 * the parent's left child (right rotate at gparent).
1853f735377SArnaldo Carvalho de Melo 			 *
1863f735377SArnaldo Carvalho de Melo 			 *        G           P
1873f735377SArnaldo Carvalho de Melo 			 *       / \         / \
1883f735377SArnaldo Carvalho de Melo 			 *      p   U  -->  n   g
1893f735377SArnaldo Carvalho de Melo 			 *     /                 \
1903f735377SArnaldo Carvalho de Melo 			 *    n                   U
1913f735377SArnaldo Carvalho de Melo 			 */
192*3aef2cadSDavidlohr Bueso 			WRITE_ONCE(gparent->rb_left, tmp); /* == parent->rb_right */
193*3aef2cadSDavidlohr Bueso 			WRITE_ONCE(parent->rb_right, gparent);
1943f735377SArnaldo Carvalho de Melo 			if (tmp)
1953f735377SArnaldo Carvalho de Melo 				rb_set_parent_color(tmp, gparent, RB_BLACK);
1963f735377SArnaldo Carvalho de Melo 			__rb_rotate_set_parents(gparent, parent, root, RB_RED);
1973f735377SArnaldo Carvalho de Melo 			augment_rotate(gparent, parent);
1983f735377SArnaldo Carvalho de Melo 			break;
1993f735377SArnaldo Carvalho de Melo 		} else {
2003f735377SArnaldo Carvalho de Melo 			tmp = gparent->rb_left;
2013f735377SArnaldo Carvalho de Melo 			if (tmp && rb_is_red(tmp)) {
2023f735377SArnaldo Carvalho de Melo 				/* Case 1 - color flips */
2033f735377SArnaldo Carvalho de Melo 				rb_set_parent_color(tmp, gparent, RB_BLACK);
2043f735377SArnaldo Carvalho de Melo 				rb_set_parent_color(parent, gparent, RB_BLACK);
2053f735377SArnaldo Carvalho de Melo 				node = gparent;
2063f735377SArnaldo Carvalho de Melo 				parent = rb_parent(node);
2073f735377SArnaldo Carvalho de Melo 				rb_set_parent_color(node, parent, RB_RED);
2083f735377SArnaldo Carvalho de Melo 				continue;
2093f735377SArnaldo Carvalho de Melo 			}
2103f735377SArnaldo Carvalho de Melo 
2113f735377SArnaldo Carvalho de Melo 			tmp = parent->rb_left;
2123f735377SArnaldo Carvalho de Melo 			if (node == tmp) {
2133f735377SArnaldo Carvalho de Melo 				/* Case 2 - right rotate at parent */
214*3aef2cadSDavidlohr Bueso 				tmp = node->rb_right;
215*3aef2cadSDavidlohr Bueso 				WRITE_ONCE(parent->rb_left, tmp);
216*3aef2cadSDavidlohr Bueso 				WRITE_ONCE(node->rb_right, parent);
2173f735377SArnaldo Carvalho de Melo 				if (tmp)
2183f735377SArnaldo Carvalho de Melo 					rb_set_parent_color(tmp, parent,
2193f735377SArnaldo Carvalho de Melo 							    RB_BLACK);
2203f735377SArnaldo Carvalho de Melo 				rb_set_parent_color(parent, node, RB_RED);
2213f735377SArnaldo Carvalho de Melo 				augment_rotate(parent, node);
2223f735377SArnaldo Carvalho de Melo 				parent = node;
2233f735377SArnaldo Carvalho de Melo 				tmp = node->rb_left;
2243f735377SArnaldo Carvalho de Melo 			}
2253f735377SArnaldo Carvalho de Melo 
2263f735377SArnaldo Carvalho de Melo 			/* Case 3 - left rotate at gparent */
227*3aef2cadSDavidlohr Bueso 			WRITE_ONCE(gparent->rb_right, tmp); /* == parent->rb_left */
228*3aef2cadSDavidlohr Bueso 			WRITE_ONCE(parent->rb_left, gparent);
2293f735377SArnaldo Carvalho de Melo 			if (tmp)
2303f735377SArnaldo Carvalho de Melo 				rb_set_parent_color(tmp, gparent, RB_BLACK);
2313f735377SArnaldo Carvalho de Melo 			__rb_rotate_set_parents(gparent, parent, root, RB_RED);
2323f735377SArnaldo Carvalho de Melo 			augment_rotate(gparent, parent);
2333f735377SArnaldo Carvalho de Melo 			break;
2343f735377SArnaldo Carvalho de Melo 		}
2353f735377SArnaldo Carvalho de Melo 	}
2363f735377SArnaldo Carvalho de Melo }
2373f735377SArnaldo Carvalho de Melo 
2383f735377SArnaldo Carvalho de Melo /*
2393f735377SArnaldo Carvalho de Melo  * Inline version for rb_erase() use - we want to be able to inline
2403f735377SArnaldo Carvalho de Melo  * and eliminate the dummy_rotate callback there
2413f735377SArnaldo Carvalho de Melo  */
2423f735377SArnaldo Carvalho de Melo static __always_inline void
2433f735377SArnaldo Carvalho de Melo ____rb_erase_color(struct rb_node *parent, struct rb_root *root,
2443f735377SArnaldo Carvalho de Melo 	void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
2453f735377SArnaldo Carvalho de Melo {
2463f735377SArnaldo Carvalho de Melo 	struct rb_node *node = NULL, *sibling, *tmp1, *tmp2;
2473f735377SArnaldo Carvalho de Melo 
2483f735377SArnaldo Carvalho de Melo 	while (true) {
2493f735377SArnaldo Carvalho de Melo 		/*
2503f735377SArnaldo Carvalho de Melo 		 * Loop invariants:
2513f735377SArnaldo Carvalho de Melo 		 * - node is black (or NULL on first iteration)
2523f735377SArnaldo Carvalho de Melo 		 * - node is not the root (parent is not NULL)
2533f735377SArnaldo Carvalho de Melo 		 * - All leaf paths going through parent and node have a
2543f735377SArnaldo Carvalho de Melo 		 *   black node count that is 1 lower than other leaf paths.
2553f735377SArnaldo Carvalho de Melo 		 */
2563f735377SArnaldo Carvalho de Melo 		sibling = parent->rb_right;
2573f735377SArnaldo Carvalho de Melo 		if (node != sibling) {	/* node == parent->rb_left */
2583f735377SArnaldo Carvalho de Melo 			if (rb_is_red(sibling)) {
2593f735377SArnaldo Carvalho de Melo 				/*
2603f735377SArnaldo Carvalho de Melo 				 * Case 1 - left rotate at parent
2613f735377SArnaldo Carvalho de Melo 				 *
2623f735377SArnaldo Carvalho de Melo 				 *     P               S
2633f735377SArnaldo Carvalho de Melo 				 *    / \             / \
2643f735377SArnaldo Carvalho de Melo 				 *   N   s    -->    p   Sr
2653f735377SArnaldo Carvalho de Melo 				 *      / \         / \
2663f735377SArnaldo Carvalho de Melo 				 *     Sl  Sr      N   Sl
2673f735377SArnaldo Carvalho de Melo 				 */
268*3aef2cadSDavidlohr Bueso 				tmp1 = sibling->rb_left;
269*3aef2cadSDavidlohr Bueso 				WRITE_ONCE(parent->rb_right, tmp1);
270*3aef2cadSDavidlohr Bueso 				WRITE_ONCE(sibling->rb_left, parent);
2713f735377SArnaldo Carvalho de Melo 				rb_set_parent_color(tmp1, parent, RB_BLACK);
2723f735377SArnaldo Carvalho de Melo 				__rb_rotate_set_parents(parent, sibling, root,
2733f735377SArnaldo Carvalho de Melo 							RB_RED);
2743f735377SArnaldo Carvalho de Melo 				augment_rotate(parent, sibling);
2753f735377SArnaldo Carvalho de Melo 				sibling = tmp1;
2763f735377SArnaldo Carvalho de Melo 			}
2773f735377SArnaldo Carvalho de Melo 			tmp1 = sibling->rb_right;
2783f735377SArnaldo Carvalho de Melo 			if (!tmp1 || rb_is_black(tmp1)) {
2793f735377SArnaldo Carvalho de Melo 				tmp2 = sibling->rb_left;
2803f735377SArnaldo Carvalho de Melo 				if (!tmp2 || rb_is_black(tmp2)) {
2813f735377SArnaldo Carvalho de Melo 					/*
2823f735377SArnaldo Carvalho de Melo 					 * Case 2 - sibling color flip
2833f735377SArnaldo Carvalho de Melo 					 * (p could be either color here)
2843f735377SArnaldo Carvalho de Melo 					 *
2853f735377SArnaldo Carvalho de Melo 					 *    (p)           (p)
2863f735377SArnaldo Carvalho de Melo 					 *    / \           / \
2873f735377SArnaldo Carvalho de Melo 					 *   N   S    -->  N   s
2883f735377SArnaldo Carvalho de Melo 					 *      / \           / \
2893f735377SArnaldo Carvalho de Melo 					 *     Sl  Sr        Sl  Sr
2903f735377SArnaldo Carvalho de Melo 					 *
2913f735377SArnaldo Carvalho de Melo 					 * This leaves us violating 5) which
2923f735377SArnaldo Carvalho de Melo 					 * can be fixed by flipping p to black
2933f735377SArnaldo Carvalho de Melo 					 * if it was red, or by recursing at p.
2943f735377SArnaldo Carvalho de Melo 					 * p is red when coming from Case 1.
2953f735377SArnaldo Carvalho de Melo 					 */
2963f735377SArnaldo Carvalho de Melo 					rb_set_parent_color(sibling, parent,
2973f735377SArnaldo Carvalho de Melo 							    RB_RED);
2983f735377SArnaldo Carvalho de Melo 					if (rb_is_red(parent))
2993f735377SArnaldo Carvalho de Melo 						rb_set_black(parent);
3003f735377SArnaldo Carvalho de Melo 					else {
3013f735377SArnaldo Carvalho de Melo 						node = parent;
3023f735377SArnaldo Carvalho de Melo 						parent = rb_parent(node);
3033f735377SArnaldo Carvalho de Melo 						if (parent)
3043f735377SArnaldo Carvalho de Melo 							continue;
3053f735377SArnaldo Carvalho de Melo 					}
3063f735377SArnaldo Carvalho de Melo 					break;
3073f735377SArnaldo Carvalho de Melo 				}
3083f735377SArnaldo Carvalho de Melo 				/*
3093f735377SArnaldo Carvalho de Melo 				 * Case 3 - right rotate at sibling
3103f735377SArnaldo Carvalho de Melo 				 * (p could be either color here)
3113f735377SArnaldo Carvalho de Melo 				 *
3123f735377SArnaldo Carvalho de Melo 				 *   (p)           (p)
3133f735377SArnaldo Carvalho de Melo 				 *   / \           / \
314*3aef2cadSDavidlohr Bueso 				 *  N   S    -->  N   sl
3153f735377SArnaldo Carvalho de Melo 				 *     / \             \
316*3aef2cadSDavidlohr Bueso 				 *    sl  Sr            S
317*3aef2cadSDavidlohr Bueso 				 *                       \
318*3aef2cadSDavidlohr Bueso 				 *                        Sr
319*3aef2cadSDavidlohr Bueso 				 *
320*3aef2cadSDavidlohr Bueso 				 * Note: p might be red, and then both
321*3aef2cadSDavidlohr Bueso 				 * p and sl are red after rotation(which
322*3aef2cadSDavidlohr Bueso 				 * breaks property 4). This is fixed in
323*3aef2cadSDavidlohr Bueso 				 * Case 4 (in __rb_rotate_set_parents()
324*3aef2cadSDavidlohr Bueso 				 *         which set sl the color of p
325*3aef2cadSDavidlohr Bueso 				 *         and set p RB_BLACK)
326*3aef2cadSDavidlohr Bueso 				 *
327*3aef2cadSDavidlohr Bueso 				 *   (p)            (sl)
328*3aef2cadSDavidlohr Bueso 				 *   / \            /  \
329*3aef2cadSDavidlohr Bueso 				 *  N   sl   -->   P    S
330*3aef2cadSDavidlohr Bueso 				 *       \        /      \
331*3aef2cadSDavidlohr Bueso 				 *        S      N        Sr
3323f735377SArnaldo Carvalho de Melo 				 *         \
3333f735377SArnaldo Carvalho de Melo 				 *          Sr
3343f735377SArnaldo Carvalho de Melo 				 */
335*3aef2cadSDavidlohr Bueso 				tmp1 = tmp2->rb_right;
336*3aef2cadSDavidlohr Bueso 				WRITE_ONCE(sibling->rb_left, tmp1);
337*3aef2cadSDavidlohr Bueso 				WRITE_ONCE(tmp2->rb_right, sibling);
338*3aef2cadSDavidlohr Bueso 				WRITE_ONCE(parent->rb_right, tmp2);
3393f735377SArnaldo Carvalho de Melo 				if (tmp1)
3403f735377SArnaldo Carvalho de Melo 					rb_set_parent_color(tmp1, sibling,
3413f735377SArnaldo Carvalho de Melo 							    RB_BLACK);
3423f735377SArnaldo Carvalho de Melo 				augment_rotate(sibling, tmp2);
3433f735377SArnaldo Carvalho de Melo 				tmp1 = sibling;
3443f735377SArnaldo Carvalho de Melo 				sibling = tmp2;
3453f735377SArnaldo Carvalho de Melo 			}
3463f735377SArnaldo Carvalho de Melo 			/*
3473f735377SArnaldo Carvalho de Melo 			 * Case 4 - left rotate at parent + color flips
3483f735377SArnaldo Carvalho de Melo 			 * (p and sl could be either color here.
3493f735377SArnaldo Carvalho de Melo 			 *  After rotation, p becomes black, s acquires
3503f735377SArnaldo Carvalho de Melo 			 *  p's color, and sl keeps its color)
3513f735377SArnaldo Carvalho de Melo 			 *
3523f735377SArnaldo Carvalho de Melo 			 *      (p)             (s)
3533f735377SArnaldo Carvalho de Melo 			 *      / \             / \
3543f735377SArnaldo Carvalho de Melo 			 *     N   S     -->   P   Sr
3553f735377SArnaldo Carvalho de Melo 			 *        / \         / \
3563f735377SArnaldo Carvalho de Melo 			 *      (sl) sr      N  (sl)
3573f735377SArnaldo Carvalho de Melo 			 */
358*3aef2cadSDavidlohr Bueso 			tmp2 = sibling->rb_left;
359*3aef2cadSDavidlohr Bueso 			WRITE_ONCE(parent->rb_right, tmp2);
360*3aef2cadSDavidlohr Bueso 			WRITE_ONCE(sibling->rb_left, parent);
3613f735377SArnaldo Carvalho de Melo 			rb_set_parent_color(tmp1, sibling, RB_BLACK);
3623f735377SArnaldo Carvalho de Melo 			if (tmp2)
3633f735377SArnaldo Carvalho de Melo 				rb_set_parent(tmp2, parent);
3643f735377SArnaldo Carvalho de Melo 			__rb_rotate_set_parents(parent, sibling, root,
3653f735377SArnaldo Carvalho de Melo 						RB_BLACK);
3663f735377SArnaldo Carvalho de Melo 			augment_rotate(parent, sibling);
3673f735377SArnaldo Carvalho de Melo 			break;
3683f735377SArnaldo Carvalho de Melo 		} else {
3693f735377SArnaldo Carvalho de Melo 			sibling = parent->rb_left;
3703f735377SArnaldo Carvalho de Melo 			if (rb_is_red(sibling)) {
3713f735377SArnaldo Carvalho de Melo 				/* Case 1 - right rotate at parent */
372*3aef2cadSDavidlohr Bueso 				tmp1 = sibling->rb_right;
373*3aef2cadSDavidlohr Bueso 				WRITE_ONCE(parent->rb_left, tmp1);
374*3aef2cadSDavidlohr Bueso 				WRITE_ONCE(sibling->rb_right, parent);
3753f735377SArnaldo Carvalho de Melo 				rb_set_parent_color(tmp1, parent, RB_BLACK);
3763f735377SArnaldo Carvalho de Melo 				__rb_rotate_set_parents(parent, sibling, root,
3773f735377SArnaldo Carvalho de Melo 							RB_RED);
3783f735377SArnaldo Carvalho de Melo 				augment_rotate(parent, sibling);
3793f735377SArnaldo Carvalho de Melo 				sibling = tmp1;
3803f735377SArnaldo Carvalho de Melo 			}
3813f735377SArnaldo Carvalho de Melo 			tmp1 = sibling->rb_left;
3823f735377SArnaldo Carvalho de Melo 			if (!tmp1 || rb_is_black(tmp1)) {
3833f735377SArnaldo Carvalho de Melo 				tmp2 = sibling->rb_right;
3843f735377SArnaldo Carvalho de Melo 				if (!tmp2 || rb_is_black(tmp2)) {
3853f735377SArnaldo Carvalho de Melo 					/* Case 2 - sibling color flip */
3863f735377SArnaldo Carvalho de Melo 					rb_set_parent_color(sibling, parent,
3873f735377SArnaldo Carvalho de Melo 							    RB_RED);
3883f735377SArnaldo Carvalho de Melo 					if (rb_is_red(parent))
3893f735377SArnaldo Carvalho de Melo 						rb_set_black(parent);
3903f735377SArnaldo Carvalho de Melo 					else {
3913f735377SArnaldo Carvalho de Melo 						node = parent;
3923f735377SArnaldo Carvalho de Melo 						parent = rb_parent(node);
3933f735377SArnaldo Carvalho de Melo 						if (parent)
3943f735377SArnaldo Carvalho de Melo 							continue;
3953f735377SArnaldo Carvalho de Melo 					}
3963f735377SArnaldo Carvalho de Melo 					break;
3973f735377SArnaldo Carvalho de Melo 				}
398*3aef2cadSDavidlohr Bueso 				/* Case 3 - left rotate at sibling */
399*3aef2cadSDavidlohr Bueso 				tmp1 = tmp2->rb_left;
400*3aef2cadSDavidlohr Bueso 				WRITE_ONCE(sibling->rb_right, tmp1);
401*3aef2cadSDavidlohr Bueso 				WRITE_ONCE(tmp2->rb_left, sibling);
402*3aef2cadSDavidlohr Bueso 				WRITE_ONCE(parent->rb_left, tmp2);
4033f735377SArnaldo Carvalho de Melo 				if (tmp1)
4043f735377SArnaldo Carvalho de Melo 					rb_set_parent_color(tmp1, sibling,
4053f735377SArnaldo Carvalho de Melo 							    RB_BLACK);
4063f735377SArnaldo Carvalho de Melo 				augment_rotate(sibling, tmp2);
4073f735377SArnaldo Carvalho de Melo 				tmp1 = sibling;
4083f735377SArnaldo Carvalho de Melo 				sibling = tmp2;
4093f735377SArnaldo Carvalho de Melo 			}
410*3aef2cadSDavidlohr Bueso 			/* Case 4 - right rotate at parent + color flips */
411*3aef2cadSDavidlohr Bueso 			tmp2 = sibling->rb_right;
412*3aef2cadSDavidlohr Bueso 			WRITE_ONCE(parent->rb_left, tmp2);
413*3aef2cadSDavidlohr Bueso 			WRITE_ONCE(sibling->rb_right, parent);
4143f735377SArnaldo Carvalho de Melo 			rb_set_parent_color(tmp1, sibling, RB_BLACK);
4153f735377SArnaldo Carvalho de Melo 			if (tmp2)
4163f735377SArnaldo Carvalho de Melo 				rb_set_parent(tmp2, parent);
4173f735377SArnaldo Carvalho de Melo 			__rb_rotate_set_parents(parent, sibling, root,
4183f735377SArnaldo Carvalho de Melo 						RB_BLACK);
4193f735377SArnaldo Carvalho de Melo 			augment_rotate(parent, sibling);
4203f735377SArnaldo Carvalho de Melo 			break;
4213f735377SArnaldo Carvalho de Melo 		}
4223f735377SArnaldo Carvalho de Melo 	}
4233f735377SArnaldo Carvalho de Melo }
4243f735377SArnaldo Carvalho de Melo 
4253f735377SArnaldo Carvalho de Melo /* Non-inline version for rb_erase_augmented() use */
4263f735377SArnaldo Carvalho de Melo void __rb_erase_color(struct rb_node *parent, struct rb_root *root,
4273f735377SArnaldo Carvalho de Melo 	void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
4283f735377SArnaldo Carvalho de Melo {
4293f735377SArnaldo Carvalho de Melo 	____rb_erase_color(parent, root, augment_rotate);
4303f735377SArnaldo Carvalho de Melo }
4313f735377SArnaldo Carvalho de Melo 
4323f735377SArnaldo Carvalho de Melo /*
4333f735377SArnaldo Carvalho de Melo  * Non-augmented rbtree manipulation functions.
4343f735377SArnaldo Carvalho de Melo  *
4353f735377SArnaldo Carvalho de Melo  * We use dummy augmented callbacks here, and have the compiler optimize them
4363f735377SArnaldo Carvalho de Melo  * out of the rb_insert_color() and rb_erase() function definitions.
4373f735377SArnaldo Carvalho de Melo  */
4383f735377SArnaldo Carvalho de Melo 
4393f735377SArnaldo Carvalho de Melo static inline void dummy_propagate(struct rb_node *node, struct rb_node *stop) {}
4403f735377SArnaldo Carvalho de Melo static inline void dummy_copy(struct rb_node *old, struct rb_node *new) {}
4413f735377SArnaldo Carvalho de Melo static inline void dummy_rotate(struct rb_node *old, struct rb_node *new) {}
4423f735377SArnaldo Carvalho de Melo 
4433f735377SArnaldo Carvalho de Melo static const struct rb_augment_callbacks dummy_callbacks = {
444*3aef2cadSDavidlohr Bueso 	.propagate = dummy_propagate,
445*3aef2cadSDavidlohr Bueso 	.copy = dummy_copy,
446*3aef2cadSDavidlohr Bueso 	.rotate = dummy_rotate
4473f735377SArnaldo Carvalho de Melo };
4483f735377SArnaldo Carvalho de Melo 
4493f735377SArnaldo Carvalho de Melo void rb_insert_color(struct rb_node *node, struct rb_root *root)
4503f735377SArnaldo Carvalho de Melo {
451*3aef2cadSDavidlohr Bueso 	__rb_insert(node, root, false, NULL, dummy_rotate);
4523f735377SArnaldo Carvalho de Melo }
4533f735377SArnaldo Carvalho de Melo 
4543f735377SArnaldo Carvalho de Melo void rb_erase(struct rb_node *node, struct rb_root *root)
4553f735377SArnaldo Carvalho de Melo {
4563f735377SArnaldo Carvalho de Melo 	struct rb_node *rebalance;
457*3aef2cadSDavidlohr Bueso 	rebalance = __rb_erase_augmented(node, root,
458*3aef2cadSDavidlohr Bueso 					 NULL, &dummy_callbacks);
4593f735377SArnaldo Carvalho de Melo 	if (rebalance)
4603f735377SArnaldo Carvalho de Melo 		____rb_erase_color(rebalance, root, dummy_rotate);
4613f735377SArnaldo Carvalho de Melo }
4623f735377SArnaldo Carvalho de Melo 
463*3aef2cadSDavidlohr Bueso void rb_insert_color_cached(struct rb_node *node,
464*3aef2cadSDavidlohr Bueso 			    struct rb_root_cached *root, bool leftmost)
465*3aef2cadSDavidlohr Bueso {
466*3aef2cadSDavidlohr Bueso 	__rb_insert(node, &root->rb_root, leftmost,
467*3aef2cadSDavidlohr Bueso 		    &root->rb_leftmost, dummy_rotate);
468*3aef2cadSDavidlohr Bueso }
469*3aef2cadSDavidlohr Bueso 
470*3aef2cadSDavidlohr Bueso void rb_erase_cached(struct rb_node *node, struct rb_root_cached *root)
471*3aef2cadSDavidlohr Bueso {
472*3aef2cadSDavidlohr Bueso 	struct rb_node *rebalance;
473*3aef2cadSDavidlohr Bueso 	rebalance = __rb_erase_augmented(node, &root->rb_root,
474*3aef2cadSDavidlohr Bueso 					 &root->rb_leftmost, &dummy_callbacks);
475*3aef2cadSDavidlohr Bueso 	if (rebalance)
476*3aef2cadSDavidlohr Bueso 		____rb_erase_color(rebalance, &root->rb_root, dummy_rotate);
477*3aef2cadSDavidlohr Bueso }
478*3aef2cadSDavidlohr Bueso 
4793f735377SArnaldo Carvalho de Melo /*
4803f735377SArnaldo Carvalho de Melo  * Augmented rbtree manipulation functions.
4813f735377SArnaldo Carvalho de Melo  *
4823f735377SArnaldo Carvalho de Melo  * This instantiates the same __always_inline functions as in the non-augmented
4833f735377SArnaldo Carvalho de Melo  * case, but this time with user-defined callbacks.
4843f735377SArnaldo Carvalho de Melo  */
4853f735377SArnaldo Carvalho de Melo 
4863f735377SArnaldo Carvalho de Melo void __rb_insert_augmented(struct rb_node *node, struct rb_root *root,
487*3aef2cadSDavidlohr Bueso 			   bool newleft, struct rb_node **leftmost,
4883f735377SArnaldo Carvalho de Melo 	void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
4893f735377SArnaldo Carvalho de Melo {
490*3aef2cadSDavidlohr Bueso 	__rb_insert(node, root, newleft, leftmost, augment_rotate);
4913f735377SArnaldo Carvalho de Melo }
4923f735377SArnaldo Carvalho de Melo 
4933f735377SArnaldo Carvalho de Melo /*
4943f735377SArnaldo Carvalho de Melo  * This function returns the first node (in sort order) of the tree.
4953f735377SArnaldo Carvalho de Melo  */
4963f735377SArnaldo Carvalho de Melo struct rb_node *rb_first(const struct rb_root *root)
4973f735377SArnaldo Carvalho de Melo {
4983f735377SArnaldo Carvalho de Melo 	struct rb_node	*n;
4993f735377SArnaldo Carvalho de Melo 
5003f735377SArnaldo Carvalho de Melo 	n = root->rb_node;
5013f735377SArnaldo Carvalho de Melo 	if (!n)
5023f735377SArnaldo Carvalho de Melo 		return NULL;
5033f735377SArnaldo Carvalho de Melo 	while (n->rb_left)
5043f735377SArnaldo Carvalho de Melo 		n = n->rb_left;
5053f735377SArnaldo Carvalho de Melo 	return n;
5063f735377SArnaldo Carvalho de Melo }
5073f735377SArnaldo Carvalho de Melo 
5083f735377SArnaldo Carvalho de Melo struct rb_node *rb_last(const struct rb_root *root)
5093f735377SArnaldo Carvalho de Melo {
5103f735377SArnaldo Carvalho de Melo 	struct rb_node	*n;
5113f735377SArnaldo Carvalho de Melo 
5123f735377SArnaldo Carvalho de Melo 	n = root->rb_node;
5133f735377SArnaldo Carvalho de Melo 	if (!n)
5143f735377SArnaldo Carvalho de Melo 		return NULL;
5153f735377SArnaldo Carvalho de Melo 	while (n->rb_right)
5163f735377SArnaldo Carvalho de Melo 		n = n->rb_right;
5173f735377SArnaldo Carvalho de Melo 	return n;
5183f735377SArnaldo Carvalho de Melo }
5193f735377SArnaldo Carvalho de Melo 
5203f735377SArnaldo Carvalho de Melo struct rb_node *rb_next(const struct rb_node *node)
5213f735377SArnaldo Carvalho de Melo {
5223f735377SArnaldo Carvalho de Melo 	struct rb_node *parent;
5233f735377SArnaldo Carvalho de Melo 
5243f735377SArnaldo Carvalho de Melo 	if (RB_EMPTY_NODE(node))
5253f735377SArnaldo Carvalho de Melo 		return NULL;
5263f735377SArnaldo Carvalho de Melo 
5273f735377SArnaldo Carvalho de Melo 	/*
5283f735377SArnaldo Carvalho de Melo 	 * If we have a right-hand child, go down and then left as far
5293f735377SArnaldo Carvalho de Melo 	 * as we can.
5303f735377SArnaldo Carvalho de Melo 	 */
5313f735377SArnaldo Carvalho de Melo 	if (node->rb_right) {
5323f735377SArnaldo Carvalho de Melo 		node = node->rb_right;
5333f735377SArnaldo Carvalho de Melo 		while (node->rb_left)
5343f735377SArnaldo Carvalho de Melo 			node=node->rb_left;
5353f735377SArnaldo Carvalho de Melo 		return (struct rb_node *)node;
5363f735377SArnaldo Carvalho de Melo 	}
5373f735377SArnaldo Carvalho de Melo 
5383f735377SArnaldo Carvalho de Melo 	/*
5393f735377SArnaldo Carvalho de Melo 	 * No right-hand children. Everything down and left is smaller than us,
5403f735377SArnaldo Carvalho de Melo 	 * so any 'next' node must be in the general direction of our parent.
5413f735377SArnaldo Carvalho de Melo 	 * Go up the tree; any time the ancestor is a right-hand child of its
5423f735377SArnaldo Carvalho de Melo 	 * parent, keep going up. First time it's a left-hand child of its
5433f735377SArnaldo Carvalho de Melo 	 * parent, said parent is our 'next' node.
5443f735377SArnaldo Carvalho de Melo 	 */
5453f735377SArnaldo Carvalho de Melo 	while ((parent = rb_parent(node)) && node == parent->rb_right)
5463f735377SArnaldo Carvalho de Melo 		node = parent;
5473f735377SArnaldo Carvalho de Melo 
5483f735377SArnaldo Carvalho de Melo 	return parent;
5493f735377SArnaldo Carvalho de Melo }
5503f735377SArnaldo Carvalho de Melo 
5513f735377SArnaldo Carvalho de Melo struct rb_node *rb_prev(const struct rb_node *node)
5523f735377SArnaldo Carvalho de Melo {
5533f735377SArnaldo Carvalho de Melo 	struct rb_node *parent;
5543f735377SArnaldo Carvalho de Melo 
5553f735377SArnaldo Carvalho de Melo 	if (RB_EMPTY_NODE(node))
5563f735377SArnaldo Carvalho de Melo 		return NULL;
5573f735377SArnaldo Carvalho de Melo 
5583f735377SArnaldo Carvalho de Melo 	/*
5593f735377SArnaldo Carvalho de Melo 	 * If we have a left-hand child, go down and then right as far
5603f735377SArnaldo Carvalho de Melo 	 * as we can.
5613f735377SArnaldo Carvalho de Melo 	 */
5623f735377SArnaldo Carvalho de Melo 	if (node->rb_left) {
5633f735377SArnaldo Carvalho de Melo 		node = node->rb_left;
5643f735377SArnaldo Carvalho de Melo 		while (node->rb_right)
5653f735377SArnaldo Carvalho de Melo 			node=node->rb_right;
5663f735377SArnaldo Carvalho de Melo 		return (struct rb_node *)node;
5673f735377SArnaldo Carvalho de Melo 	}
5683f735377SArnaldo Carvalho de Melo 
5693f735377SArnaldo Carvalho de Melo 	/*
5703f735377SArnaldo Carvalho de Melo 	 * No left-hand children. Go up till we find an ancestor which
5713f735377SArnaldo Carvalho de Melo 	 * is a right-hand child of its parent.
5723f735377SArnaldo Carvalho de Melo 	 */
5733f735377SArnaldo Carvalho de Melo 	while ((parent = rb_parent(node)) && node == parent->rb_left)
5743f735377SArnaldo Carvalho de Melo 		node = parent;
5753f735377SArnaldo Carvalho de Melo 
5763f735377SArnaldo Carvalho de Melo 	return parent;
5773f735377SArnaldo Carvalho de Melo }
5783f735377SArnaldo Carvalho de Melo 
5793f735377SArnaldo Carvalho de Melo void rb_replace_node(struct rb_node *victim, struct rb_node *new,
5803f735377SArnaldo Carvalho de Melo 		     struct rb_root *root)
5813f735377SArnaldo Carvalho de Melo {
5823f735377SArnaldo Carvalho de Melo 	struct rb_node *parent = rb_parent(victim);
5833f735377SArnaldo Carvalho de Melo 
584*3aef2cadSDavidlohr Bueso 	/* Copy the pointers/colour from the victim to the replacement */
585*3aef2cadSDavidlohr Bueso 	*new = *victim;
586*3aef2cadSDavidlohr Bueso 
5873f735377SArnaldo Carvalho de Melo 	/* Set the surrounding nodes to point to the replacement */
5883f735377SArnaldo Carvalho de Melo 	if (victim->rb_left)
5893f735377SArnaldo Carvalho de Melo 		rb_set_parent(victim->rb_left, new);
5903f735377SArnaldo Carvalho de Melo 	if (victim->rb_right)
5913f735377SArnaldo Carvalho de Melo 		rb_set_parent(victim->rb_right, new);
592*3aef2cadSDavidlohr Bueso 	__rb_change_child(victim, new, parent, root);
593*3aef2cadSDavidlohr Bueso }
5943f735377SArnaldo Carvalho de Melo 
595*3aef2cadSDavidlohr Bueso void rb_replace_node_cached(struct rb_node *victim, struct rb_node *new,
596*3aef2cadSDavidlohr Bueso 			    struct rb_root_cached *root)
597*3aef2cadSDavidlohr Bueso {
598*3aef2cadSDavidlohr Bueso 	rb_replace_node(victim, new, &root->rb_root);
599*3aef2cadSDavidlohr Bueso 
600*3aef2cadSDavidlohr Bueso 	if (root->rb_leftmost == victim)
601*3aef2cadSDavidlohr Bueso 		root->rb_leftmost = new;
6023f735377SArnaldo Carvalho de Melo }
6033f735377SArnaldo Carvalho de Melo 
6043f735377SArnaldo Carvalho de Melo static struct rb_node *rb_left_deepest_node(const struct rb_node *node)
6053f735377SArnaldo Carvalho de Melo {
6063f735377SArnaldo Carvalho de Melo 	for (;;) {
6073f735377SArnaldo Carvalho de Melo 		if (node->rb_left)
6083f735377SArnaldo Carvalho de Melo 			node = node->rb_left;
6093f735377SArnaldo Carvalho de Melo 		else if (node->rb_right)
6103f735377SArnaldo Carvalho de Melo 			node = node->rb_right;
6113f735377SArnaldo Carvalho de Melo 		else
6123f735377SArnaldo Carvalho de Melo 			return (struct rb_node *)node;
6133f735377SArnaldo Carvalho de Melo 	}
6143f735377SArnaldo Carvalho de Melo }
6153f735377SArnaldo Carvalho de Melo 
6163f735377SArnaldo Carvalho de Melo struct rb_node *rb_next_postorder(const struct rb_node *node)
6173f735377SArnaldo Carvalho de Melo {
6183f735377SArnaldo Carvalho de Melo 	const struct rb_node *parent;
6193f735377SArnaldo Carvalho de Melo 	if (!node)
6203f735377SArnaldo Carvalho de Melo 		return NULL;
6213f735377SArnaldo Carvalho de Melo 	parent = rb_parent(node);
6223f735377SArnaldo Carvalho de Melo 
6233f735377SArnaldo Carvalho de Melo 	/* If we're sitting on node, we've already seen our children */
6243f735377SArnaldo Carvalho de Melo 	if (parent && node == parent->rb_left && parent->rb_right) {
6253f735377SArnaldo Carvalho de Melo 		/* If we are the parent's left node, go to the parent's right
6263f735377SArnaldo Carvalho de Melo 		 * node then all the way down to the left */
6273f735377SArnaldo Carvalho de Melo 		return rb_left_deepest_node(parent->rb_right);
6283f735377SArnaldo Carvalho de Melo 	} else
6293f735377SArnaldo Carvalho de Melo 		/* Otherwise we are the parent's right node, and the parent
6303f735377SArnaldo Carvalho de Melo 		 * should be next */
6313f735377SArnaldo Carvalho de Melo 		return (struct rb_node *)parent;
6323f735377SArnaldo Carvalho de Melo }
6333f735377SArnaldo Carvalho de Melo 
6343f735377SArnaldo Carvalho de Melo struct rb_node *rb_first_postorder(const struct rb_root *root)
6353f735377SArnaldo Carvalho de Melo {
6363f735377SArnaldo Carvalho de Melo 	if (!root->rb_node)
6373f735377SArnaldo Carvalho de Melo 		return NULL;
6383f735377SArnaldo Carvalho de Melo 
6393f735377SArnaldo Carvalho de Melo 	return rb_left_deepest_node(root->rb_node);
6403f735377SArnaldo Carvalho de Melo }
641