aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDavidlohr Bueso <dave@stgolabs.net>2018-12-06 14:18:13 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2019-01-25 09:12:09 -0500
commit3aef2cad5d51ee66d2a614dd2f70cb34c74caf77 (patch)
treeb52f1d67040ec37a2268f91061d33fa6e38e20c6 /tools
parent95420d338e2d802ea0dce4d770d3292beb587f71 (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.h52
-rw-r--r--tools/include/linux/rbtree_augmented.h60
-rw-r--r--tools/lib/rbtree.c178
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 */
56struct 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 *);
68extern struct rb_node *rb_first(const struct rb_root *); 83extern struct rb_node *rb_first(const struct rb_root *);
69extern struct rb_node *rb_last(const struct rb_root *); 84extern struct rb_node *rb_last(const struct rb_root *);
70 85
86extern void rb_insert_color_cached(struct rb_node *,
87 struct rb_root_cached *, bool);
88extern 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 */
72extern struct rb_node *rb_first_postorder(const struct rb_root *); 93extern struct rb_node *rb_first_postorder(const struct rb_root *);
73extern struct rb_node *rb_next_postorder(const struct rb_node *); 94extern 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 */
76extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, 97extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
77 struct rb_root *root); 98 struct rb_root *root);
99extern void rb_replace_node_cached(struct rb_node *victim, struct rb_node *new,
100 struct rb_root_cached *root);
78 101
79static inline void rb_link_node(struct rb_node *node, struct rb_node *parent, 102static 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
99static inline void rb_erase_init(struct rb_node *n, struct rb_root *root) 139static 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
47extern void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, 47extern 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
60rb_insert_augmented(struct rb_node *node, struct rb_root *root, 62rb_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
68static inline void
69rb_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} \
95rbstatic const struct rb_augment_callbacks rbname = { \ 106rbstatic 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
136extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root, 149extern 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
139static __always_inline struct rb_node * 152static __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
237rb_erase_augmented(struct rb_node *node, struct rb_root *root, 261rb_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 */ 270static __always_inline void
271rb_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
46static inline void rb_set_black(struct rb_node *rb) 71static 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
71static __always_inline void 96static __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) {}
378static inline void dummy_rotate(struct rb_node *old, struct rb_node *new) {} 441static inline void dummy_rotate(struct rb_node *old, struct rb_node *new) {}
379 442
380static const struct rb_augment_callbacks dummy_callbacks = { 443static 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
384void rb_insert_color(struct rb_node *node, struct rb_root *root) 449void 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
389void rb_erase(struct rb_node *node, struct rb_root *root) 454void 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
463void 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
470void 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
404void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, 486void __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 */ 595void 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
512static struct rb_node *rb_left_deepest_node(const struct rb_node *node) 604static struct rb_node *rb_left_deepest_node(const struct rb_node *node)