static int rbtree_check(node_t *node, node_t *parent, int parent_color, vtree_pthread_data_t *vtree_data) { int ln, rn; int color; vtree_slot_t *slot; if (node == NULL) return 0; slot = read_slot(node, vtree_data); assert(parent == get_node_parent(slot->parent)); color = get_node_color(slot->parent); assert(color == RB_BLACK || parent_color == RB_BLACK); assert(slot->child[0] == NULL || slot->child[0]->value < node->value); assert(slot->child[1] == NULL || slot->child[1]->value > node->value); ln = rbtree_check(slot->child[0], node, color, vtree_data); rn = rbtree_check(slot->child[1], node, color, vtree_data); assert(ln == rn); if (color == RB_BLACK) return 1 + ln; return ln; }
// Print the node color. void idaapi cfunc_graph_t::print_node_attributes(FILE *fp, int n) { bgcolor_t c = get_node_color(n); if ( c != DEFCOLOR ) qfprintf(fp, " color: %s", get_color_name(c)); }
void *list_global_init(int init_size, int value_range) { vtree_tree_t *tree; node_t *prev, *cur, *node, *gprev, *prev_sib; vtree_slot_t *slot, *prev_slot, *gprev_slot, *prev_sib_slot; vtree_record_t *rec; int i, key, val, direction, prev_direction; rec = (vtree_record_t *)malloc(sizeof(vtree_record_t)); if (rec == NULL) return NULL; rec->epoch = STARTING_EPOCH; rec->rec_next = NULL; rec->count = 0; g_committed_rec = rec; tree = (vtree_tree_t *)malloc(sizeof(vtree_tree_t)); if (tree == NULL) return NULL; tree->root = vtree_new_node(INT_MAX); if (tree->root == NULL) return NULL; i = 0; while (i < init_size) { key = rand() % value_range; prev = tree->root; cur = prev->slots->child[0]; direction = 0; while (cur != NULL) { prev = cur; val = cur->value; if (val > key) { direction = 0; cur = cur->slots->child[0]; } else if (val < key) { direction = 1; cur = cur->slots->child[1]; } else break; } if (cur != NULL) continue; node = vtree_new_node(key); if (node == NULL) return NULL; prev->slots->child[direction] = node; if (prev == tree->root) { node->slots->parent = set_node_black(NULL); goto cont; } slot = node->slots; slot->parent = set_node_red(prev); loop: if (prev == NULL) { slot->parent = set_node_black(slot->parent); goto cont; } prev_slot = prev->slots; if (get_node_color(prev_slot->parent) == RB_BLACK) goto cont; gprev = get_node_parent(prev_slot->parent); gprev_slot = gprev->slots; prev_direction = (gprev_slot->child[1] == prev); prev_sib = gprev_slot->child[!prev_direction]; if (prev_sib) { prev_sib_slot = prev_sib->slots; if (get_node_color(prev_sib_slot->parent) == RB_RED) { prev_slot->parent = set_node_black(prev_slot->parent); prev_sib_slot->parent = set_node_black(prev_sib_slot->parent); prev = get_node_parent(gprev_slot->parent); gprev_slot->parent = set_node_red(prev); node = gprev; slot = gprev_slot; if (prev) { prev_slot = prev->slots; direction = (prev_slot->child[1] == node); } goto loop; } } if (prev_direction == 0) { if (direction == 1) { rot_left_init(tree->root, prev, prev_slot); gprev_slot = gprev->slots; prev = node; prev_slot = prev->slots; } rot_right_init(tree->root, gprev, gprev_slot); gprev_slot = gprev->slots; gprev_slot->parent = set_node_red(gprev_slot->parent); prev_slot->parent = set_node_black(prev_slot->parent); } else { if (direction == 0) { rot_right_init(tree->root, prev, prev_slot); gprev_slot = gprev->slots; prev = node; prev_slot = prev->slots; } rot_left_init(tree->root, gprev, gprev_slot); gprev_slot = gprev->slots; gprev_slot->parent = set_node_red(gprev_slot->parent); prev_slot->parent = set_node_black(prev_slot->parent); } cont: i++; } qsbr_init(); return tree; }
int list_del(int key, pthread_data_t *data) { vtree_tree_t *tree = (vtree_tree_t *)data->list; vtree_pthread_data_t *vtree_data = (vtree_pthread_data_t *)data->ds_data; node_t *prev, *node, *succ, *succ_prev, *succ_right, *node_child, *rebalance_node; vtree_slot_t *slot, *prev_slot, *succ_slot, *succ_prev_slot, *node_child_slot, *rebalance_slot, *tmp_slot; int direction, rebalance_direction, ret, val; vtree_write_cs_enter(vtree_data); do { data->nr_txn++; prev = tree->root; slot = read_slot(prev, vtree_data); node = slot->child[0]; rbtree_check(node, NULL, RB_RED, vtree_data); direction = 0; while (node != NULL) { val = node->value; if (val > key) { slot = read_slot(node, vtree_data); direction = 0; prev = node; node = slot->child[0]; } else if (val < key) { slot = read_slot(node, vtree_data); direction = 1; prev = node; node = slot->child[1]; } else break; } ret = (node != NULL); if (!ret) goto out; prev_slot = slot; slot = read_slot(node, vtree_data); rebalance_node = NULL; if (slot->child[0] == NULL) { if ((succ = slot->child[1]) != NULL) { // only right, right is red and node is black, no rebalance required rebalance_node = NULL; succ_slot = read_slot(succ, vtree_data); add_slot(succ, succ_slot->child[0], succ_slot->child[1], slot->parent, vtree_data); } else { if (get_node_color(slot->parent) == RB_BLACK && prev != tree->root) rebalance_node = prev; else rebalance_node = NULL; } } else { if ((succ = slot->child[1]) != NULL) { // both left and right succ_prev = NULL; succ_prev_slot = NULL; succ_slot = read_slot(succ, vtree_data); node_child = succ; node_child_slot = succ_slot; while (succ_slot->child[0]) { succ_prev = succ; succ_prev_slot = succ_slot; succ = succ_slot->child[0]; succ_slot = read_slot(succ, vtree_data); } if (succ_prev) { // move succ to node add_slot(succ, slot->child[0], slot->child[1], slot->parent, vtree_data); succ_right = succ_slot->child[1]; // succ has no left child, if succ is red, no rebalance is required if (get_node_color(succ_slot->parent) == RB_BLACK) { rebalance_node = succ_prev; rebalance_direction = 0; } if (succ_prev != node_child) { add_slot(node_child, node_child_slot->child[0], node_child_slot->child[1], change_node_parent(node_child_slot->parent, succ), vtree_data); rebalance_slot = add_slot(succ_prev, succ_right, succ_prev_slot->child[1], succ_prev_slot->parent, vtree_data); } else { rebalance_slot = add_slot(succ_prev, succ_right, succ_prev_slot->child[1], change_node_parent(succ_prev_slot->parent, succ), vtree_data); } if (succ_right != NULL) { // if succ has right, it must be a red node with no child add_slot(succ_right, NULL, NULL, set_node_red(succ_prev), vtree_data); } } else { // succ is right child of node if (get_node_color(succ_slot->parent) == RB_BLACK) { rebalance_node = succ; rebalance_direction = 1; } rebalance_slot = add_slot(succ, slot->child[0], succ_slot->child[1], slot->parent, vtree_data); } node_child = slot->child[0]; node_child_slot = read_slot(node_child, vtree_data); add_slot(node_child, node_child_slot->child[0], node_child_slot->child[1], change_node_parent(node_child_slot->parent, succ), vtree_data); } else { // only left, left is red and node is black, no rebalance required succ = slot->child[0]; rebalance_node = NULL; succ_slot = read_slot(succ, vtree_data); add_slot(succ, succ_slot->child[0], succ_slot->child[1], slot->parent, vtree_data); } } if (prev == tree->root) { add_slot(tree->root, succ, NULL, NULL, vtree_data); } else { if (direction == 0) { tmp_slot = add_slot(prev, succ, prev_slot->child[1], prev_slot->parent, vtree_data); } else { tmp_slot = add_slot(prev, prev_slot->child[0], succ, prev_slot->parent, vtree_data); } if (rebalance_node == prev) { rebalance_slot = tmp_slot; rebalance_direction = direction; } } add_slot(node, node, node, node, vtree_data); if (rebalance_node) vtree_rebalance(tree->root, rebalance_node, rebalance_slot, rebalance_direction, vtree_data); out: ; } while (vtree_write_cs_exit(vtree_data)); if (ret == 1) vtree_free_node_later(node, vtree_data); vtree_maybe_quiescent(vtree_data); return ret; }
static void vtree_rebalance(node_t *root, node_t *prev, vtree_slot_t *prev_slot, int direction, vtree_pthread_data_t *vtree_data) { node_t *node, *sib_node, *tmp1_node, *tmp2_node; vtree_slot_t *sib_slot, *tmp1_slot, *tmp2_slot; node = NULL; loop: /* * loop invariants: * - node is black (or NULL on 1st iteration) * - node is not roiot (parent is not NULL) * -ALL leaf paths going through parent and node have * black node count is 1 lower than other leaf path */ sib_node = prev_slot->child[!direction]; if ((sib_slot = get_slot_from_rec_new(sib_node, vtree_data)) == NULL) sib_slot = read_slot(sib_node, vtree_data); if (get_node_color(sib_slot->parent) == RB_RED) { if (direction == 0) { tmp1_node = sib_slot->child[0]; rot_left(root, prev, prev_slot, vtree_data); } else { tmp1_node = sib_slot->child[1]; rot_right(root, prev, prev_slot, vtree_data); } tmp1_slot = get_slot_from_rec_new(tmp1_node, vtree_data); prev_slot->parent = set_node_red(prev_slot->parent); sib_slot = get_slot_from_rec_new(sib_node, vtree_data); sib_slot->parent = set_node_black(sib_slot->parent); sib_node = tmp1_node; sib_slot = tmp1_slot; } // now node and sib are both black tmp1_node = sib_slot->child[!direction]; if (tmp1_node != NULL) if ((tmp1_slot = get_slot_from_rec_new(tmp1_node, vtree_data)) == NULL) tmp1_slot = read_slot(tmp1_node, vtree_data); if (tmp1_node == NULL || get_node_color(tmp1_slot->parent) == RB_BLACK) { tmp2_node = sib_slot->child[direction]; if (tmp2_node != NULL) if ((tmp2_slot = get_slot_from_rec_new(tmp2_node, vtree_data)) == NULL) tmp2_slot = read_slot(tmp2_node, vtree_data); if (tmp2_node == NULL || get_node_color(tmp2_slot->parent) == RB_BLACK) { // sibling color flip to red // this violate rbtree variant, flip parent to black if it was red, or recurse add_or_change_slot(sib_node, sib_slot->child[0], sib_slot->child[1], set_node_red(sib_slot->parent), vtree_data); if (get_node_color(prev_slot->parent) == RB_RED) prev_slot->parent = set_node_black(prev_slot->parent); else { node = prev; prev = get_node_parent(prev_slot->parent); if (prev) { if ((prev_slot = get_slot_from_rec_new(prev, vtree_data)) == NULL) { prev_slot = read_slot(prev, vtree_data); prev_slot = add_slot(prev, prev_slot->child[0], prev_slot->child[1], prev_slot->parent, vtree_data); } direction = (prev_slot->child[1] == node); goto loop; } } goto out; } if (direction == 0) { rot_right(root, sib_node, sib_slot, vtree_data); } else { rot_left(root, sib_node, sib_slot, vtree_data); } sib_slot = get_slot_from_rec_new(sib_node, vtree_data); sib_slot->parent = set_node_red(sib_slot->parent); tmp2_slot = get_slot_from_rec_new(tmp2_node, vtree_data); tmp2_slot->parent = set_node_black(tmp2_slot->parent); tmp1_node = sib_node; tmp1_slot = sib_slot; sib_node = tmp2_node; } if (direction == 0) { rot_left(root, prev, prev_slot, vtree_data); } else { rot_right(root, prev, prev_slot, vtree_data); } sib_slot = get_slot_from_rec_new(sib_node, vtree_data); sib_slot->parent = change_node_parent(prev_slot->parent, get_node_parent(sib_slot->parent)); prev_slot->parent = set_node_black(prev_slot->parent); add_or_change_slot(tmp1_node, tmp1_slot->child[0], tmp1_slot->child[1], set_node_black(tmp1_slot->parent), vtree_data); out: return; }
int list_ins(int key, pthread_data_t *data) { vtree_tree_t *tree = (vtree_tree_t *)data->list; vtree_pthread_data_t *vtree_data = (vtree_pthread_data_t *)data->ds_data; node_t *prev, *cur, *node, *new_node, *gprev, *prev_sib; vtree_slot_t *slot, *prev_slot, *gprev_slot, *prev_sib_slot; int prev_direction, direction, ret, val; new_node = vtree_new_node(key); assert(new_node != NULL); vtree_write_cs_enter(vtree_data); do { data->nr_txn++; prev = tree->root; prev_slot = read_slot(prev, vtree_data); cur = prev_slot->child[0]; rbtree_check(cur, NULL, RB_RED, vtree_data); direction = 0; while (cur != NULL) { val = cur->value; if (val > key) { prev_slot = read_slot(cur, vtree_data); direction = 0; prev = cur; cur = prev_slot->child[0]; } else if (val < key) { prev_slot = read_slot(cur, vtree_data); direction = 1; prev = cur; cur = prev_slot->child[1]; } else break; } ret = (cur == NULL); if (!ret) goto out; node = new_node; if (direction == 0) prev_slot = add_slot(prev, node, prev_slot->child[1], prev_slot->parent, vtree_data); else prev_slot = add_slot(prev, prev_slot->child[0], node, prev_slot->parent, vtree_data); if (prev == tree->root) { slot = add_slot(node, NULL, NULL, set_node_black(NULL), vtree_data); goto out; } // newly inserted node is red to maintain invariant slot = add_slot(node, NULL, NULL, set_node_red(prev), vtree_data); loop: if (prev == NULL) { // we can always set root to black slot->parent = set_node_black(slot->parent); goto out; } if (get_node_color(prev_slot->parent) == RB_BLACK) { // parent is black, no invariant violated goto out; } // now both node and parent are red, check grandparent, // since parent is red, there must be grandparent and it is black gprev = get_node_parent(prev_slot->parent); gprev_slot = read_slot(gprev, vtree_data); prev_direction = (gprev_slot->child[1] == prev); prev_sib = gprev_slot->child[!prev_direction]; if (prev_sib) { prev_sib_slot = read_slot(prev_sib, vtree_data); if (get_node_color(prev_sib_slot->parent) == RB_RED) { // if sib is red, change parent and sib to black // and move upwards prev_slot->parent = set_node_black(prev_slot->parent); add_slot(prev_sib, prev_sib_slot->child[0], prev_sib_slot->child[1], set_node_black(prev_sib_slot->parent), vtree_data); prev = get_node_parent(gprev_slot->parent); slot = add_slot(gprev, gprev_slot->child[0], gprev_slot->child[1], set_node_red(prev), vtree_data); node = gprev; if (prev) { prev_slot = read_slot(prev, vtree_data); direction = (prev_slot->child[1] == node); prev_slot = add_slot(prev, prev_slot->child[0], prev_slot->child[1], prev_slot->parent, vtree_data); } goto loop; } } // now, either there is no sib of parent or it is black if (prev_direction == 0) { if (direction == 1) { rot_left(tree->root, prev, prev_slot, vtree_data); gprev_slot = get_slot_from_rec_new(gprev, vtree_data); prev = node; prev_slot = get_slot_from_rec_new(node, vtree_data); } rot_right(tree->root, gprev, gprev_slot, vtree_data); gprev_slot = get_slot_from_rec_new(gprev, vtree_data); gprev_slot->parent = set_node_red(gprev_slot->parent); prev_slot->parent = set_node_black(prev_slot->parent); } else { if (direction == 0) { rot_right(tree->root, prev, prev_slot, vtree_data); gprev_slot = get_slot_from_rec_new(gprev, vtree_data); prev = node; prev_slot = get_slot_from_rec_new(node, vtree_data); } rot_left(tree->root, gprev, gprev_slot, vtree_data); gprev_slot = get_slot_from_rec_new(gprev, vtree_data); gprev_slot->parent = set_node_red(gprev_slot->parent); prev_slot->parent = set_node_black(prev_slot->parent); } out: ; } while (vtree_write_cs_exit(vtree_data)); if (ret == 0) vtree_free_node_later(new_node, vtree_data); vtree_maybe_quiescent(vtree_data); return ret; }
COLOR ConstraintGraph::get_node_color(NType type,int idx){ GNode nd(type,idx); return get_node_color(nd); }