diff options
author | Davidlohr Bueso <dave@stgolabs.net> | 2018-12-06 14:18:13 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2019-01-25 09:12:09 -0500 |
commit | 3aef2cad5d51ee66d2a614dd2f70cb34c74caf77 (patch) | |
tree | b52f1d67040ec37a2268f91061d33fa6e38e20c6 /tools | |
parent | 95420d338e2d802ea0dce4d770d3292beb587f71 (diff) |
tools: Update rbtree implementation
There have been a number of changes in the kernel's rbrtee
implementation, including loose lockless searching guarantees and
rb_root_cached, which later patches will use as an optimization.
Signed-off-by: Davidlohr Bueso <dbueso@suse.de>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: http://lkml.kernel.org/r/20181206191819.30182-2-dave@stgolabs.net
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/include/linux/rbtree.h | 52 | ||||
-rw-r--r-- | tools/include/linux/rbtree_augmented.h | 60 | ||||
-rw-r--r-- | tools/lib/rbtree.c | 178 |
3 files changed, 229 insertions, 61 deletions
diff --git a/tools/include/linux/rbtree.h b/tools/include/linux/rbtree.h index 112582253dd0..8e9ed4786269 100644 --- a/tools/include/linux/rbtree.h +++ b/tools/include/linux/rbtree.h | |||
@@ -43,13 +43,28 @@ struct rb_root { | |||
43 | struct rb_node *rb_node; | 43 | struct rb_node *rb_node; |
44 | }; | 44 | }; |
45 | 45 | ||
46 | /* | ||
47 | * Leftmost-cached rbtrees. | ||
48 | * | ||
49 | * We do not cache the rightmost node based on footprint | ||
50 | * size vs number of potential users that could benefit | ||
51 | * from O(1) rb_last(). Just not worth it, users that want | ||
52 | * this feature can always implement the logic explicitly. | ||
53 | * Furthermore, users that want to cache both pointers may | ||
54 | * find it a bit asymmetric, but that's ok. | ||
55 | */ | ||
56 | struct rb_root_cached { | ||
57 | struct rb_root rb_root; | ||
58 | struct rb_node *rb_leftmost; | ||
59 | }; | ||
46 | 60 | ||
47 | #define rb_parent(r) ((struct rb_node *)((r)->__rb_parent_color & ~3)) | 61 | #define rb_parent(r) ((struct rb_node *)((r)->__rb_parent_color & ~3)) |
48 | 62 | ||
49 | #define RB_ROOT (struct rb_root) { NULL, } | 63 | #define RB_ROOT (struct rb_root) { NULL, } |
64 | #define RB_ROOT_CACHED (struct rb_root_cached) { {NULL, }, NULL } | ||
50 | #define rb_entry(ptr, type, member) container_of(ptr, type, member) | 65 | #define rb_entry(ptr, type, member) container_of(ptr, type, member) |
51 | 66 | ||
52 | #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) | 67 | #define RB_EMPTY_ROOT(root) (READ_ONCE((root)->rb_node) == NULL) |
53 | 68 | ||
54 | /* 'empty' nodes are nodes that are known not to be inserted in an rbtree */ | 69 | /* 'empty' nodes are nodes that are known not to be inserted in an rbtree */ |
55 | #define RB_EMPTY_NODE(node) \ | 70 | #define RB_EMPTY_NODE(node) \ |
@@ -68,6 +83,12 @@ extern struct rb_node *rb_prev(const struct rb_node *); | |||
68 | extern struct rb_node *rb_first(const struct rb_root *); | 83 | extern struct rb_node *rb_first(const struct rb_root *); |
69 | extern struct rb_node *rb_last(const struct rb_root *); | 84 | extern struct rb_node *rb_last(const struct rb_root *); |
70 | 85 | ||
86 | extern void rb_insert_color_cached(struct rb_node *, | ||
87 | struct rb_root_cached *, bool); | ||
88 | extern void rb_erase_cached(struct rb_node *node, struct rb_root_cached *); | ||
89 | /* Same as rb_first(), but O(1) */ | ||
90 | #define rb_first_cached(root) (root)->rb_leftmost | ||
91 | |||
71 | /* Postorder iteration - always visit the parent after its children */ | 92 | /* Postorder iteration - always visit the parent after its children */ |
72 | extern struct rb_node *rb_first_postorder(const struct rb_root *); | 93 | extern struct rb_node *rb_first_postorder(const struct rb_root *); |
73 | extern struct rb_node *rb_next_postorder(const struct rb_node *); | 94 | extern struct rb_node *rb_next_postorder(const struct rb_node *); |
@@ -75,6 +96,8 @@ extern struct rb_node *rb_next_postorder(const struct rb_node *); | |||
75 | /* Fast replacement of a single node without remove/rebalance/add/rebalance */ | 96 | /* Fast replacement of a single node without remove/rebalance/add/rebalance */ |
76 | extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, | 97 | extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, |
77 | struct rb_root *root); | 98 | struct rb_root *root); |
99 | extern void rb_replace_node_cached(struct rb_node *victim, struct rb_node *new, | ||
100 | struct rb_root_cached *root); | ||
78 | 101 | ||
79 | static inline void rb_link_node(struct rb_node *node, struct rb_node *parent, | 102 | static inline void rb_link_node(struct rb_node *node, struct rb_node *parent, |
80 | struct rb_node **rb_link) | 103 | struct rb_node **rb_link) |
@@ -90,12 +113,29 @@ static inline void rb_link_node(struct rb_node *node, struct rb_node *parent, | |||
90 | ____ptr ? rb_entry(____ptr, type, member) : NULL; \ | 113 | ____ptr ? rb_entry(____ptr, type, member) : NULL; \ |
91 | }) | 114 | }) |
92 | 115 | ||
93 | 116 | /** | |
94 | /* | 117 | * rbtree_postorder_for_each_entry_safe - iterate in post-order over rb_root of |
95 | * Handy for checking that we are not deleting an entry that is | 118 | * given type allowing the backing memory of @pos to be invalidated |
96 | * already in a list, found in block/{blk-throttle,cfq-iosched}.c, | 119 | * |
97 | * probably should be moved to lib/rbtree.c... | 120 | * @pos: the 'type *' to use as a loop cursor. |
121 | * @n: another 'type *' to use as temporary storage | ||
122 | * @root: 'rb_root *' of the rbtree. | ||
123 | * @field: the name of the rb_node field within 'type'. | ||
124 | * | ||
125 | * rbtree_postorder_for_each_entry_safe() provides a similar guarantee as | ||
126 | * list_for_each_entry_safe() and allows the iteration to continue independent | ||
127 | * of changes to @pos by the body of the loop. | ||
128 | * | ||
129 | * Note, however, that it cannot handle other modifications that re-order the | ||
130 | * rbtree it is iterating over. This includes calling rb_erase() on @pos, as | ||
131 | * rb_erase() may rebalance the tree, causing us to miss some nodes. | ||
98 | */ | 132 | */ |
133 | #define rbtree_postorder_for_each_entry_safe(pos, n, root, field) \ | ||
134 | for (pos = rb_entry_safe(rb_first_postorder(root), typeof(*pos), field); \ | ||
135 | pos && ({ n = rb_entry_safe(rb_next_postorder(&pos->field), \ | ||
136 | typeof(*pos), field); 1; }); \ | ||
137 | pos = n) | ||
138 | |||
99 | static inline void rb_erase_init(struct rb_node *n, struct rb_root *root) | 139 | static inline void rb_erase_init(struct rb_node *n, struct rb_root *root) |
100 | { | 140 | { |
101 | rb_erase(n, root); | 141 | rb_erase(n, root); |
diff --git a/tools/include/linux/rbtree_augmented.h b/tools/include/linux/rbtree_augmented.h index 43be941db695..d008e1404580 100644 --- a/tools/include/linux/rbtree_augmented.h +++ b/tools/include/linux/rbtree_augmented.h | |||
@@ -44,7 +44,9 @@ struct rb_augment_callbacks { | |||
44 | void (*rotate)(struct rb_node *old, struct rb_node *new); | 44 | void (*rotate)(struct rb_node *old, struct rb_node *new); |
45 | }; | 45 | }; |
46 | 46 | ||
47 | extern void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, | 47 | extern void __rb_insert_augmented(struct rb_node *node, |
48 | struct rb_root *root, | ||
49 | bool newleft, struct rb_node **leftmost, | ||
48 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)); | 50 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)); |
49 | /* | 51 | /* |
50 | * Fixup the rbtree and update the augmented information when rebalancing. | 52 | * Fixup the rbtree and update the augmented information when rebalancing. |
@@ -60,7 +62,16 @@ static inline void | |||
60 | rb_insert_augmented(struct rb_node *node, struct rb_root *root, | 62 | rb_insert_augmented(struct rb_node *node, struct rb_root *root, |
61 | const struct rb_augment_callbacks *augment) | 63 | const struct rb_augment_callbacks *augment) |
62 | { | 64 | { |
63 | __rb_insert_augmented(node, root, augment->rotate); | 65 | __rb_insert_augmented(node, root, false, NULL, augment->rotate); |
66 | } | ||
67 | |||
68 | static inline void | ||
69 | rb_insert_augmented_cached(struct rb_node *node, | ||
70 | struct rb_root_cached *root, bool newleft, | ||
71 | const struct rb_augment_callbacks *augment) | ||
72 | { | ||
73 | __rb_insert_augmented(node, &root->rb_root, | ||
74 | newleft, &root->rb_leftmost, augment->rotate); | ||
64 | } | 75 | } |
65 | 76 | ||
66 | #define RB_DECLARE_CALLBACKS(rbstatic, rbname, rbstruct, rbfield, \ | 77 | #define RB_DECLARE_CALLBACKS(rbstatic, rbname, rbstruct, rbfield, \ |
@@ -93,7 +104,9 @@ rbname ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new) \ | |||
93 | old->rbaugmented = rbcompute(old); \ | 104 | old->rbaugmented = rbcompute(old); \ |
94 | } \ | 105 | } \ |
95 | rbstatic const struct rb_augment_callbacks rbname = { \ | 106 | rbstatic const struct rb_augment_callbacks rbname = { \ |
96 | rbname ## _propagate, rbname ## _copy, rbname ## _rotate \ | 107 | .propagate = rbname ## _propagate, \ |
108 | .copy = rbname ## _copy, \ | ||
109 | .rotate = rbname ## _rotate \ | ||
97 | }; | 110 | }; |
98 | 111 | ||
99 | 112 | ||
@@ -126,11 +139,11 @@ __rb_change_child(struct rb_node *old, struct rb_node *new, | |||
126 | { | 139 | { |
127 | if (parent) { | 140 | if (parent) { |
128 | if (parent->rb_left == old) | 141 | if (parent->rb_left == old) |
129 | parent->rb_left = new; | 142 | WRITE_ONCE(parent->rb_left, new); |
130 | else | 143 | else |
131 | parent->rb_right = new; | 144 | WRITE_ONCE(parent->rb_right, new); |
132 | } else | 145 | } else |
133 | root->rb_node = new; | 146 | WRITE_ONCE(root->rb_node, new); |
134 | } | 147 | } |
135 | 148 | ||
136 | extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root, | 149 | extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root, |
@@ -138,12 +151,17 @@ extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root, | |||
138 | 151 | ||
139 | static __always_inline struct rb_node * | 152 | static __always_inline struct rb_node * |
140 | __rb_erase_augmented(struct rb_node *node, struct rb_root *root, | 153 | __rb_erase_augmented(struct rb_node *node, struct rb_root *root, |
154 | struct rb_node **leftmost, | ||
141 | const struct rb_augment_callbacks *augment) | 155 | const struct rb_augment_callbacks *augment) |
142 | { | 156 | { |
143 | struct rb_node *child = node->rb_right, *tmp = node->rb_left; | 157 | struct rb_node *child = node->rb_right; |
158 | struct rb_node *tmp = node->rb_left; | ||
144 | struct rb_node *parent, *rebalance; | 159 | struct rb_node *parent, *rebalance; |
145 | unsigned long pc; | 160 | unsigned long pc; |
146 | 161 | ||
162 | if (leftmost && node == *leftmost) | ||
163 | *leftmost = rb_next(node); | ||
164 | |||
147 | if (!tmp) { | 165 | if (!tmp) { |
148 | /* | 166 | /* |
149 | * Case 1: node to erase has no more than 1 child (easy!) | 167 | * Case 1: node to erase has no more than 1 child (easy!) |
@@ -170,6 +188,7 @@ __rb_erase_augmented(struct rb_node *node, struct rb_root *root, | |||
170 | tmp = parent; | 188 | tmp = parent; |
171 | } else { | 189 | } else { |
172 | struct rb_node *successor = child, *child2; | 190 | struct rb_node *successor = child, *child2; |
191 | |||
173 | tmp = child->rb_left; | 192 | tmp = child->rb_left; |
174 | if (!tmp) { | 193 | if (!tmp) { |
175 | /* | 194 | /* |
@@ -183,6 +202,7 @@ __rb_erase_augmented(struct rb_node *node, struct rb_root *root, | |||
183 | */ | 202 | */ |
184 | parent = successor; | 203 | parent = successor; |
185 | child2 = successor->rb_right; | 204 | child2 = successor->rb_right; |
205 | |||
186 | augment->copy(node, successor); | 206 | augment->copy(node, successor); |
187 | } else { | 207 | } else { |
188 | /* | 208 | /* |
@@ -204,19 +224,23 @@ __rb_erase_augmented(struct rb_node *node, struct rb_root *root, | |||
204 | successor = tmp; | 224 | successor = tmp; |
205 | tmp = tmp->rb_left; | 225 | tmp = tmp->rb_left; |
206 | } while (tmp); | 226 | } while (tmp); |
207 | parent->rb_left = child2 = successor->rb_right; | 227 | child2 = successor->rb_right; |
208 | successor->rb_right = child; | 228 | WRITE_ONCE(parent->rb_left, child2); |
229 | WRITE_ONCE(successor->rb_right, child); | ||
209 | rb_set_parent(child, successor); | 230 | rb_set_parent(child, successor); |
231 | |||
210 | augment->copy(node, successor); | 232 | augment->copy(node, successor); |
211 | augment->propagate(parent, successor); | 233 | augment->propagate(parent, successor); |
212 | } | 234 | } |
213 | 235 | ||
214 | successor->rb_left = tmp = node->rb_left; | 236 | tmp = node->rb_left; |
237 | WRITE_ONCE(successor->rb_left, tmp); | ||
215 | rb_set_parent(tmp, successor); | 238 | rb_set_parent(tmp, successor); |
216 | 239 | ||
217 | pc = node->__rb_parent_color; | 240 | pc = node->__rb_parent_color; |
218 | tmp = __rb_parent(pc); | 241 | tmp = __rb_parent(pc); |
219 | __rb_change_child(node, successor, tmp, root); | 242 | __rb_change_child(node, successor, tmp, root); |
243 | |||
220 | if (child2) { | 244 | if (child2) { |
221 | successor->__rb_parent_color = pc; | 245 | successor->__rb_parent_color = pc; |
222 | rb_set_parent_color(child2, parent, RB_BLACK); | 246 | rb_set_parent_color(child2, parent, RB_BLACK); |
@@ -237,9 +261,21 @@ static __always_inline void | |||
237 | rb_erase_augmented(struct rb_node *node, struct rb_root *root, | 261 | rb_erase_augmented(struct rb_node *node, struct rb_root *root, |
238 | const struct rb_augment_callbacks *augment) | 262 | const struct rb_augment_callbacks *augment) |
239 | { | 263 | { |
240 | struct rb_node *rebalance = __rb_erase_augmented(node, root, augment); | 264 | struct rb_node *rebalance = __rb_erase_augmented(node, root, |
265 | NULL, augment); | ||
241 | if (rebalance) | 266 | if (rebalance) |
242 | __rb_erase_color(rebalance, root, augment->rotate); | 267 | __rb_erase_color(rebalance, root, augment->rotate); |
243 | } | 268 | } |
244 | 269 | ||
245 | #endif /* _TOOLS_LINUX_RBTREE_AUGMENTED_H */ | 270 | static __always_inline void |
271 | rb_erase_augmented_cached(struct rb_node *node, struct rb_root_cached *root, | ||
272 | const struct rb_augment_callbacks *augment) | ||
273 | { | ||
274 | struct rb_node *rebalance = __rb_erase_augmented(node, &root->rb_root, | ||
275 | &root->rb_leftmost, | ||
276 | augment); | ||
277 | if (rebalance) | ||
278 | __rb_erase_color(rebalance, &root->rb_root, augment->rotate); | ||
279 | } | ||
280 | |||
281 | #endif /* _TOOLS_LINUX_RBTREE_AUGMENTED_H */ | ||
diff --git a/tools/lib/rbtree.c b/tools/lib/rbtree.c index 17c2b596f043..904adb70a4f0 100644 --- a/tools/lib/rbtree.c +++ b/tools/lib/rbtree.c | |||
@@ -22,6 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/rbtree_augmented.h> | 24 | #include <linux/rbtree_augmented.h> |
25 | #include <linux/export.h> | ||
25 | 26 | ||
26 | /* | 27 | /* |
27 | * red-black trees properties: http://en.wikipedia.org/wiki/Rbtree | 28 | * red-black trees properties: http://en.wikipedia.org/wiki/Rbtree |
@@ -43,6 +44,30 @@ | |||
43 | * parentheses and have some accompanying text comment. | 44 | * parentheses and have some accompanying text comment. |
44 | */ | 45 | */ |
45 | 46 | ||
47 | /* | ||
48 | * Notes on lockless lookups: | ||
49 | * | ||
50 | * All stores to the tree structure (rb_left and rb_right) must be done using | ||
51 | * WRITE_ONCE(). And we must not inadvertently cause (temporary) loops in the | ||
52 | * tree structure as seen in program order. | ||
53 | * | ||
54 | * These two requirements will allow lockless iteration of the tree -- not | ||
55 | * correct iteration mind you, tree rotations are not atomic so a lookup might | ||
56 | * miss entire subtrees. | ||
57 | * | ||
58 | * But they do guarantee that any such traversal will only see valid elements | ||
59 | * and that it will indeed complete -- does not get stuck in a loop. | ||
60 | * | ||
61 | * It also guarantees that if the lookup returns an element it is the 'correct' | ||
62 | * one. But not returning an element does _NOT_ mean it's not present. | ||
63 | * | ||
64 | * NOTE: | ||
65 | * | ||
66 | * Stores to __rb_parent_color are not important for simple lookups so those | ||
67 | * are left undone as of now. Nor did I check for loops involving parent | ||
68 | * pointers. | ||
69 | */ | ||
70 | |||
46 | static inline void rb_set_black(struct rb_node *rb) | 71 | static inline void rb_set_black(struct rb_node *rb) |
47 | { | 72 | { |
48 | rb->__rb_parent_color |= RB_BLACK; | 73 | rb->__rb_parent_color |= RB_BLACK; |
@@ -70,22 +95,35 @@ __rb_rotate_set_parents(struct rb_node *old, struct rb_node *new, | |||
70 | 95 | ||
71 | static __always_inline void | 96 | static __always_inline void |
72 | __rb_insert(struct rb_node *node, struct rb_root *root, | 97 | __rb_insert(struct rb_node *node, struct rb_root *root, |
98 | bool newleft, struct rb_node **leftmost, | ||
73 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) | 99 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) |
74 | { | 100 | { |
75 | struct rb_node *parent = rb_red_parent(node), *gparent, *tmp; | 101 | struct rb_node *parent = rb_red_parent(node), *gparent, *tmp; |
76 | 102 | ||
103 | if (newleft) | ||
104 | *leftmost = node; | ||
105 | |||
77 | while (true) { | 106 | while (true) { |
78 | /* | 107 | /* |
79 | * Loop invariant: node is red | 108 | * Loop invariant: node is red. |
80 | * | ||
81 | * If there is a black parent, we are done. | ||
82 | * Otherwise, take some corrective action as we don't | ||
83 | * want a red root or two consecutive red nodes. | ||
84 | */ | 109 | */ |
85 | if (!parent) { | 110 | if (unlikely(!parent)) { |
111 | /* | ||
112 | * The inserted node is root. Either this is the | ||
113 | * first node, or we recursed at Case 1 below and | ||
114 | * are no longer violating 4). | ||
115 | */ | ||
86 | rb_set_parent_color(node, NULL, RB_BLACK); | 116 | rb_set_parent_color(node, NULL, RB_BLACK); |
87 | break; | 117 | break; |
88 | } else if (rb_is_black(parent)) | 118 | } |
119 | |||
120 | /* | ||
121 | * If there is a black parent, we are done. | ||
122 | * Otherwise, take some corrective action as, | ||
123 | * per 4), we don't want a red root or two | ||
124 | * consecutive red nodes. | ||
125 | */ | ||
126 | if(rb_is_black(parent)) | ||
89 | break; | 127 | break; |
90 | 128 | ||
91 | gparent = rb_red_parent(parent); | 129 | gparent = rb_red_parent(parent); |
@@ -94,7 +132,7 @@ __rb_insert(struct rb_node *node, struct rb_root *root, | |||
94 | if (parent != tmp) { /* parent == gparent->rb_left */ | 132 | if (parent != tmp) { /* parent == gparent->rb_left */ |
95 | if (tmp && rb_is_red(tmp)) { | 133 | if (tmp && rb_is_red(tmp)) { |
96 | /* | 134 | /* |
97 | * Case 1 - color flips | 135 | * Case 1 - node's uncle is red (color flips). |
98 | * | 136 | * |
99 | * G g | 137 | * G g |
100 | * / \ / \ | 138 | * / \ / \ |
@@ -117,7 +155,8 @@ __rb_insert(struct rb_node *node, struct rb_root *root, | |||
117 | tmp = parent->rb_right; | 155 | tmp = parent->rb_right; |
118 | if (node == tmp) { | 156 | if (node == tmp) { |
119 | /* | 157 | /* |
120 | * Case 2 - left rotate at parent | 158 | * Case 2 - node's uncle is black and node is |
159 | * the parent's right child (left rotate at parent). | ||
121 | * | 160 | * |
122 | * G G | 161 | * G G |
123 | * / \ / \ | 162 | * / \ / \ |
@@ -128,8 +167,9 @@ __rb_insert(struct rb_node *node, struct rb_root *root, | |||
128 | * This still leaves us in violation of 4), the | 167 | * This still leaves us in violation of 4), the |
129 | * continuation into Case 3 will fix that. | 168 | * continuation into Case 3 will fix that. |
130 | */ | 169 | */ |
131 | parent->rb_right = tmp = node->rb_left; | 170 | tmp = node->rb_left; |
132 | node->rb_left = parent; | 171 | WRITE_ONCE(parent->rb_right, tmp); |
172 | WRITE_ONCE(node->rb_left, parent); | ||
133 | if (tmp) | 173 | if (tmp) |
134 | rb_set_parent_color(tmp, parent, | 174 | rb_set_parent_color(tmp, parent, |
135 | RB_BLACK); | 175 | RB_BLACK); |
@@ -140,7 +180,8 @@ __rb_insert(struct rb_node *node, struct rb_root *root, | |||
140 | } | 180 | } |
141 | 181 | ||
142 | /* | 182 | /* |
143 | * Case 3 - right rotate at gparent | 183 | * Case 3 - node's uncle is black and node is |
184 | * the parent's left child (right rotate at gparent). | ||
144 | * | 185 | * |
145 | * G P | 186 | * G P |
146 | * / \ / \ | 187 | * / \ / \ |
@@ -148,8 +189,8 @@ __rb_insert(struct rb_node *node, struct rb_root *root, | |||
148 | * / \ | 189 | * / \ |
149 | * n U | 190 | * n U |
150 | */ | 191 | */ |
151 | gparent->rb_left = tmp; /* == parent->rb_right */ | 192 | WRITE_ONCE(gparent->rb_left, tmp); /* == parent->rb_right */ |
152 | parent->rb_right = gparent; | 193 | WRITE_ONCE(parent->rb_right, gparent); |
153 | if (tmp) | 194 | if (tmp) |
154 | rb_set_parent_color(tmp, gparent, RB_BLACK); | 195 | rb_set_parent_color(tmp, gparent, RB_BLACK); |
155 | __rb_rotate_set_parents(gparent, parent, root, RB_RED); | 196 | __rb_rotate_set_parents(gparent, parent, root, RB_RED); |
@@ -170,8 +211,9 @@ __rb_insert(struct rb_node *node, struct rb_root *root, | |||
170 | tmp = parent->rb_left; | 211 | tmp = parent->rb_left; |
171 | if (node == tmp) { | 212 | if (node == tmp) { |
172 | /* Case 2 - right rotate at parent */ | 213 | /* Case 2 - right rotate at parent */ |
173 | parent->rb_left = tmp = node->rb_right; | 214 | tmp = node->rb_right; |
174 | node->rb_right = parent; | 215 | WRITE_ONCE(parent->rb_left, tmp); |
216 | WRITE_ONCE(node->rb_right, parent); | ||
175 | if (tmp) | 217 | if (tmp) |
176 | rb_set_parent_color(tmp, parent, | 218 | rb_set_parent_color(tmp, parent, |
177 | RB_BLACK); | 219 | RB_BLACK); |
@@ -182,8 +224,8 @@ __rb_insert(struct rb_node *node, struct rb_root *root, | |||
182 | } | 224 | } |
183 | 225 | ||
184 | /* Case 3 - left rotate at gparent */ | 226 | /* Case 3 - left rotate at gparent */ |
185 | gparent->rb_right = tmp; /* == parent->rb_left */ | 227 | WRITE_ONCE(gparent->rb_right, tmp); /* == parent->rb_left */ |
186 | parent->rb_left = gparent; | 228 | WRITE_ONCE(parent->rb_left, gparent); |
187 | if (tmp) | 229 | if (tmp) |
188 | rb_set_parent_color(tmp, gparent, RB_BLACK); | 230 | rb_set_parent_color(tmp, gparent, RB_BLACK); |
189 | __rb_rotate_set_parents(gparent, parent, root, RB_RED); | 231 | __rb_rotate_set_parents(gparent, parent, root, RB_RED); |
@@ -223,8 +265,9 @@ ____rb_erase_color(struct rb_node *parent, struct rb_root *root, | |||
223 | * / \ / \ | 265 | * / \ / \ |
224 | * Sl Sr N Sl | 266 | * Sl Sr N Sl |
225 | */ | 267 | */ |
226 | parent->rb_right = tmp1 = sibling->rb_left; | 268 | tmp1 = sibling->rb_left; |
227 | sibling->rb_left = parent; | 269 | WRITE_ONCE(parent->rb_right, tmp1); |
270 | WRITE_ONCE(sibling->rb_left, parent); | ||
228 | rb_set_parent_color(tmp1, parent, RB_BLACK); | 271 | rb_set_parent_color(tmp1, parent, RB_BLACK); |
229 | __rb_rotate_set_parents(parent, sibling, root, | 272 | __rb_rotate_set_parents(parent, sibling, root, |
230 | RB_RED); | 273 | RB_RED); |
@@ -268,15 +311,31 @@ ____rb_erase_color(struct rb_node *parent, struct rb_root *root, | |||
268 | * | 311 | * |
269 | * (p) (p) | 312 | * (p) (p) |
270 | * / \ / \ | 313 | * / \ / \ |
271 | * N S --> N Sl | 314 | * N S --> N sl |
272 | * / \ \ | 315 | * / \ \ |
273 | * sl Sr s | 316 | * sl Sr S |
274 | * \ | 317 | * \ |
275 | * Sr | 318 | * Sr |
319 | * | ||
320 | * Note: p might be red, and then both | ||
321 | * p and sl are red after rotation(which | ||
322 | * breaks property 4). This is fixed in | ||
323 | * Case 4 (in __rb_rotate_set_parents() | ||
324 | * which set sl the color of p | ||
325 | * and set p RB_BLACK) | ||
326 | * | ||
327 | * (p) (sl) | ||
328 | * / \ / \ | ||
329 | * N sl --> P S | ||
330 | * \ / \ | ||
331 | * S N Sr | ||
332 | * \ | ||
333 | * Sr | ||
276 | */ | 334 | */ |
277 | sibling->rb_left = tmp1 = tmp2->rb_right; | 335 | tmp1 = tmp2->rb_right; |
278 | tmp2->rb_right = sibling; | 336 | WRITE_ONCE(sibling->rb_left, tmp1); |
279 | parent->rb_right = tmp2; | 337 | WRITE_ONCE(tmp2->rb_right, sibling); |
338 | WRITE_ONCE(parent->rb_right, tmp2); | ||
280 | if (tmp1) | 339 | if (tmp1) |
281 | rb_set_parent_color(tmp1, sibling, | 340 | rb_set_parent_color(tmp1, sibling, |
282 | RB_BLACK); | 341 | RB_BLACK); |
@@ -296,8 +355,9 @@ ____rb_erase_color(struct rb_node *parent, struct rb_root *root, | |||
296 | * / \ / \ | 355 | * / \ / \ |
297 | * (sl) sr N (sl) | 356 | * (sl) sr N (sl) |
298 | */ | 357 | */ |
299 | parent->rb_right = tmp2 = sibling->rb_left; | 358 | tmp2 = sibling->rb_left; |
300 | sibling->rb_left = parent; | 359 | WRITE_ONCE(parent->rb_right, tmp2); |
360 | WRITE_ONCE(sibling->rb_left, parent); | ||
301 | rb_set_parent_color(tmp1, sibling, RB_BLACK); | 361 | rb_set_parent_color(tmp1, sibling, RB_BLACK); |
302 | if (tmp2) | 362 | if (tmp2) |
303 | rb_set_parent(tmp2, parent); | 363 | rb_set_parent(tmp2, parent); |
@@ -309,8 +369,9 @@ ____rb_erase_color(struct rb_node *parent, struct rb_root *root, | |||
309 | sibling = parent->rb_left; | 369 | sibling = parent->rb_left; |
310 | if (rb_is_red(sibling)) { | 370 | if (rb_is_red(sibling)) { |
311 | /* Case 1 - right rotate at parent */ | 371 | /* Case 1 - right rotate at parent */ |
312 | parent->rb_left = tmp1 = sibling->rb_right; | 372 | tmp1 = sibling->rb_right; |
313 | sibling->rb_right = parent; | 373 | WRITE_ONCE(parent->rb_left, tmp1); |
374 | WRITE_ONCE(sibling->rb_right, parent); | ||
314 | rb_set_parent_color(tmp1, parent, RB_BLACK); | 375 | rb_set_parent_color(tmp1, parent, RB_BLACK); |
315 | __rb_rotate_set_parents(parent, sibling, root, | 376 | __rb_rotate_set_parents(parent, sibling, root, |
316 | RB_RED); | 377 | RB_RED); |
@@ -334,10 +395,11 @@ ____rb_erase_color(struct rb_node *parent, struct rb_root *root, | |||
334 | } | 395 | } |
335 | break; | 396 | break; |
336 | } | 397 | } |
337 | /* Case 3 - right rotate at sibling */ | 398 | /* Case 3 - left rotate at sibling */ |
338 | sibling->rb_right = tmp1 = tmp2->rb_left; | 399 | tmp1 = tmp2->rb_left; |
339 | tmp2->rb_left = sibling; | 400 | WRITE_ONCE(sibling->rb_right, tmp1); |
340 | parent->rb_left = tmp2; | 401 | WRITE_ONCE(tmp2->rb_left, sibling); |
402 | WRITE_ONCE(parent->rb_left, tmp2); | ||
341 | if (tmp1) | 403 | if (tmp1) |
342 | rb_set_parent_color(tmp1, sibling, | 404 | rb_set_parent_color(tmp1, sibling, |
343 | RB_BLACK); | 405 | RB_BLACK); |
@@ -345,9 +407,10 @@ ____rb_erase_color(struct rb_node *parent, struct rb_root *root, | |||
345 | tmp1 = sibling; | 407 | tmp1 = sibling; |
346 | sibling = tmp2; | 408 | sibling = tmp2; |
347 | } | 409 | } |
348 | /* Case 4 - left rotate at parent + color flips */ | 410 | /* Case 4 - right rotate at parent + color flips */ |
349 | parent->rb_left = tmp2 = sibling->rb_right; | 411 | tmp2 = sibling->rb_right; |
350 | sibling->rb_right = parent; | 412 | WRITE_ONCE(parent->rb_left, tmp2); |
413 | WRITE_ONCE(sibling->rb_right, parent); | ||
351 | rb_set_parent_color(tmp1, sibling, RB_BLACK); | 414 | rb_set_parent_color(tmp1, sibling, RB_BLACK); |
352 | if (tmp2) | 415 | if (tmp2) |
353 | rb_set_parent(tmp2, parent); | 416 | rb_set_parent(tmp2, parent); |
@@ -378,22 +441,41 @@ static inline void dummy_copy(struct rb_node *old, struct rb_node *new) {} | |||
378 | static inline void dummy_rotate(struct rb_node *old, struct rb_node *new) {} | 441 | static inline void dummy_rotate(struct rb_node *old, struct rb_node *new) {} |
379 | 442 | ||
380 | static const struct rb_augment_callbacks dummy_callbacks = { | 443 | static const struct rb_augment_callbacks dummy_callbacks = { |
381 | dummy_propagate, dummy_copy, dummy_rotate | 444 | .propagate = dummy_propagate, |
445 | .copy = dummy_copy, | ||
446 | .rotate = dummy_rotate | ||
382 | }; | 447 | }; |
383 | 448 | ||
384 | void rb_insert_color(struct rb_node *node, struct rb_root *root) | 449 | void rb_insert_color(struct rb_node *node, struct rb_root *root) |
385 | { | 450 | { |
386 | __rb_insert(node, root, dummy_rotate); | 451 | __rb_insert(node, root, false, NULL, dummy_rotate); |
387 | } | 452 | } |
388 | 453 | ||
389 | void rb_erase(struct rb_node *node, struct rb_root *root) | 454 | void rb_erase(struct rb_node *node, struct rb_root *root) |
390 | { | 455 | { |
391 | struct rb_node *rebalance; | 456 | struct rb_node *rebalance; |
392 | rebalance = __rb_erase_augmented(node, root, &dummy_callbacks); | 457 | rebalance = __rb_erase_augmented(node, root, |
458 | NULL, &dummy_callbacks); | ||
393 | if (rebalance) | 459 | if (rebalance) |
394 | ____rb_erase_color(rebalance, root, dummy_rotate); | 460 | ____rb_erase_color(rebalance, root, dummy_rotate); |
395 | } | 461 | } |
396 | 462 | ||
463 | void rb_insert_color_cached(struct rb_node *node, | ||
464 | struct rb_root_cached *root, bool leftmost) | ||
465 | { | ||
466 | __rb_insert(node, &root->rb_root, leftmost, | ||
467 | &root->rb_leftmost, dummy_rotate); | ||
468 | } | ||
469 | |||
470 | void rb_erase_cached(struct rb_node *node, struct rb_root_cached *root) | ||
471 | { | ||
472 | struct rb_node *rebalance; | ||
473 | rebalance = __rb_erase_augmented(node, &root->rb_root, | ||
474 | &root->rb_leftmost, &dummy_callbacks); | ||
475 | if (rebalance) | ||
476 | ____rb_erase_color(rebalance, &root->rb_root, dummy_rotate); | ||
477 | } | ||
478 | |||
397 | /* | 479 | /* |
398 | * Augmented rbtree manipulation functions. | 480 | * Augmented rbtree manipulation functions. |
399 | * | 481 | * |
@@ -402,9 +484,10 @@ void rb_erase(struct rb_node *node, struct rb_root *root) | |||
402 | */ | 484 | */ |
403 | 485 | ||
404 | void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, | 486 | void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, |
487 | bool newleft, struct rb_node **leftmost, | ||
405 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) | 488 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) |
406 | { | 489 | { |
407 | __rb_insert(node, root, augment_rotate); | 490 | __rb_insert(node, root, newleft, leftmost, augment_rotate); |
408 | } | 491 | } |
409 | 492 | ||
410 | /* | 493 | /* |
@@ -498,15 +581,24 @@ void rb_replace_node(struct rb_node *victim, struct rb_node *new, | |||
498 | { | 581 | { |
499 | struct rb_node *parent = rb_parent(victim); | 582 | struct rb_node *parent = rb_parent(victim); |
500 | 583 | ||
584 | /* Copy the pointers/colour from the victim to the replacement */ | ||
585 | *new = *victim; | ||
586 | |||
501 | /* Set the surrounding nodes to point to the replacement */ | 587 | /* Set the surrounding nodes to point to the replacement */ |
502 | __rb_change_child(victim, new, parent, root); | ||
503 | if (victim->rb_left) | 588 | if (victim->rb_left) |
504 | rb_set_parent(victim->rb_left, new); | 589 | rb_set_parent(victim->rb_left, new); |
505 | if (victim->rb_right) | 590 | if (victim->rb_right) |
506 | rb_set_parent(victim->rb_right, new); | 591 | rb_set_parent(victim->rb_right, new); |
592 | __rb_change_child(victim, new, parent, root); | ||
593 | } | ||
507 | 594 | ||
508 | /* Copy the pointers/colour from the victim to the replacement */ | 595 | void rb_replace_node_cached(struct rb_node *victim, struct rb_node *new, |
509 | *new = *victim; | 596 | struct rb_root_cached *root) |
597 | { | ||
598 | rb_replace_node(victim, new, &root->rb_root); | ||
599 | |||
600 | if (root->rb_leftmost == victim) | ||
601 | root->rb_leftmost = new; | ||
510 | } | 602 | } |
511 | 603 | ||
512 | static struct rb_node *rb_left_deepest_node(const struct rb_node *node) | 604 | static struct rb_node *rb_left_deepest_node(const struct rb_node *node) |