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