From 651094542847ccd42580faa94fb14ac7d9e6669a Mon Sep 17 00:00:00 2001 From: Michel Lespinasse Date: Mon, 8 Oct 2012 16:30:50 -0700 Subject: [PATCH] --- yaml --- r: 332392 b: refs/heads/master c: d6ff1273928ebf15466a85b7e1810cd00e72998b h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/lib/rbtree.c | 28 ++++++++++++-------- trunk/tools/perf/util/include/linux/rbtree.h | 1 + 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/[refs] b/[refs] index 5e566c27024e..332d8c67514a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5bc9188aa207dafd47eab57df7c4fe5b3d3f636a +refs/heads/master: d6ff1273928ebf15466a85b7e1810cd00e72998b diff --git a/trunk/lib/rbtree.c b/trunk/lib/rbtree.c index 41cf19b2fe51..baf7c835c57c 100644 --- a/trunk/lib/rbtree.c +++ b/trunk/lib/rbtree.c @@ -259,10 +259,22 @@ static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, { struct rb_node *other; - while ((!node || rb_is_black(node)) && node != root->rb_node) - { - if (parent->rb_left == node) - { + while (true) { + /* + * Loop invariant: all leaf paths going through node have a + * black node count that is 1 lower than other leaf paths. + * + * If node is red, we can flip it to black to adjust. + * If node is the root, all leaf paths go through it. + * Otherwise, we need to adjust the tree through color flips + * and tree rotations as per one of the 4 cases below. + */ + if (node && rb_is_red(node)) { + rb_set_black(node); + break; + } else if (!parent) { + break; + } else if (parent->rb_left == node) { other = parent->rb_right; if (rb_is_red(other)) { @@ -291,12 +303,9 @@ static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, rb_set_black(parent); rb_set_black(other->rb_right); __rb_rotate_left(parent, root); - node = root->rb_node; break; } - } - else - { + } else { other = parent->rb_left; if (rb_is_red(other)) { @@ -325,13 +334,10 @@ static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, rb_set_black(parent); rb_set_black(other->rb_left); __rb_rotate_right(parent, root); - node = root->rb_node; break; } } } - if (node) - rb_set_black(node); } void rb_erase(struct rb_node *node, struct rb_root *root) diff --git a/trunk/tools/perf/util/include/linux/rbtree.h b/trunk/tools/perf/util/include/linux/rbtree.h index 2a030c5af3aa..9bcdc844b330 100644 --- a/trunk/tools/perf/util/include/linux/rbtree.h +++ b/trunk/tools/perf/util/include/linux/rbtree.h @@ -1,2 +1,3 @@ #include +#include #include "../../../../include/linux/rbtree.h"