diff --git a/util/interval-tree.c b/util/interval-tree.c index d86c0752db..f2866aa7d3 100644 --- a/util/interval-tree.c +++ b/util/interval-tree.c @@ -48,12 +48,6 @@ * * It also guarantees that if the lookup returns an element it is the 'correct' * one. But not returning an element does _NOT_ mean it's not present. - * - * NOTE: - * - * Stores to __rb_parent_color are not important for simple lookups so those - * are left undone as of now. Nor did I check for loops involving parent - * pointers. */ typedef enum RBColor @@ -68,6 +62,16 @@ typedef struct RBAugmentCallbacks { void (*rotate)(RBNode *old, RBNode *new); } RBAugmentCallbacks; +static inline uintptr_t rb_pc(const RBNode *n) +{ + return qatomic_read(&n->rb_parent_color); +} + +static inline void rb_set_pc(RBNode *n, uintptr_t pc) +{ + qatomic_set(&n->rb_parent_color, pc); +} + static inline RBNode *pc_parent(uintptr_t pc) { return (RBNode *)(pc & ~1); @@ -75,12 +79,12 @@ static inline RBNode *pc_parent(uintptr_t pc) static inline RBNode *rb_parent(const RBNode *n) { - return pc_parent(n->rb_parent_color); + return pc_parent(rb_pc(n)); } static inline RBNode *rb_red_parent(const RBNode *n) { - return (RBNode *)n->rb_parent_color; + return (RBNode *)rb_pc(n); } static inline RBColor pc_color(uintptr_t pc) @@ -100,27 +104,27 @@ static inline bool pc_is_black(uintptr_t pc) static inline RBColor rb_color(const RBNode *n) { - return pc_color(n->rb_parent_color); + return pc_color(rb_pc(n)); } static inline bool rb_is_red(const RBNode *n) { - return pc_is_red(n->rb_parent_color); + return pc_is_red(rb_pc(n)); } static inline bool rb_is_black(const RBNode *n) { - return pc_is_black(n->rb_parent_color); + return pc_is_black(rb_pc(n)); } static inline void rb_set_black(RBNode *n) { - n->rb_parent_color |= RB_BLACK; + rb_set_pc(n, rb_pc(n) | RB_BLACK); } static inline void rb_set_parent_color(RBNode *n, RBNode *p, RBColor color) { - n->rb_parent_color = (uintptr_t)p | color; + rb_set_pc(n, (uintptr_t)p | color); } static inline void rb_set_parent(RBNode *n, RBNode *p) @@ -186,9 +190,10 @@ static inline void rb_change_child(RBNode *old, RBNode *new, static inline void rb_rotate_set_parents(RBNode *old, RBNode *new, RBRoot *root, RBColor color) { - RBNode *parent = rb_parent(old); + uintptr_t pc = rb_pc(old); + RBNode *parent = pc_parent(pc); - new->rb_parent_color = old->rb_parent_color; + rb_set_pc(new, pc); rb_set_parent_color(old, new, color); rb_change_child(old, new, parent, root); } @@ -536,11 +541,11 @@ static void rb_erase_augmented(RBNode *node, RBRoot *root, * and node must be black due to 4). We adjust colors locally * so as to bypass rb_erase_color() later on. */ - pc = node->rb_parent_color; + pc = rb_pc(node); parent = pc_parent(pc); rb_change_child(node, child, parent, root); if (child) { - child->rb_parent_color = pc; + rb_set_pc(child, pc); rebalance = NULL; } else { rebalance = pc_is_black(pc) ? parent : NULL; @@ -548,9 +553,9 @@ static void rb_erase_augmented(RBNode *node, RBRoot *root, tmp = parent; } else if (!child) { /* Still case 1, but this time the child is node->rb_left */ - pc = node->rb_parent_color; + pc = rb_pc(node); parent = pc_parent(pc); - tmp->rb_parent_color = pc; + rb_set_pc(tmp, pc); rb_change_child(node, tmp, parent, root); rebalance = NULL; tmp = parent; @@ -604,7 +609,7 @@ static void rb_erase_augmented(RBNode *node, RBRoot *root, qatomic_set(&successor->rb_left, tmp); rb_set_parent(tmp, successor); - pc = node->rb_parent_color; + pc = rb_pc(node); tmp = pc_parent(pc); rb_change_child(node, successor, tmp, root); @@ -614,7 +619,7 @@ static void rb_erase_augmented(RBNode *node, RBRoot *root, } else { rebalance = rb_is_black(successor) ? parent : NULL; } - successor->rb_parent_color = pc; + rb_set_pc(successor, pc); tmp = successor; }