xref: /freebsd/sys/compat/linuxkpi/common/include/linux/rbtree.h (revision a5cac2e672a7d94c0391076e7452d6a487f7b5c1)
18d59ecb2SHans Petter Selasky /*-
28d59ecb2SHans Petter Selasky  * Copyright (c) 2010 Isilon Systems, Inc.
38d59ecb2SHans Petter Selasky  * Copyright (c) 2010 iX Systems, Inc.
48d59ecb2SHans Petter Selasky  * Copyright (c) 2010 Panasas, Inc.
58d59ecb2SHans Petter Selasky  * Copyright (c) 2013, 2014 Mellanox Technologies, Ltd.
68d59ecb2SHans Petter Selasky  * All rights reserved.
78d59ecb2SHans Petter Selasky  *
88d59ecb2SHans Petter Selasky  * Redistribution and use in source and binary forms, with or without
98d59ecb2SHans Petter Selasky  * modification, are permitted provided that the following conditions
108d59ecb2SHans Petter Selasky  * are met:
118d59ecb2SHans Petter Selasky  * 1. Redistributions of source code must retain the above copyright
128d59ecb2SHans Petter Selasky  *    notice unmodified, this list of conditions, and the following
138d59ecb2SHans Petter Selasky  *    disclaimer.
148d59ecb2SHans Petter Selasky  * 2. Redistributions in binary form must reproduce the above copyright
158d59ecb2SHans Petter Selasky  *    notice, this list of conditions and the following disclaimer in the
168d59ecb2SHans Petter Selasky  *    documentation and/or other materials provided with the distribution.
178d59ecb2SHans Petter Selasky  *
188d59ecb2SHans Petter Selasky  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
198d59ecb2SHans Petter Selasky  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
208d59ecb2SHans Petter Selasky  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
218d59ecb2SHans Petter Selasky  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
228d59ecb2SHans Petter Selasky  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
238d59ecb2SHans Petter Selasky  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
248d59ecb2SHans Petter Selasky  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
258d59ecb2SHans Petter Selasky  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
268d59ecb2SHans Petter Selasky  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
278d59ecb2SHans Petter Selasky  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
288d59ecb2SHans Petter Selasky  */
29307f78f3SVladimir Kondratyev #ifndef	_LINUXKPI_LINUX_RBTREE_H_
30307f78f3SVladimir Kondratyev #define	_LINUXKPI_LINUX_RBTREE_H_
318d59ecb2SHans Petter Selasky 
32ff15f3f1SHans Petter Selasky #ifndef _STANDALONE
338d59ecb2SHans Petter Selasky #include <sys/stddef.h>
34ff15f3f1SHans Petter Selasky #endif
35ff15f3f1SHans Petter Selasky 
36dbc920bdSVladimir Kondratyev #include <sys/types.h>
378d59ecb2SHans Petter Selasky #include <sys/tree.h>
388d59ecb2SHans Petter Selasky 
398d59ecb2SHans Petter Selasky struct rb_node {
408d59ecb2SHans Petter Selasky 	RB_ENTRY(rb_node)	__entry;
418d59ecb2SHans Petter Selasky };
42d0354fa7SDoug Moore #define	rb_left		__entry.rbe_link[_RB_L]
43d0354fa7SDoug Moore #define	rb_right	__entry.rbe_link[_RB_R]
448d59ecb2SHans Petter Selasky 
458d59ecb2SHans Petter Selasky /*
468d59ecb2SHans Petter Selasky  * We provide a false structure that has the same bit pattern as tree.h
478d59ecb2SHans Petter Selasky  * presents so it matches the member names expected by linux.
488d59ecb2SHans Petter Selasky  */
498d59ecb2SHans Petter Selasky struct rb_root {
508d59ecb2SHans Petter Selasky 	struct	rb_node	*rb_node;
518d59ecb2SHans Petter Selasky };
528d59ecb2SHans Petter Selasky 
53dbc920bdSVladimir Kondratyev struct rb_root_cached {
54dbc920bdSVladimir Kondratyev 	struct rb_root rb_root;
55dbc920bdSVladimir Kondratyev 	struct rb_node *rb_leftmost;
56dbc920bdSVladimir Kondratyev };
57dbc920bdSVladimir Kondratyev 
588d59ecb2SHans Petter Selasky /*
598d59ecb2SHans Petter Selasky  * In linux all of the comparisons are done by the caller.
608d59ecb2SHans Petter Selasky  */
618d59ecb2SHans Petter Selasky int panic_cmp(struct rb_node *one, struct rb_node *two);
628d59ecb2SHans Petter Selasky 
638d59ecb2SHans Petter Selasky RB_HEAD(linux_root, rb_node);
648d59ecb2SHans Petter Selasky RB_PROTOTYPE(linux_root, rb_node, __entry, panic_cmp);
658d59ecb2SHans Petter Selasky 
66dd527633SVladimir Kondratyev #define	rb_parent(r)	RB_PARENT(r, __entry)
678d59ecb2SHans Petter Selasky #define	rb_entry(ptr, type, member)	container_of(ptr, type, member)
68dd527633SVladimir Kondratyev #define	rb_entry_safe(ptr, type, member) \
69dd527633SVladimir Kondratyev 	((ptr) != NULL ? rb_entry(ptr, type, member) : NULL)
708d59ecb2SHans Petter Selasky 
71dd527633SVladimir Kondratyev #define	RB_EMPTY_ROOT(root)	((root)->rb_node == NULL)
724d569800SDoug Moore #define RB_EMPTY_NODE(node)     (RB_PARENT(node, __entry) == node)
73158c55a5SDoug Moore #define RB_CLEAR_NODE(node)     RB_SET_PARENT(node, node, __entry)
748d59ecb2SHans Petter Selasky 
754893472cSDoug Moore #define rb_insert_color(node, root) do {				\
764893472cSDoug Moore 	if (rb_parent(node))						\
774893472cSDoug Moore 		linux_root_RB_INSERT_COLOR((struct linux_root *)(root), \
784893472cSDoug Moore 		    rb_parent(node), (node));				\
794893472cSDoug Moore } while (0)
808d59ecb2SHans Petter Selasky #define	rb_erase(node, root)						\
818d59ecb2SHans Petter Selasky 	linux_root_RB_REMOVE((struct linux_root *)(root), (node))
828d59ecb2SHans Petter Selasky #define	rb_next(node)	RB_NEXT(linux_root, NULL, (node))
838d59ecb2SHans Petter Selasky #define	rb_prev(node)	RB_PREV(linux_root, NULL, (node))
848d59ecb2SHans Petter Selasky #define	rb_first(root)	RB_MIN(linux_root, (struct linux_root *)(root))
858d59ecb2SHans Petter Selasky #define	rb_last(root)	RB_MAX(linux_root, (struct linux_root *)(root))
86dbc920bdSVladimir Kondratyev #define	rb_first_cached(root)	(root)->rb_leftmost
878d59ecb2SHans Petter Selasky 
88dd527633SVladimir Kondratyev static inline struct rb_node *
89dd527633SVladimir Kondratyev __rb_deepest_left(struct rb_node *node)
90dd527633SVladimir Kondratyev {
91dd527633SVladimir Kondratyev 	struct rb_node *parent = NULL;
92dd527633SVladimir Kondratyev 	while (node != NULL) {
93dd527633SVladimir Kondratyev 		parent = node;
94dd527633SVladimir Kondratyev 		if (RB_LEFT(node, __entry))
95dd527633SVladimir Kondratyev 			node = RB_LEFT(node, __entry);
96dd527633SVladimir Kondratyev 		else
97dd527633SVladimir Kondratyev 			node = RB_RIGHT(node, __entry);
98dd527633SVladimir Kondratyev 	}
99dd527633SVladimir Kondratyev 	return (parent);
100dd527633SVladimir Kondratyev }
101dd527633SVladimir Kondratyev 
102dd527633SVladimir Kondratyev static inline struct rb_node *
103dd527633SVladimir Kondratyev rb_next_postorder(const struct rb_node *node)
104dd527633SVladimir Kondratyev {
105dd527633SVladimir Kondratyev 	struct rb_node *parent =
106dd527633SVladimir Kondratyev 	    RB_PARENT(__DECONST(struct rb_node *, node), __entry);
107dd527633SVladimir Kondratyev 	/* left -> right, right -> root */
108dd527633SVladimir Kondratyev 	if (parent != NULL &&
109dd527633SVladimir Kondratyev 	    (node == RB_LEFT(parent, __entry)) &&
110dd527633SVladimir Kondratyev 	    (RB_RIGHT(parent, __entry)))
111dd527633SVladimir Kondratyev 		return (__rb_deepest_left(RB_RIGHT(parent, __entry)));
112dd527633SVladimir Kondratyev 	else
113dd527633SVladimir Kondratyev 		return (parent);
114dd527633SVladimir Kondratyev }
115dd527633SVladimir Kondratyev 
116dd527633SVladimir Kondratyev #define	rbtree_postorder_for_each_entry_safe(x, y, head, member)	\
117dd527633SVladimir Kondratyev 	for ((x) = rb_entry_safe(__rb_deepest_left((head)->rb_node),	\
118dd527633SVladimir Kondratyev 	    __typeof(*x), member);					\
119dd527633SVladimir Kondratyev 	    ((x) != NULL) && ((y) =					\
120dd527633SVladimir Kondratyev 	    rb_entry_safe(rb_next_postorder(&x->member), typeof(*x), member), 1); \
121dd527633SVladimir Kondratyev 	    (x) = (y))
122dd527633SVladimir Kondratyev 
1238d59ecb2SHans Petter Selasky static inline void
1248d59ecb2SHans Petter Selasky rb_link_node(struct rb_node *node, struct rb_node *parent,
1258d59ecb2SHans Petter Selasky     struct rb_node **rb_link)
1268d59ecb2SHans Petter Selasky {
1274d569800SDoug Moore 	RB_SET(node, parent, __entry);
1288d59ecb2SHans Petter Selasky 	*rb_link = node;
1298d59ecb2SHans Petter Selasky }
1308d59ecb2SHans Petter Selasky 
1318d59ecb2SHans Petter Selasky static inline void
1328d59ecb2SHans Petter Selasky rb_replace_node(struct rb_node *victim, struct rb_node *new,
1338d59ecb2SHans Petter Selasky     struct rb_root *root)
1348d59ecb2SHans Petter Selasky {
1358d59ecb2SHans Petter Selasky 
13602d0c43cSDoug Moore 	RB_SWAP_CHILD((struct linux_root *)root, rb_parent(victim),
13702d0c43cSDoug Moore 	    victim, new, __entry);
138d0354fa7SDoug Moore 	if (RB_LEFT(victim, __entry))
139d0354fa7SDoug Moore 		RB_SET_PARENT(RB_LEFT(victim, __entry), new, __entry);
140d0354fa7SDoug Moore 	if (RB_RIGHT(victim, __entry))
141d0354fa7SDoug Moore 		RB_SET_PARENT(RB_RIGHT(victim, __entry), new, __entry);
1428d59ecb2SHans Petter Selasky 	*new = *victim;
1438d59ecb2SHans Petter Selasky }
1448d59ecb2SHans Petter Selasky 
145dbc920bdSVladimir Kondratyev static inline void
146dbc920bdSVladimir Kondratyev rb_insert_color_cached(struct rb_node *node, struct rb_root_cached *root,
147dbc920bdSVladimir Kondratyev     bool leftmost)
148dbc920bdSVladimir Kondratyev {
1494893472cSDoug Moore 	if (rb_parent(node))
1504893472cSDoug Moore 		linux_root_RB_INSERT_COLOR((struct linux_root *)&root->rb_root,
1514893472cSDoug Moore 		    rb_parent(node), node);
152dbc920bdSVladimir Kondratyev 	if (leftmost)
153dbc920bdSVladimir Kondratyev 		root->rb_leftmost = node;
154dbc920bdSVladimir Kondratyev }
155dbc920bdSVladimir Kondratyev 
156dbc920bdSVladimir Kondratyev static inline struct rb_node *
157dbc920bdSVladimir Kondratyev rb_erase_cached(struct rb_node *node, struct rb_root_cached *root)
158dbc920bdSVladimir Kondratyev {
159dbc920bdSVladimir Kondratyev 	struct rb_node *retval;
160dbc920bdSVladimir Kondratyev 
161dbc920bdSVladimir Kondratyev 	if (node == root->rb_leftmost)
162dbc920bdSVladimir Kondratyev 		retval = root->rb_leftmost = linux_root_RB_NEXT(node);
163dbc920bdSVladimir Kondratyev 	else
164dbc920bdSVladimir Kondratyev 		retval = NULL;
165dbc920bdSVladimir Kondratyev 	linux_root_RB_REMOVE((struct linux_root *)&root->rb_root, node);
166dbc920bdSVladimir Kondratyev 	return (retval);
167dbc920bdSVladimir Kondratyev }
168dbc920bdSVladimir Kondratyev 
169dbc920bdSVladimir Kondratyev static inline void
170dbc920bdSVladimir Kondratyev rb_replace_node_cached(struct rb_node *old, struct rb_node *new,
171dbc920bdSVladimir Kondratyev     struct rb_root_cached *root)
172dbc920bdSVladimir Kondratyev {
173dbc920bdSVladimir Kondratyev 	rb_replace_node(old, new, &root->rb_root);
174dbc920bdSVladimir Kondratyev 	if (root->rb_leftmost == old)
175dbc920bdSVladimir Kondratyev 		root->rb_leftmost = new;
176dbc920bdSVladimir Kondratyev }
177dbc920bdSVladimir Kondratyev 
178*a5cac2e6SVladimir Kondratyev static inline struct rb_node *
179*a5cac2e6SVladimir Kondratyev rb_add_cached(struct rb_node *node, struct rb_root_cached *tree,
180*a5cac2e6SVladimir Kondratyev     bool (*less)(struct rb_node *, const struct rb_node *))
181*a5cac2e6SVladimir Kondratyev {
182*a5cac2e6SVladimir Kondratyev 	struct rb_node **link = &tree->rb_root.rb_node;
183*a5cac2e6SVladimir Kondratyev 	struct rb_node *parent = NULL;
184*a5cac2e6SVladimir Kondratyev 	bool leftmost = true;
185*a5cac2e6SVladimir Kondratyev 
186*a5cac2e6SVladimir Kondratyev 	while (*link != NULL) {
187*a5cac2e6SVladimir Kondratyev 		parent = *link;
188*a5cac2e6SVladimir Kondratyev 		if (less(node, parent)) {
189*a5cac2e6SVladimir Kondratyev 			link = &RB_LEFT(parent, __entry);
190*a5cac2e6SVladimir Kondratyev 		} else {
191*a5cac2e6SVladimir Kondratyev 			link = &RB_RIGHT(parent, __entry);
192*a5cac2e6SVladimir Kondratyev 			leftmost = false;
193*a5cac2e6SVladimir Kondratyev 		}
194*a5cac2e6SVladimir Kondratyev 	}
195*a5cac2e6SVladimir Kondratyev 
196*a5cac2e6SVladimir Kondratyev 	rb_link_node(node, parent, link);
197*a5cac2e6SVladimir Kondratyev 	rb_insert_color_cached(node, tree, leftmost);
198*a5cac2e6SVladimir Kondratyev 
199*a5cac2e6SVladimir Kondratyev 	return (leftmost ? node : NULL);
200*a5cac2e6SVladimir Kondratyev }
201*a5cac2e6SVladimir Kondratyev 
2028d59ecb2SHans Petter Selasky #undef RB_ROOT
2038d59ecb2SHans Petter Selasky #define RB_ROOT		(struct rb_root) { NULL }
204dbc920bdSVladimir Kondratyev #define	RB_ROOT_CACHED	(struct rb_root_cached) { RB_ROOT, NULL }
2058d59ecb2SHans Petter Selasky 
206307f78f3SVladimir Kondratyev #endif	/* _LINUXKPI_LINUX_RBTREE_H_ */
207