[maple_leaf_16] = (1UL << 16) - 1,
[maple_leaf_32] = UINT_MAX,
[maple_leaf_64] = ULONG_MAX,
- [maple_aleaf_64] = ULONG_MAX,
[maple_range_16] = (1UL << 16) - 1,
[maple_range_32] = UINT_MAX,
[maple_range_64] = ULONG_MAX,
[maple_leaf_16] = MAPLE_RANGE16_SLOTS,
[maple_leaf_32] = MAPLE_RANGE32_SLOTS,
[maple_leaf_64] = MAPLE_RANGE64_SLOTS,
- [maple_aleaf_64] = MAPLE_ARANGE64_SLOTS,
[maple_range_16] = MAPLE_RANGE16_SLOTS,
[maple_range_32] = MAPLE_RANGE32_SLOTS,
[maple_range_64] = MAPLE_RANGE64_SLOTS,
[maple_leaf_16] = MAPLE_RANGE16_SLOTS - 1,
[maple_leaf_32] = MAPLE_RANGE32_SLOTS - 1,
[maple_leaf_64] = MAPLE_RANGE64_SLOTS - 1,
- [maple_aleaf_64] = MAPLE_ARANGE64_SLOTS - 1,
[maple_range_16] = MAPLE_RANGE16_SLOTS - 1,
[maple_range_32] = MAPLE_RANGE32_SLOTS - 1,
[maple_range_64] = MAPLE_RANGE64_SLOTS - 1,
{
switch (type) {
case maple_arange_64:
- case maple_aleaf_64:
return mt_to_node(mn)->ma64.pivot[slot];
case maple_range_64:
case maple_leaf_64:
(&mt_to_node(mn)->mr64)->pivot[slot] = val;
break;
case maple_arange_64:
- case maple_aleaf_64:
(&mt_to_node(mn)->ma64)->pivot[slot] = val;
case maple_dense:
break;
case maple_dense:
return rcu_dereference(mt_to_node(mn)->slot[slot]);
case maple_arange_64:
- case maple_aleaf_64:
return rcu_dereference(mt_to_node(mn)->ma64.slot[slot]);
case maple_sparse_6:
return rcu_dereference(mt_to_node(mn)->ms6.slot[slot]);
RCU_INIT_POINTER(mt_to_node(mn)->mr64.slot[slot], val);
break;
case maple_arange_64:
- case maple_aleaf_64:
RCU_INIT_POINTER(mt_to_node(mn)->ma64.slot[slot], val);
break;
}
rcu_assign_pointer(mt_to_node(mn)->slot[slot], val);
break;
case maple_arange_64:
- case maple_aleaf_64:
rcu_assign_pointer(mt_to_node(mn)->ma64.slot[slot], val);
break;
case maple_sparse_6:
}
}
-static inline unsigned long ma_get_gap(const struct maple_enode *mn,
+static inline unsigned long _ma_get_gap(const struct maple_node *mn,
unsigned char gap, enum maple_type type)
{
switch (type) {
case maple_arange_64:
- return mt_to_node(mn)->ma64.gap[gap];
+ return mn->ma64.gap[gap];
default:
return 0;
}
}
+static inline unsigned long ma_get_gap(const struct maple_enode *mn,
+ unsigned char gap)
+{
+ return _ma_get_gap(mt_to_node(mn), gap, mt_node_type(mn));
+}
static inline void ma_set_gap(const struct maple_enode *mn,
unsigned char gap, unsigned long val)
{
static inline void ma_cp_gap(struct maple_enode *dst,
unsigned char dloc, struct maple_enode *src, unsigned long sloc)
{
- ma_set_gap(dst, dloc, ma_get_gap(src, sloc, mt_node_type(src)));
+ ma_set_gap(dst, dloc, ma_get_gap(src, sloc));
}
static inline void mas_update_limits(struct ma_state *ms, unsigned char slot,
if (slot > 0)
ms->min = _ma_get_pivot(ms->node, slot - 1, type) + 1;
- if (slot < mt_slots[type] - 1)
+ if (slot < mt_pivots[type])
ms->max = _ma_get_pivot(ms->node, slot, type);
}
static inline void ma_encoded_parent(struct ma_state *mas)
mas->node = mt_mk_node(gparent, mt_parent_enum(mas, parent));
ma_set_slot(mas, slot);
mas_update_limits(mas, slot, mt_parent_enum(mas, parent));
+ //mas->node = ma_get_rcu_slot(mas->node, slot);
mas->node = ma_get_rcu_slot(mas->node, slot);
return;
}
return data_end;
}
-// FIXME: don't use the same pointers for maple_node and maple_enode
+
static inline unsigned char ma_calc_split(struct ma_state *mas,
struct maple_enode **left, struct maple_enode **right)
{
unsigned long half = mt_slots[type] / 2;
unsigned char data_end = ma_data_end(mas->node, type);
+ if (ma_is_root(mas->node)) {
+ i = half;
+ *left = (struct maple_enode*)ma_next_alloc(mas);
+ *right = (struct maple_enode*)ma_next_alloc(mas);
+ goto even_split;
+ }
+
*left = (struct maple_enode*)ma_next_alloc(mas);
for (i = 0; i < data_end; i++) {
max = ma_get_pivot(mas->node, i);
*left = mt_mk_node(ma_mnode_ptr(*left), type);
*right = mt_mk_node(ma_mnode_ptr(*right), maple_dense);
return j;
- } else {
- *left = mt_mk_node(ma_mnode_ptr(*left), type);
- *right = mt_mk_node(ma_mnode_ptr(*right), type);
}
+even_split:
+ *left = mt_mk_node(ma_mnode_ptr(*left), type);
+ *right = mt_mk_node(ma_mnode_ptr(*right), type);
return i > 2 ? i : half - 1;
}
}
}
+static inline unsigned long ma_leaf_max_gap(struct ma_state *mas)
+{
+ enum maple_type mt = mt_node_type(mas->node);
+ unsigned long max_gap = 0;
+ unsigned long gap = 0;
+ unsigned long pstart, pend;
+
+
+ if (mt == maple_dense) {
+ for (int i = 0; i < mt_slot_count(mas->node); i++) {
+ if (ma_get_rcu_slot(mas->node, i)) {
+ if (gap > max_gap)
+ max_gap = gap;
+ gap = 0;
+ } else {
+ gap++;
+ }
+ }
+ if (gap > max_gap)
+ max_gap = gap;
+ goto done;
+ }
+
+ pstart = mas->min;
+ for (int i = 0; i < mt_slots[mt]; i++) {
+ if (i < mt_pivots[mt])
+ pend = ma_get_pivot(mas->node, i);
+ else
+ pend = mas->max;
+
+ gap = (pend ? pend : mas->max) - pstart;
+ if ((gap > max_gap) && !ma_get_rcu_slot(mas->node, i))
+ max_gap = gap;
+
+ if (!pend)
+ break;
+
+ pstart = pend;
+ }
+done:
+ return max_gap;
+
+}
+static inline unsigned long ma_max_gap(struct ma_state *mas)
+{
+ unsigned long max_gap = 0;
+ for (int i = 0; i < mt_slot_count(mas->node); i++) {
+ unsigned long gap;
+ gap = ma_get_gap(mas->node, i);
+ if ( gap > max_gap)
+ max_gap = gap;
+ }
+ return max_gap;
+}
+static inline void ma_parent_gap(struct ma_state *mas, unsigned char slot,
+ unsigned long new)
+{
+ unsigned long max_gap = 0;
+
+ if (ma_is_root(mas->node)) {
+ ma_set_gap(mas->node, slot, new);
+ return;
+ }
+
+ ma_encoded_parent(mas);
+ max_gap = ma_max_gap(mas);
+ ma_set_gap(mas->node, slot, new);
+
+ if(max_gap < new) {
+ unsigned char pslot = mt_parent_slot(mas->node);
+ ma_parent_gap(mas, pslot, new);
+ }
+}
+/* Private
+ */
+static inline void ma_update_gap(struct ma_state *mas)
+{
+ unsigned char pslot;
+ unsigned long p_gap, max_gap = 0;
+
+
+ if (!mt_is_leaf(mas->node))
+ return;
+
+ if (ma_is_root(mas->node))
+ return;
+
+ /* Get the largest gap in this leaf and check it against the reported
+ * largest.
+ */
+ max_gap = ma_leaf_max_gap(mas);
+ pslot = mt_parent_slot(mas->node);
+ p_gap = _ma_get_gap(mt_parent(mas->node), pslot,
+ mt_parent_enum(mas, mas->node));
+ if (p_gap != max_gap)
+ ma_parent_gap(mas, pslot, max_gap);
+}
+
+
static inline void ma_copy(struct ma_state *mas, struct ma_cp *cp)
{
unsigned char sloc = cp->src_start; // src location
ma_set_pivot(cp->dst, dloc, mas->max);
}
- if (mt_is_alloc(mas->tree))
+ if (mt_node_type(cp->dst) == maple_arange_64)
ma_cp_gap(cp->dst, dloc, cp->src, sloc);
ma_cp_rcu_slot(cp->dst, dloc++, cp->src, sloc++);
}
return;
}
+static inline void ma_gap_link(struct ma_state *mas, struct maple_enode *parent,
+ unsigned char slot, unsigned long pivot)
+{
+ unsigned long gap;
+
+ if (slot)
+ mas->min = ma_get_pivot(parent, slot - 1) + 1;
+
+ mas->max = pivot;
+ if (!mt_is_leaf(mas->node))
+ gap = ma_max_gap(mas);
+ else
+ gap = ma_leaf_max_gap(mas);
+
+ ma_set_gap(parent, slot, gap);
+}
static inline void ma_link(struct maple_enode *new, struct maple_enode *parent,
unsigned char slot, unsigned long pivot, enum maple_type type)
{
// the node type for the children types.
// Node types must be set to copy data into them.
ma_split_data(mas, left, right, split);
-
-
-
if (right) {
- // Set up the link to the right in the new parent
- if (mt_node_type(right) == maple_dense) {
- pivot = ma_get_pivot(mas->node, split)
- + mt_node_max(right) - 1;
- }
- else if (ma_is_root(full)) {
- pivot = mt_node_max(mas->node);
- }
- else {
- pivot = ma_get_pivot(old_parent, p_slot);
- }
-
- ma_link(right, new_parent, p_slot + 1, pivot, ptype);
+ pivot = ma_get_pivot(left, split);
+ } else {
+ pivot = mt_node_max(left);
+ if (p_slot)
+ pivot += ma_get_pivot(new_parent, p_slot - 1);
+ else
+ pivot += mas->min;
}
- // Set up the link to the left in the new parent
- if (!right)
- pivot = mt_node_max(left) - 1;
- else if (split < slot_cnt - 1)
- pivot = ma_get_pivot(mas->node, split);
- else
- pivot = ma_get_pivot(left, split - 1);
ma_link(left, new_parent, p_slot, pivot, ptype);
+ if (right)
+ ma_link(right, new_parent, p_slot + 1, mas->max, ptype);
+
+ if (mt_is_alloc(mas->tree)) {
+ if (right) {
+ unsigned long min = mas->min;
+ mas->node = right;
+ ma_gap_link(mas, new_parent, p_slot + 1, mas->max);
+ mas->min = min;
+ }
+ mas->node = left;
+ ma_gap_link(mas, new_parent, p_slot, pivot);
+ }
// Copy grand parent to the parent, including slot encoding.
mt_to_node(new_parent)->parent = mt_to_node(old_parent)->parent;
ma_adopt_children(new_parent);
// Set up maple state to replace the parent node in the grandparent.
mas->node = new_parent;
+
// Replace the parent node & free the old parent.
mt_replace(mas);
// 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))
+ p_slot = slot - p_slot;
+
if (mas->index <= pivot) {
mas->node = left;
- p_slot = slot - p_slot + 1;
+ p_slot += 1;
+ mas->max = pivot;
} else {
mas->node = right;
- p_slot = slot - p_slot + 2;
+ p_slot += 2;
+ mas->min = pivot;
}
if (mas->index > mt_node_max(mas->node) + mas->min) {
if (old_parent != full)
mt_free(mt_to_node(full));
+
return split;
}
switch (pt) {
case maple_arange_64:
- return maple_aleaf_64;
case maple_range_64:
default:
return maple_leaf_64;
do
ma_update_rcu_slot(mas->node, min++, entry);
while(min < max);
-
- return max - min;
+ if (mt_is_alloc(mas->tree))
+ ma_update_gap(mas);
+ return max - min + 1;
}
/* Calculate the range of the slot */
unsigned long o_min = mas->min;
unsigned long o_max = mas->max;
- if (mt_is_alloc(mas->tree))
- mt = maple_aleaf_64;
-
mas_node_cnt(mas, 1);
if (mas_is_err(mas))
return 0;
wmb();
ma_set_pivot(mas->node, slot, mas->index - 1);
+ if (mt_is_alloc(mas->tree)) {
+ unsigned long gap = mas->min;
+ if (slot > 0)
+ gap = ma_get_pivot(mas->node, slot - 1);
+ gap = (mas->index - 1) - gap;
+ ma_set_gap(mas->node, slot, gap);
+ }
slot += 2;
ret = 2;
} else {
cp.dst_end = n_end;
ma_copy(mas, &cp);
+ //mas->max = mas->last;
+
if (p_mn != mas->node)
mt_replace(mas);
+ if (mt_is_alloc(mas->tree))
+ ma_update_gap(mas);
+
return ret;
}
return;
mn = ma_next_alloc(ms);
- if (mt_is_alloc(ms->tree))
- mt = maple_aleaf_64;
ms->node = mt_mk_node(mn, mt);
mn->parent = ma_parent_ptr(
((unsigned long)ms->tree | MA_ROOT_PARENT));
pr_cont(" contents: ");
for (i = 0; i < MAPLE_ARANGE64_SLOTS; i++)
pr_cont("%lu ", node->gap[i]);
- pr_cont(" | ");
+ pr_cont("| ");
for (i = 0; i < MAPLE_ARANGE64_SLOTS - 1; i++)
pr_cont("%p %lu ", node->slot[i], node->pivot[i]);
pr_cont("%p\n", node->slot[i]);
case maple_dense:
pr_cont("\n");
for (i = 0; i < MAPLE_NODE_SLOTS; i++) {
+ if (min + i > max)
+ pr_cont("OUT OF RANGE: ");
mt_dump_entry(node->slot[i], min + i, min + i);
- if (min + i == max)
- break;
}
break;
case maple_leaf_64:
mt_dump_range64(entry, min, max, depth);
break;
case maple_arange_64:
- case maple_aleaf_64:
mt_dump_arange64(entry, min, max, depth);
break;