errval_t mdb_remove(struct cte *target) { MDB_TRACE_ENTER(mdb_root, "%p", target); errval_t err = mdb_subtree_remove(target, &mdb_root, NULL); MDB_TRACE_LEAVE_SUB_RET("%"PRIuPTR, err, mdb_root); }
errval_t mdb_remove(struct cte *target) { MDB_TRACE_ENTER(mdb_root, "%p", target); CHECK_INVARIANTS(mdb_root, target, true); #ifdef IN_KERNEL #ifdef MDB_TRACE_NO_RECURSIVE char prefix[50]; snprintf(prefix, 50, "mdb_remove.%d: ", my_core_id); print_cte(target, prefix); #endif #endif errval_t err = mdb_subtree_remove(target, &mdb_root, NULL); CHECK_INVARIANTS(mdb_root, target, false); MDB_TRACE_LEAVE_SUB_RET("%"PRIuPTR, err, mdb_root); }
static errval_t mdb_subtree_remove(struct cte *target, struct cte **current, struct cte *parent) { assert(current); MDB_TRACE_ENTER(*current, "%p, %p (*%p), %p", target, *current, current, parent); errval_t err; struct cte *current_ = *current; if (!current_) { err = CAPS_ERR_MDB_ENTRY_NOTFOUND; MDB_TRACE_LEAVE_SUB_RET("%"PRIuPTR, err, current_); } int compare = compare_caps(C(target), C(current_), true); if (compare > 0) { err = mdb_subtree_remove(target, &N(current_)->right, current_); if (err != SYS_ERR_OK) { MDB_TRACE_LEAVE_SUB_RET("%"PRIuPTR, err, current_); return err; } } else if (compare < 0) { err = mdb_subtree_remove(target, &N(current_)->left, current_); if (err != SYS_ERR_OK) { MDB_TRACE_LEAVE_SUB_RET("%"PRIuPTR, err, current_); } } else { assert(current_ == target); if (!N(current_)->left && !N(current_)->right) { // target is leaf, just remove *current = NULL; err = SYS_ERR_OK; MDB_TRACE_LEAVE_SUB_RET("%"PRIuPTR, err, NULL); } else if (!N(current_)->left) { // move to right child then go left (dir=-1) // curr, new_right = xchg_rm(elem, parent, current.right, current, -1) struct cte *new_current = NULL; struct cte *new_right = N(current_)->right; mdb_exchange_remove(target, parent, &new_right, current_, -1, &new_current); assert(new_current); current_ = new_current; N(current_)->right = new_right; assert(!mdb_is_reachable(mdb_root, target)); } else { // move to left child then go right (dir=1) // curr, new_left = xchg_rm(elem, parent, current.left, current, 1) struct cte *new_current = NULL; struct cte *new_left = N(current_)->left; mdb_exchange_remove(target, parent, &new_left, current_, 1, &new_current); assert(new_current); current_ = new_current; N(current_)->left = new_left; assert(!mdb_is_reachable(mdb_root, target)); } } // rebalance after remove from subtree current_ = mdb_rebalance(current_); *current = current_; assert(C(target)->type != 0); assert(!*current || C(*current)->type != 0); err = SYS_ERR_OK; MDB_TRACE_LEAVE_SUB_RET("%"PRIuPTR, err, current_); }