aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichel Lespinasse <walken@google.com>2012-10-08 19:30:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-09 03:22:34 -0400
commite125d1471a4f8f1bf7ea9a83deb8d23cb40bd712 (patch)
tree00c6bb561cdb8d0cb455563aa233bffe73b7e6db
parentd6ff1273928ebf15466a85b7e1810cd00e72998b (diff)
rbtree: optimize case selection logic in __rb_erase_color()
In __rb_erase_color(), we have to select one of 3 cases depending on the color on the 'other' node children. If both children are black, we flip a few node colors and iterate. Otherwise, we do either one or two tree rotations, depending on the color of the 'other' child opposite to 'node', and then we are done. The corresponding logic had duplicate checks for the color of the 'other' child opposite to 'node'. It was checking it first to determine if both children are black, and then to determine how many tree rotations are required. Rearrange the logic to avoid that extra check. Signed-off-by: Michel Lespinasse <walken@google.com> Cc: Andrea Arcangeli <aarcange@redhat.com> Acked-by: David Woodhouse <David.Woodhouse@intel.com> Cc: Rik van Riel <riel@redhat.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Daniel Santos <daniel.santos@pobox.com> Cc: Jens Axboe <axboe@kernel.dk> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--lib/rbtree.c68
1 files changed, 30 insertions, 38 deletions
diff --git a/lib/rbtree.c b/lib/rbtree.c
index baf7c835c57c..eb823a31099c 100644
--- a/lib/rbtree.c
+++ b/lib/rbtree.c
@@ -283,28 +283,24 @@ static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
283 __rb_rotate_left(parent, root); 283 __rb_rotate_left(parent, root);
284 other = parent->rb_right; 284 other = parent->rb_right;
285 } 285 }
286 if ((!other->rb_left || rb_is_black(other->rb_left)) && 286 if (!other->rb_right || rb_is_black(other->rb_right)) {
287 (!other->rb_right || rb_is_black(other->rb_right))) 287 if (!other->rb_left ||
288 { 288 rb_is_black(other->rb_left)) {
289 rb_set_red(other);
290 node = parent;
291 parent = rb_parent(node);
292 }
293 else
294 {
295 if (!other->rb_right || rb_is_black(other->rb_right))
296 {
297 rb_set_black(other->rb_left);
298 rb_set_red(other); 289 rb_set_red(other);
299 __rb_rotate_right(other, root); 290 node = parent;
300 other = parent->rb_right; 291 parent = rb_parent(node);
292 continue;
301 } 293 }
302 rb_set_color(other, rb_color(parent)); 294 rb_set_black(other->rb_left);
303 rb_set_black(parent); 295 rb_set_red(other);
304 rb_set_black(other->rb_right); 296 __rb_rotate_right(other, root);
305 __rb_rotate_left(parent, root); 297 other = parent->rb_right;
306 break;
307 } 298 }
299 rb_set_color(other, rb_color(parent));
300 rb_set_black(parent);
301 rb_set_black(other->rb_right);
302 __rb_rotate_left(parent, root);
303 break;
308 } else { 304 } else {
309 other = parent->rb_left; 305 other = parent->rb_left;
310 if (rb_is_red(other)) 306 if (rb_is_red(other))
@@ -314,28 +310,24 @@ static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
314 __rb_rotate_right(parent, root); 310 __rb_rotate_right(parent, root);
315 other = parent->rb_left; 311 other = parent->rb_left;
316 } 312 }
317 if ((!other->rb_left || rb_is_black(other->rb_left)) && 313 if (!other->rb_left || rb_is_black(other->rb_left)) {
318 (!other->rb_right || rb_is_black(other->rb_right))) 314 if (!other->rb_right ||
319 { 315 rb_is_black(other->rb_right)) {
320 rb_set_red(other);
321 node = parent;
322 parent = rb_parent(node);
323 }
324 else
325 {
326 if (!other->rb_left || rb_is_black(other->rb_left))
327 {
328 rb_set_black(other->rb_right);
329 rb_set_red(other); 316 rb_set_red(other);
330 __rb_rotate_left(other, root); 317 node = parent;
331 other = parent->rb_left; 318 parent = rb_parent(node);
319 continue;
332 } 320 }
333 rb_set_color(other, rb_color(parent)); 321 rb_set_black(other->rb_right);
334 rb_set_black(parent); 322 rb_set_red(other);
335 rb_set_black(other->rb_left); 323 __rb_rotate_left(other, root);
336 __rb_rotate_right(parent, root); 324 other = parent->rb_left;
337 break;
338 } 325 }
326 rb_set_color(other, rb_color(parent));
327 rb_set_black(parent);
328 rb_set_black(other->rb_left);
329 __rb_rotate_right(parent, root);
330 break;
339 } 331 }
340 } 332 }
341} 333}