1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 Red Black Trees 4 (C) 1999 Andrea Arcangeli <andrea@suse.de> 5 (C) 2002 David Woodhouse <dwmw2@infradead.org> 6 (C) 2012 Michel Lespinasse <walken@google.com> 7 8 9 tools/linux/include/linux/rbtree_augmented.h 10 11 Copied from: 12 linux/include/linux/rbtree_augmented.h 13 */ 14 15 #ifndef _TOOLS_LINUX_RBTREE_AUGMENTED_H 16 #define _TOOLS_LINUX_RBTREE_AUGMENTED_H 17 18 #include <linux/compiler.h> 19 #include <linux/rbtree.h> 20 21 /* 22 * Please note - only struct rb_augment_callbacks and the prototypes for 23 * rb_insert_augmented() and rb_erase_augmented() are intended to be public. 24 * The rest are implementation details you are not expected to depend on. 25 * 26 * See Documentation/core-api/rbtree.rst for documentation and samples. 27 */ 28 29 struct rb_augment_callbacks { 30 void (*propagate)(struct rb_node *node, struct rb_node *stop); 31 void (*copy)(struct rb_node *old, struct rb_node *new); 32 void (*rotate)(struct rb_node *old, struct rb_node *new); 33 }; 34 35 extern void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, 36 void (*augment_rotate)(struct rb_node *old, struct rb_node *new)); 37 38 /* 39 * Fixup the rbtree and update the augmented information when rebalancing. 40 * 41 * On insertion, the user must update the augmented information on the path 42 * leading to the inserted node, then call rb_link_node() as usual and 43 * rb_insert_augmented() instead of the usual rb_insert_color() call. 44 * If rb_insert_augmented() rebalances the rbtree, it will callback into 45 * a user provided function to update the augmented information on the 46 * affected subtrees. 47 */ 48 static inline void 49 rb_insert_augmented(struct rb_node *node, struct rb_root *root, 50 const struct rb_augment_callbacks *augment) 51 { 52 __rb_insert_augmented(node, root, augment->rotate); 53 } 54 55 static inline void 56 rb_insert_augmented_cached(struct rb_node *node, 57 struct rb_root_cached *root, bool newleft, 58 const struct rb_augment_callbacks *augment) 59 { 60 if (newleft) 61 root->rb_leftmost = node; 62 rb_insert_augmented(node, &root->rb_root, augment); 63 } 64 65 /* 66 * Template for declaring augmented rbtree callbacks (generic case) 67 * 68 * RBSTATIC: 'static' or empty 69 * RBNAME: name of the rb_augment_callbacks structure 70 * RBSTRUCT: struct type of the tree nodes 71 * RBFIELD: name of struct rb_node field within RBSTRUCT 72 * RBAUGMENTED: name of field within RBSTRUCT holding data for subtree 73 * RBCOMPUTE: name of function that recomputes the RBAUGMENTED data 74 */ 75 76 #define RB_DECLARE_CALLBACKS(RBSTATIC, RBNAME, \ 77 RBSTRUCT, RBFIELD, RBAUGMENTED, RBCOMPUTE) \ 78 static inline void \ 79 RBNAME ## _propagate(struct rb_node *rb, struct rb_node *stop) \ 80 { \ 81 while (rb != stop) { \ 82 RBSTRUCT *node = rb_entry(rb, RBSTRUCT, RBFIELD); \ 83 if (RBCOMPUTE(node, true)) \ 84 break; \ 85 rb = rb_parent(&node->RBFIELD); \ 86 } \ 87 } \ 88 static inline void \ 89 RBNAME ## _copy(struct rb_node *rb_old, struct rb_node *rb_new) \ 90 { \ 91 RBSTRUCT *old = rb_entry(rb_old, RBSTRUCT, RBFIELD); \ 92 RBSTRUCT *new = rb_entry(rb_new, RBSTRUCT, RBFIELD); \ 93 new->RBAUGMENTED = old->RBAUGMENTED; \ 94 } \ 95 static void \ 96 RBNAME ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new) \ 97 { \ 98 RBSTRUCT *old = rb_entry(rb_old, RBSTRUCT, RBFIELD); \ 99 RBSTRUCT *new = rb_entry(rb_new, RBSTRUCT, RBFIELD); \ 100 new->RBAUGMENTED = old->RBAUGMENTED; \ 101 RBCOMPUTE(old, false); \ 102 } \ 103 RBSTATIC const struct rb_augment_callbacks RBNAME = { \ 104 .propagate = RBNAME ## _propagate, \ 105 .copy = RBNAME ## _copy, \ 106 .rotate = RBNAME ## _rotate \ 107 }; 108 109 /* 110 * Template for declaring augmented rbtree callbacks, 111 * computing RBAUGMENTED scalar as max(RBCOMPUTE(node)) for all subtree nodes. 112 * 113 * RBSTATIC: 'static' or empty 114 * RBNAME: name of the rb_augment_callbacks structure 115 * RBSTRUCT: struct type of the tree nodes 116 * RBFIELD: name of struct rb_node field within RBSTRUCT 117 * RBTYPE: type of the RBAUGMENTED field 118 * RBAUGMENTED: name of RBTYPE field within RBSTRUCT holding data for subtree 119 * RBCOMPUTE: name of function that returns the per-node RBTYPE scalar 120 */ 121 122 #define RB_DECLARE_CALLBACKS_MAX(RBSTATIC, RBNAME, RBSTRUCT, RBFIELD, \ 123 RBTYPE, RBAUGMENTED, RBCOMPUTE) \ 124 static inline bool RBNAME ## _compute_max(RBSTRUCT *node, bool exit) \ 125 { \ 126 RBSTRUCT *child; \ 127 RBTYPE max = RBCOMPUTE(node); \ 128 if (node->RBFIELD.rb_left) { \ 129 child = rb_entry(node->RBFIELD.rb_left, RBSTRUCT, RBFIELD); \ 130 if (child->RBAUGMENTED > max) \ 131 max = child->RBAUGMENTED; \ 132 } \ 133 if (node->RBFIELD.rb_right) { \ 134 child = rb_entry(node->RBFIELD.rb_right, RBSTRUCT, RBFIELD); \ 135 if (child->RBAUGMENTED > max) \ 136 max = child->RBAUGMENTED; \ 137 } \ 138 if (exit && node->RBAUGMENTED == max) \ 139 return true; \ 140 node->RBAUGMENTED = max; \ 141 return false; \ 142 } \ 143 RB_DECLARE_CALLBACKS(RBSTATIC, RBNAME, \ 144 RBSTRUCT, RBFIELD, RBAUGMENTED, RBNAME ## _compute_max) 145 146 147 #define RB_RED 0 148 #define RB_BLACK 1 149 150 #define __rb_parent(pc) ((struct rb_node *)(pc & ~3)) 151 152 #define __rb_color(pc) ((pc) & 1) 153 #define __rb_is_black(pc) __rb_color(pc) 154 #define __rb_is_red(pc) (!__rb_color(pc)) 155 #define rb_color(rb) __rb_color((rb)->__rb_parent_color) 156 #define rb_is_red(rb) __rb_is_red((rb)->__rb_parent_color) 157 #define rb_is_black(rb) __rb_is_black((rb)->__rb_parent_color) 158 159 static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) 160 { 161 rb->__rb_parent_color = rb_color(rb) + (unsigned long)p; 162 } 163 164 static inline void rb_set_parent_color(struct rb_node *rb, 165 struct rb_node *p, int color) 166 { 167 rb->__rb_parent_color = (unsigned long)p + color; 168 } 169 170 static inline void 171 __rb_change_child(struct rb_node *old, struct rb_node *new, 172 struct rb_node *parent, struct rb_root *root) 173 { 174 if (parent) { 175 if (parent->rb_left == old) 176 WRITE_ONCE(parent->rb_left, new); 177 else 178 WRITE_ONCE(parent->rb_right, new); 179 } else 180 WRITE_ONCE(root->rb_node, new); 181 } 182 183 extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root, 184 void (*augment_rotate)(struct rb_node *old, struct rb_node *new)); 185 186 static __always_inline struct rb_node * 187 __rb_erase_augmented(struct rb_node *node, struct rb_root *root, 188 const struct rb_augment_callbacks *augment) 189 { 190 struct rb_node *child = node->rb_right; 191 struct rb_node *tmp = node->rb_left; 192 struct rb_node *parent, *rebalance; 193 unsigned long pc; 194 195 if (!tmp) { 196 /* 197 * Case 1: node to erase has no more than 1 child (easy!) 198 * 199 * Note that if there is one child it must be red due to 5) 200 * and node must be black due to 4). We adjust colors locally 201 * so as to bypass __rb_erase_color() later on. 202 */ 203 pc = node->__rb_parent_color; 204 parent = __rb_parent(pc); 205 __rb_change_child(node, child, parent, root); 206 if (child) { 207 child->__rb_parent_color = pc; 208 rebalance = NULL; 209 } else 210 rebalance = __rb_is_black(pc) ? parent : NULL; 211 tmp = parent; 212 } else if (!child) { 213 /* Still case 1, but this time the child is node->rb_left */ 214 tmp->__rb_parent_color = pc = node->__rb_parent_color; 215 parent = __rb_parent(pc); 216 __rb_change_child(node, tmp, parent, root); 217 rebalance = NULL; 218 tmp = parent; 219 } else { 220 struct rb_node *successor = child, *child2; 221 222 tmp = child->rb_left; 223 if (!tmp) { 224 /* 225 * Case 2: node's successor is its right child 226 * 227 * (n) (s) 228 * / \ / \ 229 * (x) (s) -> (x) (c) 230 * \ 231 * (c) 232 */ 233 parent = successor; 234 child2 = successor->rb_right; 235 236 augment->copy(node, successor); 237 } else { 238 /* 239 * Case 3: node's successor is leftmost under 240 * node's right child subtree 241 * 242 * (n) (s) 243 * / \ / \ 244 * (x) (y) -> (x) (y) 245 * / / 246 * (p) (p) 247 * / / 248 * (s) (c) 249 * \ 250 * (c) 251 */ 252 do { 253 parent = successor; 254 successor = tmp; 255 tmp = tmp->rb_left; 256 } while (tmp); 257 child2 = successor->rb_right; 258 WRITE_ONCE(parent->rb_left, child2); 259 WRITE_ONCE(successor->rb_right, child); 260 rb_set_parent(child, successor); 261 262 augment->copy(node, successor); 263 augment->propagate(parent, successor); 264 } 265 266 tmp = node->rb_left; 267 WRITE_ONCE(successor->rb_left, tmp); 268 rb_set_parent(tmp, successor); 269 270 pc = node->__rb_parent_color; 271 tmp = __rb_parent(pc); 272 __rb_change_child(node, successor, tmp, root); 273 274 if (child2) { 275 successor->__rb_parent_color = pc; 276 rb_set_parent_color(child2, parent, RB_BLACK); 277 rebalance = NULL; 278 } else { 279 unsigned long pc2 = successor->__rb_parent_color; 280 successor->__rb_parent_color = pc; 281 rebalance = __rb_is_black(pc2) ? parent : NULL; 282 } 283 tmp = successor; 284 } 285 286 augment->propagate(tmp, NULL); 287 return rebalance; 288 } 289 290 static __always_inline void 291 rb_erase_augmented(struct rb_node *node, struct rb_root *root, 292 const struct rb_augment_callbacks *augment) 293 { 294 struct rb_node *rebalance = __rb_erase_augmented(node, root, augment); 295 if (rebalance) 296 __rb_erase_color(rebalance, root, augment->rotate); 297 } 298 299 static __always_inline void 300 rb_erase_augmented_cached(struct rb_node *node, struct rb_root_cached *root, 301 const struct rb_augment_callbacks *augment) 302 { 303 if (root->rb_leftmost == node) 304 root->rb_leftmost = rb_next(node); 305 rb_erase_augmented(node, &root->rb_root, augment); 306 } 307 308 #endif /* _TOOLS_LINUX_RBTREE_AUGMENTED_H */ 309
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.