RCU_INIT_POINTER(mn->mr64.slot[slot], val);
break;
case maple_arange_64:
+ if (slot >= 5)
+ BUG();
RCU_INIT_POINTER(mn->ma64.slot[slot], val);
break;
}
}
static inline unsigned char mas_cp_calc_split(struct ma_state *mas,
- enum maple_type mas_type, bool append)
+ enum maple_type mas_type, bool append, bool active)
{
unsigned char max = 7, ret = 7;
unsigned char slot;
unsigned long half;
unsigned long piv = 0;
if (mas_type == maple_arange_64)
- max = 3;
+ max = 5;
- if (mas->min == 0)
- max = 7;
+ if (!active) {
+ if (ma_is_leaf(mas_type))
+ return max;
+ return max - 2;
+ }
+
+ //if (mas->min == 0)
+ // max = 7;
half = max / 2;
if (ma_is_leaf(mas_type)) {
}
} else
+
return half;
done:
if (ret < max && (append || piv == ULONG_MAX))
ret++;
+
return ret;
}
static inline unsigned long mas_leaf_max_gap(struct ma_state *mas);
unsigned char p_slot, struct ma_state *left,
struct ma_state *right, struct maple_node *mn,
enum maple_type mn_type, unsigned long mn_min,
- int entry_cnt, void *entry, unsigned char dst_start)
+ int entry_cnt, void *entry, unsigned char dst_start,
+ bool active)
{
enum maple_type mas_type = mte_node_type(mas->node);
struct maple_node *parent = mte_to_node(mas->node);
if (ma_is_leaf(mas_type))
attempt_insert = true;
-
if (right)
- split = mas_cp_calc_split(mas, mas_type, append);
+ split = mas_cp_calc_split(mas, mas_type, append, active);
if (left) {
mas_dup_state(&cp, left);
mn_type = mte_node_type(cp.node);
p_slot = mte_parent_slot(left->node);
parent = mte_parent(left->node);
- mas_type = mas_parent_enum(mas, left->node);
+ mas_type = mas_parent_enum(left, left->node);
}
if (!entry_cnt)
if (!appending) {
if (mt_will_coalesce(existing)) {
- if (prev_null) {
+ if (prev_null && piv[2] < cp.index) {
if (slot &&
slot - 1 < mt_pivots[mas_type]) {
ma_set_pivot(mn, slot - 1,
mas_type, piv[2]);
written_piv = piv[2];
}
- if (update_gaps) {
+ if (update_gaps && entry_cnt >= 0) {
mas_ma_update_gap(mas, mas_type,
mn, mn_type, piv[2],
written_piv, src_slot,
goto skip_src_slot;
}
- if (ma_is_leaf(mn_type) &&
- (append || (attempt_insert && cp.index <= piv[2]))) {
+ if ((append || (attempt_insert && cp.index <= piv[2]))) {
i = 0;
if (written_piv == cp.index - 1) {
i = 1; // previous pivot matches exactly.
- }
- else if (!src_slot && written_piv == cp.index)
+ } else if (!src_slot && written_piv == cp.index)
i = 1;
if (appending)
src_slot++;
} while ((entry_cnt-- > 0) || attempt_insert);
- if (right && update_gaps)
+ if (right && update_gaps && p_slot < mt_slots[mas_type])
parent->ma64.gap[p_slot] = max_gap;
else if (!right)
ret = slot - 1;
mas_dup_state(&parent, mas);
mas_ascend(&parent);
old_parent = parent.node;
- ptype = mte_node_type(parent.node);
+ ptype = mas_parent_enum(mas, mas->node);
p_end = mas_data_end(&parent, ptype, &last_pivot, &coalesce);
if (p_end - coalesce >= mt_slots[ptype] - 1) {
/* Must split the parent */
return 0;
mas_dup_state(&parent, mas);
- if (split < p_slot)
+ if (split <= p_slot)
p_slot -= split;
// Split will return the parent.
old_parent = parent.node;
mas_set_slot(&parent, p_slot);
}
- ptype = mte_node_type(parent.node);
+ ptype = mas_parent_enum(mas, mas->node);
p_end = mas_data_end(&parent, ptype, &last_pivot, &coalesce);
mas_dup_state(mas, &parent);
mas_set_slot(mas, p_slot);
left.node = mt_mk_node(ma_mnode_ptr(mas_next_alloc(mas)), type);
right.node = mt_mk_node(ma_mnode_ptr(mas_next_alloc(mas)), type);
- mte_set_parent(left.node, mte_to_node(new_parent), p_slot);
- mte_set_parent(right.node, mte_to_node(new_parent), p_slot+1);
+ mte_set_parent(left.node, new_parent, p_slot);
+ mte_set_parent(right.node, new_parent, p_slot+1);
// split the data into left & right and do the insert.
split = mas_ma_cp(mas, p_slot, &left, &right, NULL, type, 0, entry_cnt,
- entry, 0);
+ entry, 0, active);
// Copy the parents information
if (!mte_is_root(full)) {
- MA_CP(cp, old_parent, new_parent, 0, p_slot - 1);
unsigned char skip = 1;
+ MA_CP(cp, old_parent, new_parent, 0, p_slot - 1);
// Copy the parent data up to p_slot - 1.
if (p_slot)
// Set up the ma_state for the return. Point to the correct node for
// the insert or subsequent split.
- if (!mt_is_alloc(mas->tree)) // FIXME: citation needed.
- p_slot = slot - p_slot;
+// if (!mt_is_alloc(mas->tree)) // FIXME: Something to do with leaf size
+// p_slot = slot - p_slot;
if (mas->index <= left.max) {
mas_dup_state(mas, &left);
}
// Free the full node, this may have happened in _mas_replace
- if (old_parent != full) {
+ if (old_parent != full) { // not root?
if (!active)
mas_push_node(mas, full);
else
mte_free(full);
}
+ //mt_dump(mas->tree);
return split;
}
}
ret = mas_ma_cp(mas, 0, &cp, NULL, mn, mas_type, mn_min, entry_cnt, entry,
- append ? entry_cnt : 0);
+ append ? entry_cnt : 0, active);
mn->parent = mas_mn(mas)->parent;
// FIXME: Propagate gaps.
// At this point, the we can perform the add.
// spans node means we will replace the tree.
- if (mas->last > mas->max)
+ if (mas->last > mas->max) {
+ //printk("Spans node %p (%lu - %lu) vs %lu - %lu\n", mas_mn(mas),
+ // mas->min, mas->max, mas->index, mas->last);
return mas_replace_tree(mas, entry);
+ }
if (!mte_is_leaf(mas->node)) {
// An allocation failed previously during a rebalance. There
// is no way to know how broken things are, so try to rebuild
// the tree.
+ printk("Allocation failed previously\n");
+ printk("%ld-%ld landed at %p[%u]\n", mas->index, mas->last,
+ mas_mn(mas), mas_get_slot(mas));
mas_reset(mas);
mas_first_node(mas, ULONG_MAX);
return mas_replace_tree(mas, entry);
new_end = _mas_add_slot_cnt(mas, slot, min, max) - coalesce;
if (new_end > slot_cnt) {
mas_split(mas, slot, active, old_end, entry);
- if (mas_is_err(mas)) {
+ if (mas_is_err(mas))
return 0;
- }
+
return old_end - new_end;
}
// Restart search for where to insert.
mas->node = MAS_START;
mas_start(mas);
- mas_add(mas, entry, false, false);
+ mas_add(mas, entry, true, false);
}
static inline void mas_insert(struct ma_state *mas, void *entry)
{
rcu_assign_pointer(mas->tree->ma_root, mte_mk_root(mas->node));
}
-static inline int mas_safe_slot(struct ma_state *mas, unsigned char *slot,
- int delta);
+static inline int mas_safe_slot(struct ma_state *mas, int *slot, int delta);
static inline int mas_dead_node(struct ma_state *mas, unsigned long index);
static inline void mas_next_slot(struct ma_state *mas, unsigned long max)
static inline void mas_prev_node(struct ma_state *mas, unsigned long limit)
{
int level;
- unsigned char slot;
+ int slot;
unsigned long start_piv;
slot = mas_get_slot(mas);
level--;
mas->node = mn;
slot = mas_data_end(mas, mte_node_type(mn), &last_pivot,
- &coalesce);
+ &coalesce) + 1;
} while (slot-- > 0);
ascend:
restart_next_node:
level = 0;
while (1) {
- unsigned char count, slot;
+ unsigned char count;
+ int slot;
struct maple_enode *mn;
unsigned long prev_piv;
start_piv = mas_get_safe_pivot(mas, slot);
level++;
mas_ascend(mas);
+ //printk("Ascend to %p[%u]\n", mas_mn(mas), slot);
- if (!mas_safe_slot(mas, &slot, 1)) {
- if (mte_is_root(mas->node))
- goto no_entry;
- goto restart_next_node;
- }
+ if (!mas_safe_slot(mas, &slot, 1))
+ goto ascend;
if (mas_dead_node(mas, start_piv))
goto restart_next_node;
count = mt_slot_count(mas->node);
prev_piv = mas_get_safe_pivot(mas, slot);
+ //printk("while with %p[%u]\n", mas_mn(mas), slot);
while (++slot < count) {
unsigned long pivot = mas_get_safe_pivot(mas, slot);
+ //printk("Checking %p[%u]\n", mas_mn(mas), slot);
if (prev_piv > max)
goto no_entry;
count = mt_slot_count(mas->node);
}
+ascend:
if (mte_is_root(mas->node))
goto no_entry;
mas_set_slot(mas, mte_parent_slot(mas->node));
+ //printk("Set parent slot to %u from %p\n", mas_get_slot(mas), mas_mn(mas));
}
no_entry:
goto next_node;
if (!mte_is_leaf(mas->node) || !mas_get_slot(mas)) {
+ //printk("Get first entry\n");
*range_start = mas_first_entry(mas, limit);
if (mas_is_none(mas)) {
mas->node = last_node;
return NULL;
next_node:
+ //printk("Next node from %p\n", mas_mn(mas));
p_slot = mte_parent_slot(mas->node);
mas_set_slot(mas, p_slot);
mas_next_node(mas, limit);
+ //printk("Next node is %p\n", mas->node);
mas_set_slot(mas, 0);
}
return NULL;
if (!mas->node || mas_is_start(mas)) {// First run.
+ //printk("First run\n");
*range_start = 0;
mas_start(mas);
+ //printk("start returned %p %p\n", mas->node, mas_mn(mas));
entry = mas_range_load(mas, range_start, &range_max);
}
if (entry)
return entry;
+ //printk("__mas_next with %p\n", mas_mn(mas));
return __mas_next(mas, limit, range_start);
}
dst.index = src->min;
dst.max = src->max;
while (slot <= count ) {
+// printk("\t%s: %p[%u]/%u to %p[%u]\n", __func__, mas_mn(src),
+// slot, count, mas_mn(&dst), dst_cnt);
void *entry = mte_get_rcu_slot(src->node, slot);
dst.last = mas_get_safe_pivot(src, slot);
if (mt_is_empty(entry) && dst.last != ULONG_MAX)
dst_cnt = mas_ma_cp(src, 0, &dst, NULL, mas_mn(&dst), mas_type,
dst.min, slot,
- entry, dst_cnt);
+ entry, dst_cnt, false);
next:
- dst.index = dst.last+1;
+ dst.index = dst.last + 1;
slot++;
}
if (retry) {
struct ma_cp *cp)
{
struct maple_node *mn;
- bool ret = false;
+ bool free_left = false;
MA_STATE(dst, mas->tree, mas->index, mas->last);
// it is possible that all of the right node can be appended to the
- // left
- if (total_slots + 1 - l_end_slot < mt_slots[l_type] - l_end_slot) {
- mas_cp_append(mas, r_mas, p_mas, l_end_slot, r_end_slot, false);
- mte_set_rcu_slot(p_mas->node, mte_parent_slot(r_mas->node),
- XA_SKIP_ENTRY);
- mte_free(r_mas->node);
- goto done;
- }
+ // left.
+ if (total_slots + 1 - l_end_slot < mt_slots[l_type] - l_end_slot)
+ goto use_left;
- mas_node_cnt(mas, 1); // Try to allocate.
+ mas_node_cnt(mas, 1); // ensure we have a node, or allocate one.
if (mas_is_err(mas)) {
// Allocation failed, we could try to append as much
// as possible here?
return false;
}
-
+ free_left = true;
mn = mas_next_alloc(mas);
mas_dup_state(&dst, mas);
mn->parent = mas_mn(mas)->parent;
l_end_slot++;
}
mas->node = dst.node;
- // FIXME: Broken.
- mas_cp_append(mas, r_mas, p_mas, l_end_slot, r_end_slot, true);
- ret = true;
-done:
+
+use_left:
+ mas_cp_append(mas, r_mas, p_mas, l_end_slot, r_end_slot, false);
+
if (!mte_is_leaf(mas->node))
mte_adopt_children(mas->node);
mte_set_pivot(p_mas->node, mte_parent_slot(mas->node), r_mas->max);
- return ret;
+ mte_set_rcu_slot(p_mas->node, mte_parent_slot(r_mas->node),
+ XA_SKIP_ENTRY);
+ mte_free(r_mas->node);
+ return free_left;
}
/** Private
mte_adopt_children(mas->node);
if (free)
mas_replace(mas);
+ //mt_dump(mas->tree);
// Check parent for rebalancing.
mas_dup_state(mas, &p_mas);
goto start;
* Skip any slots that have special values.
* If the limit of the slot is hit, then return false.
*/
-static inline int mas_safe_slot(struct ma_state *mas, unsigned char *slot,
+static inline int mas_safe_slot(struct ma_state *mas, int *slot,
int delta)
{
unsigned char max = mt_slot_count(mas->node);
if (0 > delta)
limit = 0;
while (*slot != limit) {
- if (!mt_is_empty(mte_get_rcu_slot(mas->node, *slot + delta)))
+ void *entry;
+ //printk("Checking safe slot %d\n", *slot + delta);
+ if (!mas_get_safe_pivot(mas, (*slot) + delta))
+ return false;
+
+ entry = mte_get_rcu_slot(mas->node, (*slot) + delta);
+ //printk("slot type %u %p[%u] has %p\n", mte_node_type(mas->node), mas_mn(mas), *slot + delta, entry);
+ if (!mt_is_empty(entry))
return true;
*slot += delta;
}
struct maple_enode *last = NULL;
unsigned long new_index, new_last;
unsigned long r_index, r_last;
+ struct maple_tree new_tree = MTREE_INIT(name, mas->tree->ma_flags);
void *entry;
- DEFINE_MTREE(new_tree);
MA_STATE(new_mas, &new_tree, 0, 0);
return 0;
node_cnt += 3; // Room for an extra split.
+ //printk("Getting %ld nodes\n", node_cnt);
mas_node_cnt(mas, node_cnt);
if (mas_is_err(mas))
return 0;
mas_reset(mas);
mas->index = 0;
mas->last = 0;
+ //printk("Start left\n");
mas_for_each(mas, entry, new_index - 1) {
new_mas.index = mas->index;
new_mas.last = mas_get_safe_pivot(mas, mas_get_slot(mas));
BUG_ON(1);
ma_inactive_insert(&new_mas, entry);
if (mas_is_err(&new_mas)) {
+ //mt_dump(new_mas.tree);
goto error;
}
}
+ //printk("Done\n");
// Insert the new value.
new_mas.index = new_index;
* - new_mas.last goes beyond anything right now (no entries)
* - new_mas.last cuts a range
* - new_mas.last ends in a null
- * - new_mas.last has a sequentially next value (48)
+ * - new_mas.last has a sequentially next value
*/
mas_reset(mas);
- mas->index = new_last+1;
- mas->last = new_last+1;
+ mas->index = new_last + 1;
+ mas->last = new_last + 1;
_mas_range_walk(mas, &r_index, &r_last);
if (mas_get_slot(mas) == MAPLE_NODE_SLOTS)
}
}
+ //printk("Start right from %lu\n", mas->index);
+ //mt_dump(new_mas.tree);
mas_for_each(mas, entry, ULONG_MAX) {
if (mas->index < new_index)
continue;
if (mas_is_err(&new_mas))
goto error;
}
+ //printk("Done\n");
skip_right:
error:
if (new_mas.tree)
mte_destroy_walk(new_mas.tree->ma_root);
- printk("Failed on %lu-%lu\n", mas->index, mas->last);
+ //printk("Failed on %lu-%lu\n", mas->index, mas->last);
mt_dump(mas->tree);
BUG_ON(1);
return 0;
mt_dump_entry(node->slot[i], first, last, depth + 1);
else if (xa_is_skip(node->slot[i]))
mt_dump_entry(node->slot[i], first, last, depth + 1);
+ else if (xa_is_retry(node->slot[i]))
+ mt_dump_entry(node->slot[i], first, last, depth + 1);
else if (node->slot[i])
mt_dump_node(node->slot[i], first, last, depth + 1);