/* * Recreate the addr tree of vm_map in local memory. */ struct vm_map_entry * load_vm_map_entries(kvm_t *kd, struct vm_map_entry *kptr, struct vm_map_entry *parent) { static struct kbit map_ent; struct vm_map_entry *result; if (kptr == NULL) return NULL; A(&map_ent) = (u_long)kptr; S(&map_ent) = sizeof(struct vm_map_entry); KDEREF(kd, &map_ent); result = malloc(sizeof(*result)); if (result == NULL) err(1, "malloc"); memcpy(result, D(&map_ent, vm_map_entry), sizeof(struct vm_map_entry)); /* * Recurse to download rest of the tree. */ RB_LEFT(result, daddrs.addr_entry) = load_vm_map_entries(kd, RB_LEFT(result, daddrs.addr_entry), result); RB_RIGHT(result, daddrs.addr_entry) = load_vm_map_entries(kd, RB_RIGHT(result, daddrs.addr_entry), result); RB_PARENT(result, daddrs.addr_entry) = parent; return result; }
/* * rb_print_preorder - print nodes of Red-black tree in preorder */ static void rb_print_preorder(){ printf("rb_print_preorder() called\n"); if(RB_LEFT(rb_root) == rb_null){ printf("empty\n"); }else{ rb_print_preorder_impl(RB_LEFT(rb_root)); } }
/* * rb_fix - restore properties of Red-black tree after deleting */ static void rb_fix(void *node){ void *root, *sib; root = RB_LEFT(rb_root); while(!RB_RED(node) && node != root){ if(node == RB_LEFT(RB_PARENT(node))){ sib = RB_RIGHT(RB_PARENT(node)); if(RB_RED(sib)){ RB_RED(sib) = 0; RB_RED(RB_PARENT(node)) = 1; rb_rotate_left(RB_PARENT(node)); sib = RB_RIGHT(RB_PARENT(node)); } if(!RB_RED(RB_RIGHT(sib)) && !RB_RED(RB_LEFT(sib))){ RB_RED(sib) = 1; node = RB_PARENT(node); }else{ if(!RB_RED(RB_RIGHT(sib))){ RB_RED(RB_LEFT(sib)) = 0; RB_RED(sib) = 1; rb_rotate_right(sib); sib = RB_RIGHT(RB_PARENT(node)); } RB_RED(sib) = RB_RED(RB_PARENT(node)); RB_RED(RB_PARENT(node)) = 0; RB_RED(RB_RIGHT(sib)) = 0; rb_rotate_left(RB_PARENT(node)); node = root; } }else{ sib = RB_LEFT(RB_PARENT(node)); if(RB_RED(sib)){ RB_RED(sib) = 0; RB_RED(RB_PARENT(node)) = 1; rb_rotate_right(RB_PARENT(node)); sib = RB_LEFT(RB_PARENT(node)); } if(!RB_RED(RB_RIGHT(sib)) && !RB_RED(RB_LEFT(sib))){ RB_RED(sib) = 1; node = RB_PARENT(node); }else{ if(!RB_RED(RB_LEFT(sib))){ RB_RED(RB_RIGHT(sib)) = 0; RB_RED(sib) = 1; rb_rotate_left(sib); sib = RB_LEFT(RB_PARENT(node)); } RB_RED(sib) = RB_RED(RB_PARENT(node)); RB_RED(RB_PARENT(node)) = 0; RB_RED(RB_LEFT(sib)) = 0; rb_rotate_right(RB_PARENT(node)); node = root; } } } RB_RED(node) = 0; }
/* * rb_print_preorder_impl - recursion implementation of rb_print_preorder */ static void rb_print_preorder_impl(void *node){ if(RB_LEFT(node) != rb_null){ rb_print_preorder_impl(RB_LEFT(node)); } printf("%p : %u\n", node, CUR_SIZE_MASKED(node)); if(RB_RIGHT(node) != rb_null){ rb_print_preorder_impl(RB_RIGHT(node)); } }
/* * rb_find - find the smallest free block which is bigger than or equal to size. */ static void* rb_find(size_t size){ void *node = RB_LEFT(rb_root), *best = rb_null; while(node != rb_null){ if(CUR_SIZE_MASKED(node) < size){ node = RB_RIGHT(node); }else{ best = node; node = RB_LEFT(node); } } return best; }
static struct ttm_buffer_object *ttm_bo_vm_lookup_rb(struct ttm_bo_device *bdev, unsigned long page_start, unsigned long num_pages) { unsigned long cur_offset; struct ttm_buffer_object *bo; struct ttm_buffer_object *best_bo = NULL; bo = RB_ROOT(&bdev->addr_space_rb); while (bo != NULL) { cur_offset = bo->vm_node->start; if (page_start >= cur_offset) { best_bo = bo; if (page_start == cur_offset) break; bo = RB_RIGHT(bo, vm_rb); } else bo = RB_LEFT(bo, vm_rb); } if (unlikely(best_bo == NULL)) return NULL; if (unlikely((best_bo->vm_node->start + best_bo->num_pages) < (page_start + num_pages))) return NULL; return best_bo; }
boolean_t vm_map_store_lookup_entry_rb( vm_map_t map, vm_map_offset_t address, vm_map_entry_t *vm_entry) { struct vm_map_header hdr = map->hdr; struct vm_map_store *rb_entry = RB_ROOT(&(hdr.rb_head_store)); vm_map_entry_t cur = vm_map_to_entry(map); vm_map_entry_t prev = VM_MAP_ENTRY_NULL; while (rb_entry != (struct vm_map_store*)NULL) { cur = VME_FOR_STORE(rb_entry); if(cur == VM_MAP_ENTRY_NULL) panic("no entry"); if (address >= cur->vme_start) { if (address < cur->vme_end) { *vm_entry = cur; return TRUE; } rb_entry = RB_RIGHT(rb_entry, entry); prev = cur; } else { rb_entry = RB_LEFT(rb_entry, entry); } } if( prev == VM_MAP_ENTRY_NULL){ prev = vm_map_to_entry(map); } *vm_entry = prev; return FALSE; }
/* * rb_rotate_right - rotate node and children of node to the right */ static void rb_rotate_right(void *node){ void *left; left = RB_LEFT(node); RB_LEFT(node) = RB_RIGHT(left); if(RB_RIGHT(left) != rb_null) RB_PARENT(RB_RIGHT(left)) = node; RB_PARENT(left) = RB_PARENT(node); if(node == RB_LEFT(RB_PARENT(node))){ RB_LEFT(RB_PARENT(node)) = left; }else{ RB_RIGHT(RB_PARENT(node)) = left; } RB_RIGHT(left) = node; RB_PARENT(node) = left; }
/* * rb_check_preorder_impl - recursion implementation of rb_check_preorder */ static int rb_check_preorder_impl(void *node){ if(RB_LEFT(node) != rb_null){ if(!rb_check_preorder_impl(RB_LEFT(node))){ return 0; } } if(!CUR_FREE(node)){ printf("%p is in Red-black tree, but is not free block.\n", node); return 0; } if(RB_RIGHT(node) != rb_null){ if(!rb_check_preorder_impl(RB_RIGHT(node))){ return 0; } } return 1; }
/* * The algorithm is from * I. Stoica and H. Abdel-Wahab, ``Earliest Eligible Virtual Deadline * First: A Flexible and Accurate Mechanism for Proportional Share * Resource Allocation,'' technical report. * * http://www.cs.berkeley.edu/~istoica/papers/eevdf-tr-95.pdf * * - Partition the tree into two parts by ve: * - One part contains nodes with ve smaller than vtime * - The other part contains nodes with ve larger than vtime * - In the first part, find the node with minimum vd, along the * min_vd value path * * Returns * NULL, if no node with ve smaller than vtime * or the elegible node with minimum vd. */ static struct bfq_thread_io * wf2q_augtree_get_eligible_with_min_vd(struct wf2q_augtree_t *tree, int vtime) { struct bfq_thread_io *node = RB_ROOT(tree), *st_tree = NULL, *path_req = NULL; while (node) { if (node->ve <= vtime) { /* update node with earliest deadline along path. */ if ((!path_req) || (path_req->vd > node->vd)) path_req = node; /* update root of subtree containing earliest deadline */ if ((!st_tree) || (RB_LEFT(node,entry) && st_tree->min_vd > RB_LEFT(node,entry)->min_vd)) st_tree = RB_LEFT(node,entry); node = RB_RIGHT(node, entry); } else node = RB_LEFT(node, entry); } /* check whether node with earliest deadline was along path */ if ((!st_tree) || (st_tree->min_vd >= path_req->vd)) return path_req; /* return node with earliest deadline from subtree */ for (node = st_tree; node; ) { /* if node found, return it */ if (st_tree->min_vd == node->vd) return node; /* XXX: modified temporarily */ if (RB_LEFT(node, entry) && node->min_vd == RB_LEFT(node, entry)->min_vd) node = RB_LEFT(node, entry); else node = RB_RIGHT(node, entry); } return NULL; }
/* * Release the addr tree of vm_map. */ void unload_vm_map_entries(struct vm_map_entry *ent) { if (ent == NULL) return; unload_vm_map_entries(RB_LEFT(ent, daddrs.addr_entry)); unload_vm_map_entries(RB_RIGHT(ent, daddrs.addr_entry)); free(ent); }
struct rb_node *rb_prev(struct rb_node *elm) { if (RB_LEFT(elm)) { elm = RB_LEFT(elm); while (RB_RIGHT(elm)) elm = RB_RIGHT(elm); } else { if (RB_PARENT(elm) && (elm == RB_RIGHT(RB_PARENT(elm)))) elm = RB_PARENT(elm); else { while (RB_PARENT(elm) && (elm == RB_LEFT(RB_PARENT(elm)))) elm = RB_PARENT(elm); elm = RB_PARENT(elm); } } return (elm); }
/* * rb_find_exact - check whether block is in Red-black tree or not. */ static int rb_find_exact(void *block){ void *node = RB_LEFT(rb_root); while(node != rb_null){ if(node == block){ return 1; }else if(CUR_SIZE_MASKED(node) > CUR_SIZE_MASKED(block)){ node = RB_LEFT(node); }else if(CUR_SIZE_MASKED(node) == CUR_SIZE_MASKED(block)){ if(node > block){ node = RB_LEFT(node); }else{ node = RB_RIGHT(node); } }else{ node = RB_RIGHT(node); } } return 0; }
/* Note args swapped to match Linux */ void rb_insert_color(struct rb_node *elm, struct rb_root *head) { struct rb_node *parent, *gparent, *tmp; while ((parent = RB_PARENT(elm)) && RB_COLOR(parent) == RB_RED) { gparent = RB_PARENT(parent); if (parent == RB_LEFT(gparent)) { tmp = RB_RIGHT(gparent); if (tmp && RB_COLOR(tmp) == RB_RED) { RB_COLOR(tmp) = RB_BLACK; RB_SET_BLACKRED(parent, gparent); elm = gparent; continue; } if (RB_RIGHT(parent) == elm) { RB_ROTATE_LEFT(head, parent, tmp); tmp = parent; parent = elm; elm = tmp; } RB_SET_BLACKRED(parent, gparent); RB_ROTATE_RIGHT(head, gparent, tmp); } else { tmp = RB_LEFT(gparent); if (tmp && RB_COLOR(tmp) == RB_RED) { RB_COLOR(tmp) = RB_BLACK; RB_SET_BLACKRED(parent, gparent); elm = gparent; continue; } if (RB_LEFT(parent) == elm) { RB_ROTATE_RIGHT(head, parent, tmp); tmp = parent; parent = elm; elm = tmp; } RB_SET_BLACKRED(parent, gparent); RB_ROTATE_LEFT(head, gparent, tmp); } } RB_COLOR(head->rb_node) = RB_BLACK; }
static void wf2q_tree_dump(struct bfq_thread_io *root, int level) { int i; if (!root) return; for (i = 0; i < level; i++) kprintf("-"); kprintf("vd: %d; ve: %d; min_vd: %d\n", root->vd, root->ve, root->min_vd); wf2q_tree_dump(RB_LEFT(root,entry), level + 1); wf2q_tree_dump(RB_RIGHT(root, entry), level + 1); }
void vm_map_store_walk_rb( vm_map_t map, vm_map_entry_t *wrong_vme, vm_map_entry_t *vm_entry) { struct vm_map_header hdr = map->hdr; struct vm_map_store *rb_entry = RB_ROOT(&(hdr.rb_head_store)); vm_map_entry_t cur = *vm_entry; rb_entry = RB_FIND( rb_head, &(hdr.rb_head_store), &(cur->store)); if(rb_entry == NULL) panic("NO SUCH ENTRY %p. Gave back %p", *vm_entry, *wrong_vme); else panic("Cur: %p, L: %p, R: %p", VME_FOR_STORE(rb_entry), VME_FOR_STORE(RB_LEFT(rb_entry,entry)), VME_FOR_STORE(RB_RIGHT(rb_entry,entry))); }
static void wf2q_augment_func(struct bfq_thread_io *node) { struct bfq_thread_io *tmp = node, *tmp2; int min_vd; do{ min_vd = tmp->vd; tmp2 = RB_LEFT(tmp, entry); min_vd = tmp2 ? MIN(tmp2->min_vd, min_vd) : min_vd; tmp2 = RB_RIGHT(tmp, entry); min_vd = tmp2 ? MIN(tmp2->min_vd, min_vd) : min_vd; tmp->min_vd = min_vd; }while((tmp = RB_PARENT(tmp,entry))); }
/* * mm_init - initialize the malloc package. */ int mm_init(range_t **ranges) { /* allocate root and nil nodes */ if((rb_root = rb_null = mem_sbrk(4 + MIN_BLOCK_SIZE)) == FAIL) return -1; /* assign sentinel values */ RB_LEFT(rb_root) = RB_RIGHT(rb_root) = rb_null; RB_RED(rb_root) = 0; /* prevent coalesce by setting free bit to 0*/ PREV_SIZE(NEXT_BLOCK(rb_null, MIN_BLOCK_SIZE)) = 0; /* DON't MODIFY THIS STAGE AND LEAVE IT AS IT WAS */ gl_ranges = ranges; return 0; }
/* * rb_successor - find the next node of node in ascending order. */ static void* rb_successor(void *node){ void *succ, *left; if((succ = RB_RIGHT(node)) != rb_null){ while((left = RB_LEFT(succ)) != rb_null){ succ = left; } return succ; }else{ succ = RB_PARENT(node); while(RB_RIGHT(succ) == node){ node = succ; succ = RB_PARENT(succ); } if(succ == rb_root) return rb_null; return succ; } }
struct ieee80211_node * ieee80211_find_node(struct ieee80211com *ic, const u_int8_t *macaddr) { struct ieee80211_node *ni; int cmp; /* similar to RB_FIND except we compare keys, not nodes */ ni = RB_ROOT(&ic->ic_tree); while (ni != NULL) { cmp = memcmp(macaddr, ni->ni_macaddr, IEEE80211_ADDR_LEN); if (cmp < 0) ni = RB_LEFT(ni, ni_node); else if (cmp > 0) ni = RB_RIGHT(ni, ni_node); else break; } return ni; }
/* * rb_rotate_left - rotate node and children of node to the left */ static void rb_rotate_left(void *node){ void *right; right = RB_RIGHT(node); RB_RIGHT(node) = RB_LEFT(right); if(RB_LEFT(right) != rb_null) RB_PARENT(RB_LEFT(right)) = node; RB_PARENT(right) = RB_PARENT(node); if(node == RB_LEFT(RB_PARENT(node))){ RB_LEFT(RB_PARENT(node)) = right; }else{ RB_RIGHT(RB_PARENT(node)) = right; } RB_LEFT(right) = node; RB_PARENT(node) = right; }
/** * Find next route in the table. There is no such RB_ macro, so must * dig into the innards of the RB stuff. */ static struct sroute * sroute_getnext(struct asn_oid *oid, u_int sub) { u_int i; int comp; struct sroute key; struct sroute *best; struct sroute *s; /* * We now, that the OID is at least the tableEntry OID. If it is, * the user wants the first route. */ if (oid->len == sub) return (RB_MIN(sroutes, &sroutes)); /* * This is also true for any index that consists of zeros and is * shorter than the full index. */ if (oid->len < sub + 13) { for (i = sub; i < oid->len; i++) if (oid->subs[i] != 0) break; if (i == oid->len) return (RB_MIN(sroutes, &sroutes)); /* * Now if the index is too short, we fill it with zeros and then * subtract one from the index. We can do this, because we now, * that there is at least one index element that is not zero. */ for (i = oid->len; i < sub + 13; i++) oid->subs[i] = 0; for (i = sub + 13 - 1; i >= sub; i--) { if (oid->subs[i] != 0) { oid->subs[i]--; break; } oid->subs[i] = ASN_MAXID; } oid->len = sub + 13; } /* build the index */ for (i = sub; i < sub + 13; i++) key.index[i - sub] = oid->subs[i]; /* now find the element */ best = NULL; s = RB_ROOT(&sroutes); while (s != NULL) { comp = sroute_compare(&key, s); if (comp >= 0) { /* The current element is smaller than what we search. * Forget about it and move to the right subtree. */ s = RB_RIGHT(s, link); continue; } /* the current element is larger than what we search. * forget about the right subtree (its even larger), but * the current element may be what we need. */ if (best == NULL || sroute_compare(s, best) < 0) /* this one's better */ best = s; s = RB_LEFT(s, link); } return (best); }
/* * rb_check_preorder * * return 0 if there exists allocated block in Red-black tree, 1 otherwise. */ static int rb_check_preorder(){ if(RB_LEFT(rb_root) != rb_null){ return rb_check_preorder_impl(RB_LEFT(rb_root)); } return 1; }
static void rb_remove_color(struct rb_root *head, struct rb_node *parent, struct rb_node *elm) { struct rb_node *tmp; while ((elm == NULL || RB_COLOR(elm) == RB_BLACK) && elm != RB_HEAD(head)) { if (RB_LEFT(parent) == elm) { tmp = RB_RIGHT(parent); if (RB_COLOR(tmp) == RB_RED) { RB_SET_BLACKRED(tmp, parent); RB_ROTATE_LEFT(head, parent, tmp); tmp = RB_RIGHT(parent); } if ((RB_LEFT(tmp) == NULL || RB_COLOR(RB_LEFT(tmp)) == RB_BLACK) && (RB_RIGHT(tmp) == NULL || RB_COLOR(RB_RIGHT(tmp)) == RB_BLACK)) { RB_COLOR(tmp) = RB_RED; elm = parent; parent = RB_PARENT(elm); } else { if (RB_RIGHT(tmp) == NULL || RB_COLOR(RB_RIGHT(tmp)) == RB_BLACK) { struct rb_node *oleft; if ((oleft = RB_LEFT(tmp))) RB_COLOR(oleft) = RB_BLACK; RB_COLOR(tmp) = RB_RED; RB_ROTATE_RIGHT(head, tmp, oleft); tmp = RB_RIGHT(parent); } RB_COLOR(tmp) = RB_COLOR(parent); RB_COLOR(parent) = RB_BLACK; if (RB_RIGHT(tmp)) RB_COLOR(RB_RIGHT(tmp)) = RB_BLACK; RB_ROTATE_LEFT(head, parent, tmp); elm = RB_HEAD(head); break; } } else { tmp = RB_LEFT(parent); if (RB_COLOR(tmp) == RB_RED) { RB_SET_BLACKRED(tmp, parent); RB_ROTATE_RIGHT(head, parent, tmp); tmp = RB_LEFT(parent); } if ((RB_LEFT(tmp) == NULL || RB_COLOR(RB_LEFT(tmp)) == RB_BLACK) && (RB_RIGHT(tmp) == NULL || RB_COLOR(RB_RIGHT(tmp)) == RB_BLACK)) { RB_COLOR(tmp) = RB_RED; elm = parent; parent = RB_PARENT(elm); } else { if (RB_LEFT(tmp) == NULL || RB_COLOR(RB_LEFT(tmp)) == RB_BLACK) { struct rb_node *oright; if ((oright = RB_RIGHT(tmp))) RB_COLOR(oright) = RB_BLACK; RB_COLOR(tmp) = RB_RED; RB_ROTATE_LEFT(head, tmp, oright); tmp = RB_LEFT(parent); } RB_COLOR(tmp) = RB_COLOR(parent); RB_COLOR(parent) = RB_BLACK; if (RB_LEFT(tmp)) RB_COLOR(RB_LEFT(tmp)) = RB_BLACK; RB_ROTATE_RIGHT(head, parent, tmp); elm = RB_HEAD(head); break; } } } if (elm) RB_COLOR(elm) = RB_BLACK; }
/* * rb_insert - insert node into Red-black tree */ static void rb_insert(void *node){ void *parent, *child, *sib; RB_LEFT(node) = RB_RIGHT(node) = rb_null; parent = rb_root; child = RB_LEFT(rb_root); while(child != rb_null){ parent = child; if(CUR_SIZE_MASKED(child) > CUR_SIZE_MASKED(node)){ child = RB_LEFT(child); }else if(CUR_SIZE_MASKED(child) == CUR_SIZE_MASKED(node)){ if(child > node){ child = RB_LEFT(child); }else{ child = RB_RIGHT(child); } }else{ child = RB_RIGHT(child); } } RB_PARENT(node) = parent; if(parent == rb_root || CUR_SIZE_MASKED(parent) > CUR_SIZE_MASKED(node)){ RB_LEFT(parent) = node; }else if(CUR_SIZE_MASKED(parent) == CUR_SIZE_MASKED(node)){ if(parent > node){ RB_LEFT(parent) = node; }else{ RB_RIGHT(parent) = node; } }else{ RB_RIGHT(parent) = node; } RB_RED(node) = 1; while(RB_RED(RB_PARENT(node))){ if(RB_PARENT(node) == RB_LEFT(RB_PARENT(RB_PARENT(node)))){ sib = RB_RIGHT(RB_PARENT(RB_PARENT(node))); if(RB_RED(sib)){ RB_RED(RB_PARENT(node)) = 0; RB_RED(sib) = 0; RB_RED(RB_PARENT(RB_PARENT(node))) = 1; node = RB_PARENT(RB_PARENT(node)); }else{ if(node == RB_RIGHT(RB_PARENT(node))){ node = RB_PARENT(node); rb_rotate_left(node); } RB_RED(RB_PARENT(node)) = 0; RB_RED(RB_PARENT(RB_PARENT(node))) = 1; rb_rotate_right(RB_PARENT(RB_PARENT(node))); } }else{ sib = RB_LEFT(RB_PARENT(RB_PARENT(node))); if(RB_RED(sib)){ RB_RED(RB_PARENT(node)) = 0; RB_RED(sib) = 0; RB_RED(RB_PARENT(RB_PARENT(node))) = 1; node = RB_PARENT(RB_PARENT(node)); }else{ if(node == RB_LEFT(RB_PARENT(node))){ node = RB_PARENT(node); rb_rotate_right(node); } RB_RED(RB_PARENT(node)) = 0; RB_RED(RB_PARENT(RB_PARENT(node))) = 1; rb_rotate_left(RB_PARENT(RB_PARENT(node))); } } } RB_RED(RB_LEFT(rb_root)) = 0; }
/* * rb_delete - delete node from Red-black tree */ static void rb_delete(void *node){ void *m, *c; m = RB_LEFT(node) == rb_null || RB_RIGHT(node) == rb_null ? node : rb_successor(node); c = RB_LEFT(m) == rb_null ? RB_RIGHT(m) : RB_LEFT(m); if((RB_PARENT(c) = RB_PARENT(m)) == rb_root){ RB_LEFT(rb_root) = c; }else{ if(RB_LEFT(RB_PARENT(m)) == m){ RB_LEFT(RB_PARENT(m)) = c; }else{ RB_RIGHT(RB_PARENT(m)) = c; } } if(m != node){ if(!RB_RED(m)) rb_fix(c); RB_LEFT(m) = RB_LEFT(node); RB_RIGHT(m) = RB_RIGHT(node); RB_PARENT(m) = RB_PARENT(node); RB_RED(m) = RB_RED(node); RB_PARENT(RB_LEFT(node)) = RB_PARENT(RB_RIGHT(node)) = m; if(node == RB_LEFT(RB_PARENT(node))){ RB_LEFT(RB_PARENT(node)) = m; }else{ RB_RIGHT(RB_PARENT(node)) = m; } }else{ if(!RB_RED(m)) rb_fix(c); } }
/* Note name changed. Guess why :) */ void rb_erase(struct rb_node *elm, struct rb_root *head) { struct rb_node *child, *parent, *old = elm; int color; if (RB_LEFT(elm) == NULL) { child = RB_RIGHT(elm); } else if (RB_RIGHT(elm) == NULL) { child = RB_LEFT(elm); } else { struct rb_node *left; elm = RB_RIGHT(elm); while ((left = RB_LEFT(elm))) { elm = left; } child = RB_RIGHT(elm); parent = RB_PARENT(elm); color = RB_COLOR(elm); if (child) { RB_PARENT(child) = parent; } if (parent) { if (RB_LEFT(parent) == elm) { RB_LEFT(parent) = child; } else { RB_RIGHT(parent) = child; } RB_AUGMENT(parent); } else { RB_HEAD(head) = child; } if (RB_PARENT(elm) == old) { parent = elm; } *(elm) = *(old); if (RB_PARENT(old)) { if (RB_LEFT(RB_PARENT(old)) == old) { RB_LEFT(RB_PARENT(old)) = elm; } else { RB_RIGHT(RB_PARENT(old)) = elm; } RB_AUGMENT(RB_PARENT(old)); } else { RB_HEAD(head) = elm; } RB_PARENT(RB_LEFT(old)) = elm; if (RB_RIGHT(old)) { RB_PARENT(RB_RIGHT(old)) = elm; } if (parent) { left = parent; do { RB_AUGMENT(left); } while ((left = RB_PARENT(left))); } goto color; } parent = RB_PARENT(elm); color = RB_COLOR(elm); if (child) { RB_PARENT(child) = parent; } if (parent) { if (RB_LEFT(parent) == elm) { RB_LEFT(parent) = child; } else { RB_RIGHT(parent) = child; } RB_AUGMENT(parent); } else { RB_HEAD(head) = child; } color: if (color == RB_BLACK) { rb_remove_color(head, parent, child); } }