xref: /openbsd-src/sys/kern/subr_tree.c (revision 6728b1666b77468c8838e1c56283e867ac1159a7)
1*6728b166Sdlg /*	$OpenBSD: subr_tree.c,v 1.10 2018/10/09 08:28:43 dlg Exp $ */
27ea23c36Sdlg 
37ea23c36Sdlg /*
47ea23c36Sdlg  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
57ea23c36Sdlg  * All rights reserved.
67ea23c36Sdlg  *
77ea23c36Sdlg  * Redistribution and use in source and binary forms, with or without
87ea23c36Sdlg  * modification, are permitted provided that the following conditions
97ea23c36Sdlg  * are met:
107ea23c36Sdlg  * 1. Redistributions of source code must retain the above copyright
117ea23c36Sdlg  *    notice, this list of conditions and the following disclaimer.
127ea23c36Sdlg  * 2. Redistributions in binary form must reproduce the above copyright
137ea23c36Sdlg  *    notice, this list of conditions and the following disclaimer in the
147ea23c36Sdlg  *    documentation and/or other materials provided with the distribution.
157ea23c36Sdlg  *
167ea23c36Sdlg  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
177ea23c36Sdlg  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
187ea23c36Sdlg  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
197ea23c36Sdlg  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
207ea23c36Sdlg  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
217ea23c36Sdlg  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
227ea23c36Sdlg  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
237ea23c36Sdlg  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
247ea23c36Sdlg  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
257ea23c36Sdlg  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
267ea23c36Sdlg  */
277ea23c36Sdlg 
287ea23c36Sdlg /*
297ea23c36Sdlg  * Copyright (c) 2016 David Gwynne <dlg@openbsd.org>
307ea23c36Sdlg  *
317ea23c36Sdlg  * Permission to use, copy, modify, and distribute this software for any
327ea23c36Sdlg  * purpose with or without fee is hereby granted, provided that the above
337ea23c36Sdlg  * copyright notice and this permission notice appear in all copies.
347ea23c36Sdlg  *
357ea23c36Sdlg  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
367ea23c36Sdlg  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
377ea23c36Sdlg  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
387ea23c36Sdlg  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
397ea23c36Sdlg  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
407ea23c36Sdlg  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
417ea23c36Sdlg  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
427ea23c36Sdlg  */
437ea23c36Sdlg 
447ea23c36Sdlg #include <sys/tree.h>
457ea23c36Sdlg 
46b2b87122Sdlg static inline struct rb_entry *
rb_n2e(const struct rb_type * t,void * node)477ea23c36Sdlg rb_n2e(const struct rb_type *t, void *node)
487ea23c36Sdlg {
495373dfabSdlg 	unsigned long addr = (unsigned long)node;
507ea23c36Sdlg 
51b2b87122Sdlg 	return ((struct rb_entry *)(addr + t->t_offset));
527ea23c36Sdlg }
537ea23c36Sdlg 
547ea23c36Sdlg static inline void *
rb_e2n(const struct rb_type * t,struct rb_entry * rbe)557ea23c36Sdlg rb_e2n(const struct rb_type *t, struct rb_entry *rbe)
567ea23c36Sdlg {
575373dfabSdlg 	unsigned long addr = (unsigned long)rbe;
587ea23c36Sdlg 
597ea23c36Sdlg 	return ((void *)(addr - t->t_offset));
607ea23c36Sdlg }
617ea23c36Sdlg 
6251f4a827Sdlg #define RBE_LEFT(_rbe)		(_rbe)->rbt_left
6351f4a827Sdlg #define RBE_RIGHT(_rbe)		(_rbe)->rbt_right
6451f4a827Sdlg #define RBE_PARENT(_rbe)	(_rbe)->rbt_parent
6551f4a827Sdlg #define RBE_COLOR(_rbe)		(_rbe)->rbt_color
667ea23c36Sdlg 
677ea23c36Sdlg #define RBH_ROOT(_rbt)		(_rbt)->rbt_root
687ea23c36Sdlg 
697ea23c36Sdlg static inline void
rbe_set(struct rb_entry * rbe,struct rb_entry * parent)707ea23c36Sdlg rbe_set(struct rb_entry *rbe, struct rb_entry *parent)
717ea23c36Sdlg {
727ea23c36Sdlg 	RBE_PARENT(rbe) = parent;
737ea23c36Sdlg 	RBE_LEFT(rbe) = RBE_RIGHT(rbe) = NULL;
747ea23c36Sdlg 	RBE_COLOR(rbe) = RB_RED;
757ea23c36Sdlg }
767ea23c36Sdlg 
777ea23c36Sdlg static inline void
rbe_set_blackred(struct rb_entry * black,struct rb_entry * red)787ea23c36Sdlg rbe_set_blackred(struct rb_entry *black, struct rb_entry *red)
797ea23c36Sdlg {
807ea23c36Sdlg 	RBE_COLOR(black) = RB_BLACK;
817ea23c36Sdlg 	RBE_COLOR(red) = RB_RED;
827ea23c36Sdlg }
837ea23c36Sdlg 
847ea23c36Sdlg static inline void
rbe_augment(const struct rb_type * t,struct rb_entry * rbe)857ea23c36Sdlg rbe_augment(const struct rb_type *t, struct rb_entry *rbe)
867ea23c36Sdlg {
877ea23c36Sdlg 	(*t->t_augment)(rb_e2n(t, rbe));
887ea23c36Sdlg }
897ea23c36Sdlg 
907ea23c36Sdlg static inline void
rbe_if_augment(const struct rb_type * t,struct rb_entry * rbe)917ea23c36Sdlg rbe_if_augment(const struct rb_type *t, struct rb_entry *rbe)
927ea23c36Sdlg {
937ea23c36Sdlg 	if (t->t_augment != NULL)
947ea23c36Sdlg 		rbe_augment(t, rbe);
957ea23c36Sdlg }
967ea23c36Sdlg 
977ea23c36Sdlg static inline void
rbe_rotate_left(const struct rb_type * t,struct rb_tree * rbt,struct rb_entry * rbe)987ea23c36Sdlg rbe_rotate_left(const struct rb_type *t, struct rb_tree *rbt,
997ea23c36Sdlg     struct rb_entry *rbe)
1007ea23c36Sdlg {
1017ea23c36Sdlg 	struct rb_entry *parent;
1027ea23c36Sdlg 	struct rb_entry *tmp;
1037ea23c36Sdlg 
1047ea23c36Sdlg 	tmp = RBE_RIGHT(rbe);
1057ea23c36Sdlg 	RBE_RIGHT(rbe) = RBE_LEFT(tmp);
1067ea23c36Sdlg 	if (RBE_RIGHT(rbe) != NULL)
1077ea23c36Sdlg 		RBE_PARENT(RBE_LEFT(tmp)) = rbe;
1087ea23c36Sdlg 
1097ea23c36Sdlg 	parent = RBE_PARENT(rbe);
1107ea23c36Sdlg 	RBE_PARENT(tmp) = parent;
1117ea23c36Sdlg 	if (parent != NULL) {
1127ea23c36Sdlg 		if (rbe == RBE_LEFT(parent))
1137ea23c36Sdlg 			RBE_LEFT(parent) = tmp;
1147ea23c36Sdlg 		else
1157ea23c36Sdlg 			RBE_RIGHT(parent) = tmp;
1167ea23c36Sdlg 	} else
1177ea23c36Sdlg 		RBH_ROOT(rbt) = tmp;
1187ea23c36Sdlg 
1197ea23c36Sdlg 	RBE_LEFT(tmp) = rbe;
1207ea23c36Sdlg 	RBE_PARENT(rbe) = tmp;
1217ea23c36Sdlg 
1227ea23c36Sdlg 	if (t->t_augment != NULL) {
1237ea23c36Sdlg 		rbe_augment(t, rbe);
1247ea23c36Sdlg 		rbe_augment(t, tmp);
1257ea23c36Sdlg 		parent = RBE_PARENT(tmp);
1267ea23c36Sdlg 		if (parent != NULL)
1277ea23c36Sdlg 			rbe_augment(t, parent);
1287ea23c36Sdlg 	}
1297ea23c36Sdlg }
1307ea23c36Sdlg 
1317ea23c36Sdlg static inline void
rbe_rotate_right(const struct rb_type * t,struct rb_tree * rbt,struct rb_entry * rbe)1327ea23c36Sdlg rbe_rotate_right(const struct rb_type *t, struct rb_tree *rbt,
1337ea23c36Sdlg     struct rb_entry *rbe)
1347ea23c36Sdlg {
1357ea23c36Sdlg 	struct rb_entry *parent;
1367ea23c36Sdlg 	struct rb_entry *tmp;
1377ea23c36Sdlg 
1387ea23c36Sdlg 	tmp = RBE_LEFT(rbe);
1397ea23c36Sdlg 	RBE_LEFT(rbe) = RBE_RIGHT(tmp);
1407ea23c36Sdlg 	if (RBE_LEFT(rbe) != NULL)
1417ea23c36Sdlg 		RBE_PARENT(RBE_RIGHT(tmp)) = rbe;
1427ea23c36Sdlg 
1437ea23c36Sdlg 	parent = RBE_PARENT(rbe);
1447ea23c36Sdlg 	RBE_PARENT(tmp) = parent;
1457ea23c36Sdlg 	if (parent != NULL) {
1467ea23c36Sdlg 		if (rbe == RBE_LEFT(parent))
1477ea23c36Sdlg 			RBE_LEFT(parent) = tmp;
1487ea23c36Sdlg 		else
1497ea23c36Sdlg 			RBE_RIGHT(parent) = tmp;
1507ea23c36Sdlg 	} else
1517ea23c36Sdlg 		RBH_ROOT(rbt) = tmp;
1527ea23c36Sdlg 
1537ea23c36Sdlg 	RBE_RIGHT(tmp) = rbe;
1547ea23c36Sdlg 	RBE_PARENT(rbe) = tmp;
1557ea23c36Sdlg 
1567ea23c36Sdlg 	if (t->t_augment != NULL) {
1577ea23c36Sdlg 		rbe_augment(t, rbe);
1587ea23c36Sdlg 		rbe_augment(t, tmp);
1597ea23c36Sdlg 		parent = RBE_PARENT(tmp);
1607ea23c36Sdlg 		if (parent != NULL)
1617ea23c36Sdlg 			rbe_augment(t, parent);
1627ea23c36Sdlg 	}
1637ea23c36Sdlg }
1647ea23c36Sdlg 
1657ea23c36Sdlg static inline void
rbe_insert_color(const struct rb_type * t,struct rb_tree * rbt,struct rb_entry * rbe)1667ea23c36Sdlg rbe_insert_color(const struct rb_type *t, struct rb_tree *rbt,
1677ea23c36Sdlg     struct rb_entry *rbe)
1687ea23c36Sdlg {
1697ea23c36Sdlg 	struct rb_entry *parent, *gparent, *tmp;
1707ea23c36Sdlg 
1717ea23c36Sdlg 	while ((parent = RBE_PARENT(rbe)) != NULL &&
1727ea23c36Sdlg 	    RBE_COLOR(parent) == RB_RED) {
1737ea23c36Sdlg 		gparent = RBE_PARENT(parent);
1747ea23c36Sdlg 
1757ea23c36Sdlg 		if (parent == RBE_LEFT(gparent)) {
1767ea23c36Sdlg 			tmp = RBE_RIGHT(gparent);
1777ea23c36Sdlg 			if (tmp != NULL && RBE_COLOR(tmp) == RB_RED) {
1787ea23c36Sdlg 				RBE_COLOR(tmp) = RB_BLACK;
1797ea23c36Sdlg 				rbe_set_blackred(parent, gparent);
1807ea23c36Sdlg 				rbe = gparent;
1817ea23c36Sdlg 				continue;
1827ea23c36Sdlg 			}
1837ea23c36Sdlg 
1847ea23c36Sdlg 			if (RBE_RIGHT(parent) == rbe) {
1857ea23c36Sdlg 				rbe_rotate_left(t, rbt, parent);
1867ea23c36Sdlg 				tmp = parent;
1877ea23c36Sdlg 				parent = rbe;
1887ea23c36Sdlg 				rbe = tmp;
1897ea23c36Sdlg 			}
1907ea23c36Sdlg 
1917ea23c36Sdlg 			rbe_set_blackred(parent, gparent);
1927ea23c36Sdlg 			rbe_rotate_right(t, rbt, gparent);
1937ea23c36Sdlg 		} else {
1947ea23c36Sdlg 			tmp = RBE_LEFT(gparent);
1957ea23c36Sdlg 			if (tmp != NULL && RBE_COLOR(tmp) == RB_RED) {
1967ea23c36Sdlg 				RBE_COLOR(tmp) = RB_BLACK;
1977ea23c36Sdlg 				rbe_set_blackred(parent, gparent);
1987ea23c36Sdlg 				rbe = gparent;
1997ea23c36Sdlg 				continue;
2007ea23c36Sdlg 			}
2017ea23c36Sdlg 
2027ea23c36Sdlg 			if (RBE_LEFT(parent) == rbe) {
2037ea23c36Sdlg 				rbe_rotate_right(t, rbt, parent);
2047ea23c36Sdlg 				tmp = parent;
2057ea23c36Sdlg 				parent = rbe;
2067ea23c36Sdlg 				rbe = tmp;
2077ea23c36Sdlg 			}
2087ea23c36Sdlg 
2097ea23c36Sdlg 			rbe_set_blackred(parent, gparent);
2107ea23c36Sdlg 			rbe_rotate_left(t, rbt, gparent);
2117ea23c36Sdlg 		}
2127ea23c36Sdlg 	}
2137ea23c36Sdlg 
2147ea23c36Sdlg 	RBE_COLOR(RBH_ROOT(rbt)) = RB_BLACK;
2157ea23c36Sdlg }
2167ea23c36Sdlg 
2177ea23c36Sdlg static inline void
rbe_remove_color(const struct rb_type * t,struct rb_tree * rbt,struct rb_entry * parent,struct rb_entry * rbe)2187ea23c36Sdlg rbe_remove_color(const struct rb_type *t, struct rb_tree *rbt,
2197ea23c36Sdlg     struct rb_entry *parent, struct rb_entry *rbe)
2207ea23c36Sdlg {
2217ea23c36Sdlg 	struct rb_entry *tmp;
2227ea23c36Sdlg 
2237ea23c36Sdlg 	while ((rbe == NULL || RBE_COLOR(rbe) == RB_BLACK) &&
2247ea23c36Sdlg 	    rbe != RBH_ROOT(rbt)) {
2257ea23c36Sdlg 		if (RBE_LEFT(parent) == rbe) {
2267ea23c36Sdlg 			tmp = RBE_RIGHT(parent);
2277ea23c36Sdlg 			if (RBE_COLOR(tmp) == RB_RED) {
2287ea23c36Sdlg 				rbe_set_blackred(tmp, parent);
2297ea23c36Sdlg 				rbe_rotate_left(t, rbt, parent);
2307ea23c36Sdlg 				tmp = RBE_RIGHT(parent);
2317ea23c36Sdlg 			}
2327ea23c36Sdlg 			if ((RBE_LEFT(tmp) == NULL ||
2337ea23c36Sdlg 			     RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) &&
2347ea23c36Sdlg 			    (RBE_RIGHT(tmp) == NULL ||
2357ea23c36Sdlg 			     RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK)) {
2367ea23c36Sdlg 				RBE_COLOR(tmp) = RB_RED;
2377ea23c36Sdlg 				rbe = parent;
2387ea23c36Sdlg 				parent = RBE_PARENT(rbe);
2397ea23c36Sdlg 			} else {
2407ea23c36Sdlg 				if (RBE_RIGHT(tmp) == NULL ||
2417ea23c36Sdlg 				    RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK) {
2427ea23c36Sdlg 					struct rb_entry *oleft;
2437ea23c36Sdlg 
2447ea23c36Sdlg 					oleft = RBE_LEFT(tmp);
2457ea23c36Sdlg 					if (oleft != NULL)
2467ea23c36Sdlg 						RBE_COLOR(oleft) = RB_BLACK;
2477ea23c36Sdlg 
2487ea23c36Sdlg 					RBE_COLOR(tmp) = RB_RED;
2497ea23c36Sdlg 					rbe_rotate_right(t, rbt, tmp);
2507ea23c36Sdlg 					tmp = RBE_RIGHT(parent);
2517ea23c36Sdlg 				}
2527ea23c36Sdlg 
2537ea23c36Sdlg 				RBE_COLOR(tmp) = RBE_COLOR(parent);
2547ea23c36Sdlg 				RBE_COLOR(parent) = RB_BLACK;
2557ea23c36Sdlg 				if (RBE_RIGHT(tmp))
2567ea23c36Sdlg 					RBE_COLOR(RBE_RIGHT(tmp)) = RB_BLACK;
2577ea23c36Sdlg 
2587ea23c36Sdlg 				rbe_rotate_left(t, rbt, parent);
2597ea23c36Sdlg 				rbe = RBH_ROOT(rbt);
2607ea23c36Sdlg 				break;
2617ea23c36Sdlg 			}
2627ea23c36Sdlg 		} else {
2637ea23c36Sdlg 			tmp = RBE_LEFT(parent);
2647ea23c36Sdlg 			if (RBE_COLOR(tmp) == RB_RED) {
2657ea23c36Sdlg 				rbe_set_blackred(tmp, parent);
2667ea23c36Sdlg 				rbe_rotate_right(t, rbt, parent);
2677ea23c36Sdlg 				tmp = RBE_LEFT(parent);
2687ea23c36Sdlg 			}
2697ea23c36Sdlg 
2707ea23c36Sdlg 			if ((RBE_LEFT(tmp) == NULL ||
2717ea23c36Sdlg 			     RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) &&
2727ea23c36Sdlg 			    (RBE_RIGHT(tmp) == NULL ||
2737ea23c36Sdlg 			     RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK)) {
2747ea23c36Sdlg 				RBE_COLOR(tmp) = RB_RED;
2757ea23c36Sdlg 				rbe = parent;
2767ea23c36Sdlg 				parent = RBE_PARENT(rbe);
2777ea23c36Sdlg 			} else {
2787ea23c36Sdlg 				if (RBE_LEFT(tmp) == NULL ||
2797ea23c36Sdlg 				    RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) {
2807ea23c36Sdlg 					struct rb_entry *oright;
2817ea23c36Sdlg 
2827ea23c36Sdlg 					oright = RBE_RIGHT(tmp);
2837ea23c36Sdlg 					if (oright != NULL)
2847ea23c36Sdlg 						RBE_COLOR(oright) = RB_BLACK;
2857ea23c36Sdlg 
2867ea23c36Sdlg 					RBE_COLOR(tmp) = RB_RED;
2877ea23c36Sdlg 					rbe_rotate_left(t, rbt, tmp);
2887ea23c36Sdlg 					tmp = RBE_LEFT(parent);
2897ea23c36Sdlg 				}
2907ea23c36Sdlg 
2917ea23c36Sdlg 				RBE_COLOR(tmp) = RBE_COLOR(parent);
2927ea23c36Sdlg 				RBE_COLOR(parent) = RB_BLACK;
2937ea23c36Sdlg 				if (RBE_LEFT(tmp) != NULL)
2947ea23c36Sdlg 					RBE_COLOR(RBE_LEFT(tmp)) = RB_BLACK;
2957ea23c36Sdlg 
2967ea23c36Sdlg 				rbe_rotate_right(t, rbt, parent);
2977ea23c36Sdlg 				rbe = RBH_ROOT(rbt);
2987ea23c36Sdlg 				break;
2997ea23c36Sdlg 			}
3007ea23c36Sdlg 		}
3017ea23c36Sdlg 	}
3027ea23c36Sdlg 
3037ea23c36Sdlg 	if (rbe != NULL)
3047ea23c36Sdlg 		RBE_COLOR(rbe) = RB_BLACK;
3057ea23c36Sdlg }
3067ea23c36Sdlg 
3077ea23c36Sdlg static inline struct rb_entry *
rbe_remove(const struct rb_type * t,struct rb_tree * rbt,struct rb_entry * rbe)3087ea23c36Sdlg rbe_remove(const struct rb_type *t, struct rb_tree *rbt, struct rb_entry *rbe)
3097ea23c36Sdlg {
3107ea23c36Sdlg 	struct rb_entry *child, *parent, *old = rbe;
3117ea23c36Sdlg 	unsigned int color;
3127ea23c36Sdlg 
3137ea23c36Sdlg 	if (RBE_LEFT(rbe) == NULL)
3147ea23c36Sdlg 		child = RBE_RIGHT(rbe);
3157ea23c36Sdlg 	else if (RBE_RIGHT(rbe) == NULL)
3167ea23c36Sdlg 		child = RBE_LEFT(rbe);
3177ea23c36Sdlg 	else {
3187ea23c36Sdlg 		struct rb_entry *tmp;
3197ea23c36Sdlg 
3207ea23c36Sdlg 		rbe = RBE_RIGHT(rbe);
3217ea23c36Sdlg 		while ((tmp = RBE_LEFT(rbe)) != NULL)
3227ea23c36Sdlg 			rbe = tmp;
3237ea23c36Sdlg 
3247ea23c36Sdlg 		child = RBE_RIGHT(rbe);
3257ea23c36Sdlg 		parent = RBE_PARENT(rbe);
3267ea23c36Sdlg 		color = RBE_COLOR(rbe);
3277ea23c36Sdlg 		if (child != NULL)
3287ea23c36Sdlg 			RBE_PARENT(child) = parent;
3297ea23c36Sdlg 		if (parent != NULL) {
3307ea23c36Sdlg 			if (RBE_LEFT(parent) == rbe)
3317ea23c36Sdlg 				RBE_LEFT(parent) = child;
3327ea23c36Sdlg 			else
3337ea23c36Sdlg 				RBE_RIGHT(parent) = child;
3347ea23c36Sdlg 
3357ea23c36Sdlg 			rbe_if_augment(t, parent);
3367ea23c36Sdlg 		} else
3377ea23c36Sdlg 			RBH_ROOT(rbt) = child;
3387ea23c36Sdlg 		if (RBE_PARENT(rbe) == old)
3397ea23c36Sdlg 			parent = rbe;
3407ea23c36Sdlg 		*rbe = *old;
3417ea23c36Sdlg 
3427ea23c36Sdlg 		tmp = RBE_PARENT(old);
3437ea23c36Sdlg 		if (tmp != NULL) {
3447ea23c36Sdlg 			if (RBE_LEFT(tmp) == old)
3457ea23c36Sdlg 				RBE_LEFT(tmp) = rbe;
3467ea23c36Sdlg 			else
3477ea23c36Sdlg 				RBE_RIGHT(tmp) = rbe;
3487ea23c36Sdlg 
349*6728b166Sdlg 			rbe_if_augment(t, tmp);
3507ea23c36Sdlg 		} else
3517ea23c36Sdlg 			RBH_ROOT(rbt) = rbe;
3527ea23c36Sdlg 
3537ea23c36Sdlg 		RBE_PARENT(RBE_LEFT(old)) = rbe;
3547ea23c36Sdlg 		if (RBE_RIGHT(old))
3557ea23c36Sdlg 			RBE_PARENT(RBE_RIGHT(old)) = rbe;
3567ea23c36Sdlg 
3577ea23c36Sdlg 		if (t->t_augment != NULL && parent != NULL) {
3587ea23c36Sdlg 			tmp = parent;
3597ea23c36Sdlg 			do {
3607ea23c36Sdlg 				rbe_augment(t, tmp);
3617ea23c36Sdlg 				tmp = RBE_PARENT(tmp);
3627ea23c36Sdlg 			} while (tmp != NULL);
3637ea23c36Sdlg 		}
3647ea23c36Sdlg 
3657ea23c36Sdlg 		goto color;
3667ea23c36Sdlg 	}
3677ea23c36Sdlg 
3687ea23c36Sdlg 	parent = RBE_PARENT(rbe);
3697ea23c36Sdlg 	color = RBE_COLOR(rbe);
3707ea23c36Sdlg 
3717ea23c36Sdlg 	if (child != NULL)
3727ea23c36Sdlg 		RBE_PARENT(child) = parent;
3737ea23c36Sdlg 	if (parent != NULL) {
3747ea23c36Sdlg 		if (RBE_LEFT(parent) == rbe)
3757ea23c36Sdlg 			RBE_LEFT(parent) = child;
3767ea23c36Sdlg 		else
3777ea23c36Sdlg 			RBE_RIGHT(parent) = child;
3787ea23c36Sdlg 
3797ea23c36Sdlg 		rbe_if_augment(t, parent);
3807ea23c36Sdlg 	} else
3817ea23c36Sdlg 		RBH_ROOT(rbt) = child;
3827ea23c36Sdlg color:
3837ea23c36Sdlg 	if (color == RB_BLACK)
3847ea23c36Sdlg 		rbe_remove_color(t, rbt, parent, child);
3857ea23c36Sdlg 
3867ea23c36Sdlg 	return (old);
3877ea23c36Sdlg }
3887ea23c36Sdlg 
3897ea23c36Sdlg void *
_rb_remove(const struct rb_type * t,struct rb_tree * rbt,void * elm)3907ea23c36Sdlg _rb_remove(const struct rb_type *t, struct rb_tree *rbt, void *elm)
3917ea23c36Sdlg {
3927ea23c36Sdlg 	struct rb_entry *rbe = rb_n2e(t, elm);
3937ea23c36Sdlg 	struct rb_entry *old;
3947ea23c36Sdlg 
3957ea23c36Sdlg 	old = rbe_remove(t, rbt, rbe);
3967ea23c36Sdlg 
3977ea23c36Sdlg 	return (old == NULL ? NULL : rb_e2n(t, old));
3987ea23c36Sdlg }
3997ea23c36Sdlg 
4007ea23c36Sdlg void *
_rb_insert(const struct rb_type * t,struct rb_tree * rbt,void * elm)4017ea23c36Sdlg _rb_insert(const struct rb_type *t, struct rb_tree *rbt, void *elm)
4027ea23c36Sdlg {
4037ea23c36Sdlg 	struct rb_entry *rbe = rb_n2e(t, elm);
4047ea23c36Sdlg 	struct rb_entry *tmp;
4057ea23c36Sdlg 	struct rb_entry *parent = NULL;
4067ea23c36Sdlg 	void *node;
4077ea23c36Sdlg 	int comp = 0;
4087ea23c36Sdlg 
4097ea23c36Sdlg 	tmp = RBH_ROOT(rbt);
4107ea23c36Sdlg 	while (tmp != NULL) {
4117ea23c36Sdlg 		parent = tmp;
4127ea23c36Sdlg 
4137ea23c36Sdlg 		node = rb_e2n(t, tmp);
4147ea23c36Sdlg 		comp = (*t->t_compare)(elm, node);
4157ea23c36Sdlg 		if (comp < 0)
4167ea23c36Sdlg 			tmp = RBE_LEFT(tmp);
4177ea23c36Sdlg 		else if (comp > 0)
4187ea23c36Sdlg 			tmp = RBE_RIGHT(tmp);
4197ea23c36Sdlg 		else
4207ea23c36Sdlg 			return (node);
4217ea23c36Sdlg 	}
4227ea23c36Sdlg 
4237ea23c36Sdlg 	rbe_set(rbe, parent);
4247ea23c36Sdlg 
4257ea23c36Sdlg 	if (parent != NULL) {
4267ea23c36Sdlg 		if (comp < 0)
4277ea23c36Sdlg 			RBE_LEFT(parent) = rbe;
4287ea23c36Sdlg 		else
4297ea23c36Sdlg 			RBE_RIGHT(parent) = rbe;
4307ea23c36Sdlg 
4317ea23c36Sdlg 		rbe_if_augment(t, parent);
4327ea23c36Sdlg 	} else
4337ea23c36Sdlg 		RBH_ROOT(rbt) = rbe;
4347ea23c36Sdlg 
4357ea23c36Sdlg 	rbe_insert_color(t, rbt, rbe);
4367ea23c36Sdlg 
4377ea23c36Sdlg 	return (NULL);
4387ea23c36Sdlg }
4397ea23c36Sdlg 
4407ea23c36Sdlg /* Finds the node with the same key as elm */
4417ea23c36Sdlg void *
_rb_find(const struct rb_type * t,struct rb_tree * rbt,const void * key)4427ea23c36Sdlg _rb_find(const struct rb_type *t, struct rb_tree *rbt, const void *key)
4437ea23c36Sdlg {
4447ea23c36Sdlg 	struct rb_entry *tmp = RBH_ROOT(rbt);
4457ea23c36Sdlg 	void *node;
4467ea23c36Sdlg 	int comp;
4477ea23c36Sdlg 
4487ea23c36Sdlg 	while (tmp != NULL) {
4497ea23c36Sdlg 		node = rb_e2n(t, tmp);
4507ea23c36Sdlg 		comp = (*t->t_compare)(key, node);
4517ea23c36Sdlg 		if (comp < 0)
4527ea23c36Sdlg 			tmp = RBE_LEFT(tmp);
4537ea23c36Sdlg 		else if (comp > 0)
4547ea23c36Sdlg 			tmp = RBE_RIGHT(tmp);
4557ea23c36Sdlg 		else
4567ea23c36Sdlg 			return (node);
4577ea23c36Sdlg 	}
4587ea23c36Sdlg 
4597ea23c36Sdlg 	return (NULL);
4607ea23c36Sdlg }
4617ea23c36Sdlg 
462a3c22bbaSdlg /* Finds the first node greater than or equal to the search key */
4637ea23c36Sdlg void *
_rb_nfind(const struct rb_type * t,struct rb_tree * rbt,const void * key)4647ea23c36Sdlg _rb_nfind(const struct rb_type *t, struct rb_tree *rbt, const void *key)
4657ea23c36Sdlg {
4667ea23c36Sdlg 	struct rb_entry *tmp = RBH_ROOT(rbt);
4677ea23c36Sdlg 	void *node;
4687ea23c36Sdlg 	void *res = NULL;
4697ea23c36Sdlg 	int comp;
4707ea23c36Sdlg 
4717ea23c36Sdlg 	while (tmp != NULL) {
4727ea23c36Sdlg 		node = rb_e2n(t, tmp);
4737ea23c36Sdlg 		comp = (*t->t_compare)(key, node);
4747ea23c36Sdlg 		if (comp < 0) {
4757ea23c36Sdlg 			res = node;
4767ea23c36Sdlg 			tmp = RBE_LEFT(tmp);
4777ea23c36Sdlg 		} else if (comp > 0)
4787ea23c36Sdlg 			tmp = RBE_RIGHT(tmp);
4797ea23c36Sdlg 		else
4807ea23c36Sdlg 			return (node);
4817ea23c36Sdlg 	}
4827ea23c36Sdlg 
4837ea23c36Sdlg 	return (res);
4847ea23c36Sdlg }
4857ea23c36Sdlg 
4867ea23c36Sdlg void *
_rb_next(const struct rb_type * t,void * elm)4877ea23c36Sdlg _rb_next(const struct rb_type *t, void *elm)
4887ea23c36Sdlg {
4897ea23c36Sdlg 	struct rb_entry *rbe = rb_n2e(t, elm);
4907ea23c36Sdlg 
4917ea23c36Sdlg 	if (RBE_RIGHT(rbe) != NULL) {
4927ea23c36Sdlg 		rbe = RBE_RIGHT(rbe);
4937ea23c36Sdlg 		while (RBE_LEFT(rbe) != NULL)
4947ea23c36Sdlg 			rbe = RBE_LEFT(rbe);
4957ea23c36Sdlg 	} else {
4967ea23c36Sdlg 		if (RBE_PARENT(rbe) &&
4977ea23c36Sdlg 		    (rbe == RBE_LEFT(RBE_PARENT(rbe))))
4987ea23c36Sdlg 			rbe = RBE_PARENT(rbe);
4997ea23c36Sdlg 		else {
5007ea23c36Sdlg 			while (RBE_PARENT(rbe) &&
5017ea23c36Sdlg 			    (rbe == RBE_RIGHT(RBE_PARENT(rbe))))
5027ea23c36Sdlg 				rbe = RBE_PARENT(rbe);
5037ea23c36Sdlg 			rbe = RBE_PARENT(rbe);
5047ea23c36Sdlg 		}
5057ea23c36Sdlg 	}
5067ea23c36Sdlg 
5077ea23c36Sdlg 	return (rbe == NULL ? NULL : rb_e2n(t, rbe));
5087ea23c36Sdlg }
5097ea23c36Sdlg 
5107ea23c36Sdlg void *
_rb_prev(const struct rb_type * t,void * elm)5117ea23c36Sdlg _rb_prev(const struct rb_type *t, void *elm)
5127ea23c36Sdlg {
5137ea23c36Sdlg 	struct rb_entry *rbe = rb_n2e(t, elm);
5147ea23c36Sdlg 
5157ea23c36Sdlg 	if (RBE_LEFT(rbe)) {
5167ea23c36Sdlg 		rbe = RBE_LEFT(rbe);
5177ea23c36Sdlg 		while (RBE_RIGHT(rbe))
5187ea23c36Sdlg 			rbe = RBE_RIGHT(rbe);
5197ea23c36Sdlg 	} else {
5207ea23c36Sdlg 		if (RBE_PARENT(rbe) &&
5217ea23c36Sdlg 		    (rbe == RBE_RIGHT(RBE_PARENT(rbe))))
5227ea23c36Sdlg 			rbe = RBE_PARENT(rbe);
5237ea23c36Sdlg 		else {
5247ea23c36Sdlg 			while (RBE_PARENT(rbe) &&
5257ea23c36Sdlg 			    (rbe == RBE_LEFT(RBE_PARENT(rbe))))
5267ea23c36Sdlg 				rbe = RBE_PARENT(rbe);
5277ea23c36Sdlg 			rbe = RBE_PARENT(rbe);
5287ea23c36Sdlg 		}
5297ea23c36Sdlg 	}
5307ea23c36Sdlg 
5317ea23c36Sdlg 	return (rbe == NULL ? NULL : rb_e2n(t, rbe));
5327ea23c36Sdlg }
5337ea23c36Sdlg 
5347ea23c36Sdlg void *
_rb_root(const struct rb_type * t,struct rb_tree * rbt)5357ea23c36Sdlg _rb_root(const struct rb_type *t, struct rb_tree *rbt)
5367ea23c36Sdlg {
5377ea23c36Sdlg 	struct rb_entry *rbe = RBH_ROOT(rbt);
5387ea23c36Sdlg 
5397ea23c36Sdlg 	return (rbe == NULL ? rbe : rb_e2n(t, rbe));
5407ea23c36Sdlg }
5417ea23c36Sdlg 
5427ea23c36Sdlg void *
_rb_min(const struct rb_type * t,struct rb_tree * rbt)5437ea23c36Sdlg _rb_min(const struct rb_type *t, struct rb_tree *rbt)
5447ea23c36Sdlg {
5457ea23c36Sdlg 	struct rb_entry *rbe = RBH_ROOT(rbt);
5467ea23c36Sdlg 	struct rb_entry *parent = NULL;
5477ea23c36Sdlg 
5487ea23c36Sdlg 	while (rbe != NULL) {
5497ea23c36Sdlg 		parent = rbe;
5507ea23c36Sdlg 		rbe = RBE_LEFT(rbe);
5517ea23c36Sdlg 	}
5527ea23c36Sdlg 
5537ea23c36Sdlg 	return (parent == NULL ? NULL : rb_e2n(t, parent));
5547ea23c36Sdlg }
5557ea23c36Sdlg 
5567ea23c36Sdlg void *
_rb_max(const struct rb_type * t,struct rb_tree * rbt)5577ea23c36Sdlg _rb_max(const struct rb_type *t, struct rb_tree *rbt)
5587ea23c36Sdlg {
5597ea23c36Sdlg 	struct rb_entry *rbe = RBH_ROOT(rbt);
5607ea23c36Sdlg 	struct rb_entry *parent = NULL;
5617ea23c36Sdlg 
5627ea23c36Sdlg 	while (rbe != NULL) {
5637ea23c36Sdlg 		parent = rbe;
5647ea23c36Sdlg 		rbe = RBE_RIGHT(rbe);
5657ea23c36Sdlg 	}
5667ea23c36Sdlg 
5677ea23c36Sdlg 	return (parent == NULL ? NULL : rb_e2n(t, parent));
5687ea23c36Sdlg }
5697ea23c36Sdlg 
5707ea23c36Sdlg void *
_rb_left(const struct rb_type * t,void * node)5717ea23c36Sdlg _rb_left(const struct rb_type *t, void *node)
5727ea23c36Sdlg {
5737ea23c36Sdlg 	struct rb_entry *rbe = rb_n2e(t, node);
5747ea23c36Sdlg 	rbe = RBE_LEFT(rbe);
5757ea23c36Sdlg 	return (rbe == NULL ? NULL : rb_e2n(t, rbe));
5767ea23c36Sdlg }
5777ea23c36Sdlg 
5787ea23c36Sdlg void *
_rb_right(const struct rb_type * t,void * node)5797ea23c36Sdlg _rb_right(const struct rb_type *t, void *node)
5807ea23c36Sdlg {
5817ea23c36Sdlg 	struct rb_entry *rbe = rb_n2e(t, node);
5827ea23c36Sdlg 	rbe = RBE_RIGHT(rbe);
5837ea23c36Sdlg 	return (rbe == NULL ? NULL : rb_e2n(t, rbe));
5847ea23c36Sdlg }
5857ea23c36Sdlg 
5867ea23c36Sdlg void *
_rb_parent(const struct rb_type * t,void * node)5877ea23c36Sdlg _rb_parent(const struct rb_type *t, void *node)
5887ea23c36Sdlg {
5897ea23c36Sdlg 	struct rb_entry *rbe = rb_n2e(t, node);
5907ea23c36Sdlg 	rbe = RBE_PARENT(rbe);
5917ea23c36Sdlg 	return (rbe == NULL ? NULL : rb_e2n(t, rbe));
5927ea23c36Sdlg }
5937ea23c36Sdlg 
59406591450Sdlg void
_rb_set_left(const struct rb_type * t,void * node,void * left)595f13ac283Sdlg _rb_set_left(const struct rb_type *t, void *node, void *left)
596f13ac283Sdlg {
597f13ac283Sdlg 	struct rb_entry *rbe = rb_n2e(t, node);
598f13ac283Sdlg 	struct rb_entry *rbl = (left == NULL) ? NULL : rb_n2e(t, left);
599f13ac283Sdlg 
600f13ac283Sdlg 	RBE_LEFT(rbe) = rbl;
601f13ac283Sdlg }
602f13ac283Sdlg 
603f13ac283Sdlg void
_rb_set_right(const struct rb_type * t,void * node,void * right)604f13ac283Sdlg _rb_set_right(const struct rb_type *t, void *node, void *right)
605f13ac283Sdlg {
606f13ac283Sdlg 	struct rb_entry *rbe = rb_n2e(t, node);
607f13ac283Sdlg 	struct rb_entry *rbr = (right == NULL) ? NULL : rb_n2e(t, right);
608f13ac283Sdlg 
609f13ac283Sdlg 	RBE_RIGHT(rbe) = rbr;
610f13ac283Sdlg }
611f13ac283Sdlg 
612f13ac283Sdlg void
_rb_set_parent(const struct rb_type * t,void * node,void * parent)613f13ac283Sdlg _rb_set_parent(const struct rb_type *t, void *node, void *parent)
614f13ac283Sdlg {
615f13ac283Sdlg 	struct rb_entry *rbe = rb_n2e(t, node);
616f13ac283Sdlg 	struct rb_entry *rbp = (parent == NULL) ? NULL : rb_n2e(t, parent);
617f13ac283Sdlg 
618f13ac283Sdlg 	RBE_PARENT(rbe) = rbp;
619f13ac283Sdlg }
620f13ac283Sdlg 
621f13ac283Sdlg void
_rb_poison(const struct rb_type * t,void * node,unsigned long poison)62206591450Sdlg _rb_poison(const struct rb_type *t, void *node, unsigned long poison)
62306591450Sdlg {
62406591450Sdlg 	struct rb_entry *rbe = rb_n2e(t, node);
62506591450Sdlg 
62606591450Sdlg 	RBE_PARENT(rbe) = RBE_LEFT(rbe) = RBE_RIGHT(rbe) =
62706591450Sdlg 	    (struct rb_entry *)poison;
62806591450Sdlg }
62906591450Sdlg 
63006591450Sdlg int
_rb_check(const struct rb_type * t,void * node,unsigned long poison)63106591450Sdlg _rb_check(const struct rb_type *t, void *node, unsigned long poison)
63206591450Sdlg {
63306591450Sdlg 	struct rb_entry *rbe = rb_n2e(t, node);
63406591450Sdlg 
63506591450Sdlg 	return ((unsigned long)RBE_PARENT(rbe) == poison &&
63606591450Sdlg 	    (unsigned long)RBE_LEFT(rbe) == poison &&
63706591450Sdlg 	    (unsigned long)RBE_RIGHT(rbe) == poison);
63806591450Sdlg }
639